home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / var / lib / python-support / python2.4 / xdg / IconTheme.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  13.2 KB  |  474 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''
  5. Complete implementation of the XDG Icon Spec Version 0.8
  6. http://standards.freedesktop.org/icon-theme-spec/
  7. '''
  8. import os
  9. import sys
  10. import time
  11. from xdg.IniFile import *
  12. from xdg.BaseDirectory import *
  13. from xdg.Exceptions import *
  14. import xdg.Config as xdg
  15.  
  16. class IconTheme(IniFile):
  17.     '''Class to parse and validate IconThemes'''
  18.     
  19.     def __init__(self):
  20.         IniFile.__init__(self)
  21.  
  22.     
  23.     def __repr__(self):
  24.         return self.name
  25.  
  26.     
  27.     def parse(self, file):
  28.         IniFile.parse(self, file, [
  29.             'Icon Theme',
  30.             'KDE Icon Theme'])
  31.         self.dir = os.path.dirname(file)
  32.         (nil, self.name) = os.path.split(self.dir)
  33.  
  34.     
  35.     def getDir(self):
  36.         return self.dir
  37.  
  38.     
  39.     def getName(self):
  40.         return self.get('Name', locale = True)
  41.  
  42.     
  43.     def getComment(self):
  44.         return self.get('Comment', locale = True)
  45.  
  46.     
  47.     def getInherits(self):
  48.         return self.get('Inherits', list = True)
  49.  
  50.     
  51.     def getDirectories(self):
  52.         return self.get('Directories', list = True)
  53.  
  54.     
  55.     def getHidden(self):
  56.         return self.get('Hidden', type = 'boolean')
  57.  
  58.     
  59.     def getExample(self):
  60.         return self.get('Example')
  61.  
  62.     
  63.     def getSize(self, directory):
  64.         return self.get('Size', type = 'integer', group = directory)
  65.  
  66.     
  67.     def getContext(self, directory):
  68.         return self.get('Context', group = directory)
  69.  
  70.     
  71.     def getType(self, directory):
  72.         value = self.get('Type', group = directory)
  73.         if value:
  74.             return value
  75.         else:
  76.             return 'Threshold'
  77.  
  78.     
  79.     def getMaxSize(self, directory):
  80.         value = self.get('MaxSize', type = 'integer', group = directory)
  81.         if value or value == 0:
  82.             return value
  83.         else:
  84.             return self.getSize(directory)
  85.  
  86.     
  87.     def getMinSize(self, directory):
  88.         value = self.get('MinSize', type = 'integer', group = directory)
  89.         if value or value == 0:
  90.             return value
  91.         else:
  92.             return self.getSize(directory)
  93.  
  94.     
  95.     def getThreshold(self, directory):
  96.         value = self.get('Threshold', type = 'integer', group = directory)
  97.         if value or value == 0:
  98.             return value
  99.         else:
  100.             return 2
  101.  
  102.     
  103.     def checkExtras(self):
  104.         if self.defaultGroup == 'KDE Icon Theme':
  105.             self.warnings.append('[KDE Icon Theme]-Header is deprecated')
  106.         
  107.         if self.fileExtension == '.theme':
  108.             pass
  109.         elif self.fileExtension == '.desktop':
  110.             self.warnings.append('.desktop fileExtension is deprecated')
  111.         else:
  112.             self.warnings.append('Unknown File extension')
  113.         
  114.         try:
  115.             self.name = self.content[self.defaultGroup]['Name']
  116.         except KeyError:
  117.             self.errors.append("Key 'Name' is missing")
  118.  
  119.         
  120.         try:
  121.             self.comment = self.content[self.defaultGroup]['Comment']
  122.         except KeyError:
  123.             self.errors.append("Key 'Comment' is missing")
  124.  
  125.         
  126.         try:
  127.             self.directories = self.content[self.defaultGroup]['Directories']
  128.         except KeyError:
  129.             self.errors.append("Key 'Directories' is missing")
  130.  
  131.  
  132.     
  133.     def checkGroup(self, group):
  134.         if group == self.defaultGroup:
  135.             pass
  136.         elif group in self.getDirectories():
  137.             
  138.             try:
  139.                 self.type = self.content[group]['Type']
  140.             except KeyError:
  141.                 self.type = 'Threshold'
  142.  
  143.             
  144.             try:
  145.                 self.name = self.content[group]['Name']
  146.             except KeyError:
  147.                 self.errors.append("Key 'Name' in Group '%s' is missing" % group)
  148.             except:
  149.                 None<EXCEPTION MATCH>KeyError
  150.             
  151.  
  152.         None<EXCEPTION MATCH>KeyError
  153.         if not re.match('^\\[X-', group) and group.decode('utf-8', 'ignore').encode('ascii', 'ignore') == group:
  154.             self.errors.append('Invalid Group name: %s' % group)
  155.         
  156.  
  157.     
  158.     def checkKey(self, key, value, group):
  159.         if group == self.defaultGroup:
  160.             if re.match('^Name' + xdg.Locale.regex + '$', key):
  161.                 pass
  162.             elif re.match('^Comment' + xdg.Locale.regex + '$', key):
  163.                 pass
  164.             elif key == 'Inherits':
  165.                 self.checkValue(key, value, list = True)
  166.             elif key == 'Directories':
  167.                 self.checkValue(key, value, list = True)
  168.             elif key == 'Hidden':
  169.                 self.checkValue(key, value, type = 'boolean')
  170.             elif key == 'Example':
  171.                 self.checkValue(key, value)
  172.             elif re.match('^X-[a-zA-Z0-9-]+', key):
  173.                 pass
  174.             else:
  175.                 self.errors.append('Invalid key: %s' % key)
  176.         elif group in self.getDirectories():
  177.             if key == 'Size':
  178.                 self.checkValue(key, value, type = 'integer')
  179.             elif key == 'Context':
  180.                 self.checkValue(key, value)
  181.             elif key == 'Type':
  182.                 self.checkValue(key, value)
  183.                 if value not in [
  184.                     'Fixed',
  185.                     'Scalable',
  186.                     'Threshold']:
  187.                     self.errors.append("Key 'Type' must be one out of 'Fixed','Scalable','Threshold', but is %s" % value)
  188.                 
  189.             elif key == 'MaxSize':
  190.                 self.checkValue(key, value, type = 'integer')
  191.                 if self.type != 'Scalable':
  192.                     self.errors.append("Key 'MaxSize' give, but Type is %s" % self.type)
  193.                 
  194.             elif key == 'MinSize':
  195.                 self.checkValue(key, value, type = 'integer')
  196.                 if self.type != 'Scalable':
  197.                     self.errors.append("Key 'MinSize' give, but Type is %s" % self.type)
  198.                 
  199.             elif key == 'Threshold':
  200.                 self.checkValue(key, value, type = 'integer')
  201.                 if self.type != 'Threshold':
  202.                     self.errors.append("Key 'Threshold' give, but Type is %s" % self.type)
  203.                 
  204.             elif re.match('^X-[a-zA-Z0-9-]+', key):
  205.                 pass
  206.             else:
  207.                 self.errors.append('Invalid key: %s' % key)
  208.         
  209.  
  210.  
  211.  
  212. class IconData(IniFile):
  213.     '''Class to parse and validate IconData Files'''
  214.     
  215.     def __init__(self):
  216.         IniFile.__init__(self)
  217.  
  218.     
  219.     def __repr__(self):
  220.         return self.getDisplayName()
  221.  
  222.     
  223.     def parse(self, file):
  224.         IniFile.parse(self, file, [
  225.             'Icon Data'])
  226.  
  227.     
  228.     def getDisplayName(self):
  229.         return self.get('DisplayName', locale = True)
  230.  
  231.     
  232.     def getEmbeddedTextRectangle(self):
  233.         return self.get('EmbeddedTextRectangle', list = True)
  234.  
  235.     
  236.     def getAttachPoints(self):
  237.         return self.get('AttachPoints', type = 'point', list = True)
  238.  
  239.     
  240.     def checkExtras(self):
  241.         if self.fileExtension != '.icon':
  242.             self.warnings.append('Unknown File extension')
  243.         
  244.  
  245.     
  246.     def checkGroup(self, group):
  247.         if not group == self.defaultGroup and re.match('^\\[X-', group) and group.encode('ascii', 'ignore') == group:
  248.             self.errors.append('Invalid Group name: %s' % group.encode('ascii', 'replace'))
  249.         
  250.  
  251.     
  252.     def checkKey(self, key, value, group):
  253.         if re.match('^DisplayName' + xdg.Locale.regex + '$', key):
  254.             pass
  255.         elif key == 'EmbeddedTextRectangle':
  256.             self.checkValue(key, value, type = 'integer', list = True)
  257.         elif key == 'AttachPoints':
  258.             self.checkValue(key, value, type = 'point', list = True)
  259.         elif re.match('^X-[a-zA-Z0-9-]+', key):
  260.             pass
  261.         else:
  262.             self.errors.append('Invalid key: %s' % key)
  263.  
  264.  
  265. icondirs = []
  266. for basedir in xdg_data_dirs:
  267.     icondirs.append(os.path.join(basedir, 'icons'))
  268.  
  269. icondirs.append('/usr/share/pixmaps')
  270. icondirs.append(os.path.expanduser('~/.icons'))
  271. themes = []
  272. cache = dict()
  273. dache = dict()
  274. eache = dict()
  275.  
  276. def getIconPath(iconname, size = None, theme = None, extensions = [
  277.     'png',
  278.     'svg',
  279.     'xpm']):
  280.     global themes
  281.     if size == None:
  282.         size = xdg.Config.icon_size
  283.     
  284.     if theme == None:
  285.         theme = xdg.Config.icon_theme
  286.     
  287.     if os.path.isabs(iconname):
  288.         return iconname
  289.     
  290.     if os.path.splitext(iconname)[1][1:] in extensions:
  291.         iconname = os.path.splitext(iconname)[0]
  292.     
  293.     
  294.     try:
  295.         if themes[0].name != theme:
  296.             themes = []
  297.             __addTheme(theme)
  298.     except IndexError:
  299.         __addTheme(theme)
  300.  
  301.     tmp = ''.join([
  302.         iconname,
  303.         str(size),
  304.         theme,
  305.         ''.join(extensions)])
  306.     if eache.has_key(tmp):
  307.         if int(time.time() - eache[tmp][0]) >= xdg.Config.cache_time:
  308.             del eache[tmp]
  309.         else:
  310.             return eache[tmp][1]
  311.     
  312.     for thme in themes:
  313.         icon = LookupIcon(iconname, size, thme, extensions)
  314.         if icon:
  315.             eache[tmp] = [
  316.                 time.time(),
  317.                 icon]
  318.             return icon
  319.             continue
  320.     
  321.     for directory in icondirs:
  322.         if (not dache.has_key(directory) or int(time.time() - dache[directory][1]) >= xdg.Config.cache_time or dache[directory][2] < os.path.getmtime(directory)) and os.path.isdir(directory):
  323.             dache[directory] = [
  324.                 os.listdir(directory),
  325.                 time.time(),
  326.                 os.path.getmtime(directory)]
  327.             continue
  328.     
  329.     for dir, values in dache.items():
  330.         for extension in extensions:
  331.             
  332.             try:
  333.                 if iconname + '.' + extension in values[0]:
  334.                     icon = os.path.join(dir, iconname + '.' + extension)
  335.                     eache[tmp] = [
  336.                         time.time(),
  337.                         icon]
  338.                     return icon
  339.             continue
  340.             except UnicodeDecodeError:
  341.                 continue
  342.             
  343.  
  344.         
  345.     
  346.     if theme != 'hicolor':
  347.         icon = getIconPath(iconname, size, 'hicolor')
  348.         eache[tmp] = [
  349.             time.time(),
  350.             icon]
  351.         return icon
  352.     
  353.  
  354.  
  355. def getIconData(path):
  356.     if os.path.isfile(path):
  357.         dirname = os.path.dirname(path)
  358.         basename = os.path.basename(path)
  359.         if os.path.isfile(os.path.join(dirname, basename + '.icon')):
  360.             data = IconData()
  361.             data.parse(os.path.join(dirname, basename + '.icon'))
  362.             return data
  363.         
  364.     
  365.  
  366.  
  367. def __addTheme(theme):
  368.     for dir in icondirs:
  369.         if os.path.isfile(os.path.join(dir, theme, 'index.theme')):
  370.             __parseTheme(os.path.join(dir, theme, 'index.theme'))
  371.             break
  372.             continue
  373.         if os.path.isfile(os.path.join(dir, theme, 'index.desktop')):
  374.             __parseTheme(os.path.join(dir, theme, 'index.desktop'))
  375.             break
  376.             continue
  377.     elif debug:
  378.         raise NoThemeError(theme)
  379.     
  380.  
  381.  
  382. def __parseTheme(file):
  383.     theme = IconTheme()
  384.     theme.parse(file)
  385.     themes.append(theme)
  386.     for subtheme in theme.getInherits():
  387.         __addTheme(subtheme)
  388.     
  389.  
  390.  
  391. def LookupIcon(iconname, size, theme, extensions):
  392.     if not cache.has_key(theme.name):
  393.         cache[theme.name] = []
  394.         cache[theme.name].append(time.time() - (xdg.Config.cache_time + 1))
  395.         cache[theme.name].append(0)
  396.         cache[theme.name].append(dict())
  397.     
  398.     if int(time.time() - cache[theme.name][0]) >= xdg.Config.cache_time:
  399.         cache[theme.name][0] = time.time()
  400.         for subdir in theme.getDirectories():
  401.             for directory in icondirs:
  402.                 dir = os.path.join(directory, theme.name, subdir)
  403.                 if (not cache[theme.name][2].has_key(dir) or cache[theme.name][1] < os.path.getmtime(os.path.join(directory, theme.name))) and subdir != '' and os.path.isdir(dir):
  404.                     cache[theme.name][2][dir] = [
  405.                         subdir,
  406.                         os.listdir(dir)]
  407.                     cache[theme.name][1] = os.path.getmtime(os.path.join(directory, theme.name))
  408.                     continue
  409.             
  410.         
  411.     
  412.     for dir, values in cache[theme.name][2].items():
  413.         if DirectoryMatchesSize(values[0], size, theme):
  414.             for extension in extensions:
  415.                 if iconname + '.' + extension in values[1]:
  416.                     return os.path.join(dir, iconname + '.' + extension)
  417.                     continue
  418.             
  419.     
  420.     minimal_size = sys.maxint
  421.     closest_filename = ''
  422.     for dir, values in cache[theme.name][2].items():
  423.         distance = DirectorySizeDistance(values[0], size, theme)
  424.         if distance < minimal_size:
  425.             for extension in extensions:
  426.                 if iconname + '.' + extension in values[1]:
  427.                     closest_filename = os.path.join(dir, iconname + '.' + extension)
  428.                     minimal_size = distance
  429.                     continue
  430.             
  431.     
  432.     return closest_filename
  433.  
  434.  
  435. def DirectoryMatchesSize(subdir, iconsize, theme):
  436.     Type = theme.getType(subdir)
  437.     Size = theme.getSize(subdir)
  438.     Threshold = theme.getThreshold(subdir)
  439.     MinSize = theme.getMinSize(subdir)
  440.     MaxSize = theme.getMaxSize(subdir)
  441.     if Type == 'Fixed':
  442.         return Size == iconsize
  443.     elif Type == 'Scaleable':
  444.         return None if iconsize <= iconsize else iconsize <= MaxSize
  445.     elif Type == 'Threshold':
  446.         return None if iconsize <= iconsize else iconsize <= Size + Threshold
  447.     
  448.  
  449.  
  450. def DirectorySizeDistance(subdir, iconsize, theme):
  451.     Type = theme.getType(subdir)
  452.     Size = theme.getSize(subdir)
  453.     Threshold = theme.getThreshold(subdir)
  454.     MinSize = theme.getMinSize(subdir)
  455.     MaxSize = theme.getMaxSize(subdir)
  456.     if Type == 'Fixed':
  457.         return abs(Size - iconsize)
  458.     elif Type == 'Scalable':
  459.         if iconsize < MinSize:
  460.             return MinSize - iconsize
  461.         elif iconsize > MaxSize:
  462.             return MaxSize - iconsize
  463.         
  464.         return 0
  465.     elif Type == 'Threshold':
  466.         if iconsize < Size - Threshold:
  467.             return MinSize - iconsize
  468.         elif iconsize > Size + Threshold:
  469.             return iconsize - MaxSize
  470.         
  471.         return 0
  472.     
  473.  
  474.