home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / xdg / Menu.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  33.9 KB  |  1,301 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. Implementation of the XDG Menu Specification Version 1.0.draft-1
  6. http://standards.freedesktop.org/menu-spec/
  7. '''
  8. from __future__ import generators
  9. import locale
  10. import os
  11. import xml.dom.minidom as xml
  12. from xdg.BaseDirectory import *
  13. from xdg.DesktopEntry import *
  14. from xdg.Exceptions import *
  15. import xdg.Locale as xdg
  16. import xdg.Config as xdg
  17. ELEMENT_NODE = xml.dom.Node.ELEMENT_NODE
  18.  
  19. class Menu:
  20.     
  21.     def __init__(self):
  22.         self.Name = ''
  23.         self.Directory = None
  24.         self.Entries = []
  25.         self.Doc = ''
  26.         self.Filename = ''
  27.         self.Depth = 0
  28.         self.Parent = None
  29.         self.NotInXml = False
  30.         self.Show = True
  31.         self.Visible = 0
  32.         self.AppDirs = []
  33.         self.DefaultLayout = None
  34.         self.Deleted = 'notset'
  35.         self.Directories = []
  36.         self.DirectoryDirs = []
  37.         self.Layout = None
  38.         self.MenuEntries = []
  39.         self.Moves = []
  40.         self.OnlyUnallocated = 'notset'
  41.         self.Rules = []
  42.         self.Submenus = []
  43.  
  44.     
  45.     def __str__(self):
  46.         return self.Name
  47.  
  48.     
  49.     def __add__(self, other):
  50.         for dir in other.AppDirs:
  51.             self.AppDirs.append(dir)
  52.         
  53.         for dir in other.DirectoryDirs:
  54.             self.DirectoryDirs.append(dir)
  55.         
  56.         for directory in other.Directories:
  57.             self.Directories.append(directory)
  58.         
  59.         if other.Deleted != 'notset':
  60.             self.Deleted = other.Deleted
  61.         
  62.         if other.OnlyUnallocated != 'notset':
  63.             self.OnlyUnallocated = other.OnlyUnallocated
  64.         
  65.         if other.Layout:
  66.             self.Layout = other.Layout
  67.         
  68.         if other.DefaultLayout:
  69.             self.DefaultLayout = other.DefaultLayout
  70.         
  71.         for rule in other.Rules:
  72.             self.Rules.append(rule)
  73.         
  74.         for move in other.Moves:
  75.             self.Moves.append(move)
  76.         
  77.         for submenu in other.Submenus:
  78.             self.addSubmenu(submenu)
  79.         
  80.         return self
  81.  
  82.     
  83.     def __cmp__(self, other):
  84.         return locale.strcoll(self.getName(), other.getName())
  85.  
  86.     
  87.     def __eq__(self, other):
  88.         if self.Name == str(other):
  89.             return True
  90.         return False
  91.  
  92.     
  93.     def getEntries(self, hidden = False):
  94.         for entry in self.Entries:
  95.             if hidden == True:
  96.                 yield entry
  97.                 continue
  98.             if entry.Show == True:
  99.                 yield entry
  100.                 continue
  101.         
  102.  
  103.     
  104.     def getMenuEntry(self, desktopfileid, deep = False):
  105.         for menuentry in self.MenuEntries:
  106.             if menuentry.DesktopFileID == desktopfileid:
  107.                 return menuentry
  108.         
  109.         if deep == True:
  110.             for submenu in self.Submenus:
  111.                 submenu.getMenuEntry(desktopfileid, deep)
  112.             
  113.         
  114.  
  115.     
  116.     def getMenu(self, path):
  117.         array = path.split('/', 1)
  118.         for submenu in self.Submenus:
  119.             if submenu.Name == array[0]:
  120.                 if len(array) > 1:
  121.                     return submenu.getMenu(array[1])
  122.                 return submenu
  123.             submenu.Name == array[0]
  124.         
  125.  
  126.     
  127.     def getPath(self, org = False, toplevel = False):
  128.         parent = self
  129.         names = []
  130.         while org:
  131.             names.append(parent.Name)
  132.         names.append(parent.getName())
  133.         if parent.Depth > 0:
  134.             parent = parent.Parent
  135.             continue
  136.         break
  137.         continue
  138.         names.reverse()
  139.         path = ''
  140.         if toplevel == False:
  141.             names.pop(0)
  142.         
  143.         for name in names:
  144.             path = os.path.join(path, name)
  145.         
  146.         return path
  147.  
  148.     
  149.     def getName(self):
  150.         
  151.         try:
  152.             return self.Directory.DesktopEntry.getName()
  153.         except AttributeError:
  154.             return self.Name
  155.  
  156.  
  157.     
  158.     def getGenericName(self):
  159.         
  160.         try:
  161.             return self.Directory.DesktopEntry.getGenericName()
  162.         except AttributeError:
  163.             return ''
  164.  
  165.  
  166.     
  167.     def getComment(self):
  168.         
  169.         try:
  170.             return self.Directory.DesktopEntry.getComment()
  171.         except AttributeError:
  172.             return ''
  173.  
  174.  
  175.     
  176.     def getIcon(self):
  177.         
  178.         try:
  179.             return self.Directory.DesktopEntry.getIcon()
  180.         except AttributeError:
  181.             return ''
  182.  
  183.  
  184.     
  185.     def addSubmenu(self, newmenu):
  186.         for submenu in self.Submenus:
  187.             if submenu == newmenu:
  188.                 submenu += newmenu
  189.                 break
  190.                 continue
  191.         else:
  192.             newmenu.Parent = self
  193.             newmenu.Depth = self.Depth + 1
  194.  
  195.  
  196.  
  197. class Move:
  198.     '''A move operation'''
  199.     
  200.     def __init__(self, node = None):
  201.         if node:
  202.             self.parseNode(node)
  203.         else:
  204.             self.Old = ''
  205.             self.New = ''
  206.  
  207.     
  208.     def __cmp__(self, other):
  209.         return cmp(self.Old, other.Old)
  210.  
  211.     
  212.     def parseNode(self, node):
  213.         for child in node.childNodes:
  214.             if child.nodeType == ELEMENT_NODE:
  215.                 if child.tagName == 'Old':
  216.                     
  217.                     try:
  218.                         self.parseOld(child.childNodes[0].nodeValue)
  219.                     except IndexError:
  220.                         raise ValidationError('Old cannot be empty', '??')
  221.                     except:
  222.                         None<EXCEPTION MATCH>IndexError
  223.                     
  224.  
  225.                 None<EXCEPTION MATCH>IndexError
  226.                 if child.tagName == 'New':
  227.                     
  228.                     try:
  229.                         self.parseNew(child.childNodes[0].nodeValue)
  230.                     except IndexError:
  231.                         raise ValidationError('New cannot be empty', '??')
  232.                     except:
  233.                         None<EXCEPTION MATCH>IndexError
  234.                     
  235.  
  236.                 None<EXCEPTION MATCH>IndexError
  237.                 continue
  238.         
  239.  
  240.     
  241.     def parseOld(self, value):
  242.         self.Old = value
  243.  
  244.     
  245.     def parseNew(self, value):
  246.         self.New = value
  247.  
  248.  
  249.  
  250. class Layout:
  251.     '''Menu Layout class'''
  252.     
  253.     def __init__(self, node = None):
  254.         self.order = []
  255.         if node:
  256.             if not node.getAttribute('show_empty'):
  257.                 pass
  258.             self.show_empty = 'false'
  259.             if not node.getAttribute('inline'):
  260.                 pass
  261.             self.inline = 'false'
  262.             if not node.getAttribute('inline_limit'):
  263.                 pass
  264.             self.inline_limit = 4
  265.             if not node.getAttribute('inline_header'):
  266.                 pass
  267.             self.inline_header = 'true'
  268.             if not node.getAttribute('inline_alias'):
  269.                 pass
  270.             self.inline_alias = 'false'
  271.             self.inline_limit = int(self.inline_limit)
  272.             self.parseNode(node)
  273.         else:
  274.             self.show_empty = 'false'
  275.             self.inline = 'false'
  276.             self.inline_limit = 4
  277.             self.inline_header = 'true'
  278.             self.inline_alias = 'false'
  279.             self.order.append([
  280.                 'Merge',
  281.                 'menus'])
  282.             self.order.append([
  283.                 'Merge',
  284.                 'files'])
  285.  
  286.     
  287.     def parseNode(self, node):
  288.         for child in node.childNodes:
  289.             if child.nodeType == ELEMENT_NODE:
  290.                 if child.tagName == 'Menuname':
  291.                     
  292.                     try:
  293.                         if not child.getAttribute('show_empty'):
  294.                             pass
  295.                         if not child.getAttribute('inline'):
  296.                             pass
  297.                         if not child.getAttribute('inline_limit'):
  298.                             pass
  299.                         if not child.getAttribute('inline_header'):
  300.                             pass
  301.                         if not child.getAttribute('inline_alias'):
  302.                             pass
  303.                         self.parseMenuname(child.childNodes[0].nodeValue, 'false', 'false', 4, 'true', 'false')
  304.                     except IndexError:
  305.                         raise ValidationError('Menuname cannot be empty', '')
  306.                     except:
  307.                         None<EXCEPTION MATCH>IndexError
  308.                     
  309.  
  310.                 None<EXCEPTION MATCH>IndexError
  311.                 if child.tagName == 'Separator':
  312.                     self.parseSeparator()
  313.                 elif child.tagName == 'Filename':
  314.                     
  315.                     try:
  316.                         self.parseFilename(child.childNodes[0].nodeValue)
  317.                     except IndexError:
  318.                         raise ValidationError('Filename cannot be empty', '')
  319.                     except:
  320.                         None<EXCEPTION MATCH>IndexError
  321.                     
  322.  
  323.                 None<EXCEPTION MATCH>IndexError
  324.                 if child.tagName == 'Merge':
  325.                     if not child.getAttribute('type'):
  326.                         pass
  327.                     self.parseMerge('all')
  328.                 
  329.             child.tagName == 'Merge'
  330.         
  331.  
  332.     
  333.     def parseMenuname(self, value, empty = 'false', inline = 'false', inline_limit = 4, inline_header = 'true', inline_alias = 'false'):
  334.         self.order.append([
  335.             'Menuname',
  336.             value,
  337.             empty,
  338.             inline,
  339.             inline_limit,
  340.             inline_header,
  341.             inline_alias])
  342.         self.order[-1][4] = int(self.order[-1][4])
  343.  
  344.     
  345.     def parseSeparator(self):
  346.         self.order.append([
  347.             'Separator'])
  348.  
  349.     
  350.     def parseFilename(self, value):
  351.         self.order.append([
  352.             'Filename',
  353.             value])
  354.  
  355.     
  356.     def parseMerge(self, type = 'all'):
  357.         self.order.append([
  358.             'Merge',
  359.             type])
  360.  
  361.  
  362.  
  363. class Rule:
  364.     '''Inlcude / Exclude Rules Class'''
  365.     
  366.     def __init__(self, type, node = None):
  367.         self.Type = type
  368.         self.Rule = ''
  369.         self.Depth = 0
  370.         self.Expr = [
  371.             'or']
  372.         self.New = True
  373.         if node:
  374.             self.parseNode(node)
  375.             self.compile()
  376.         
  377.  
  378.     
  379.     def __str__(self):
  380.         return self.Rule
  381.  
  382.     
  383.     def compile(self):
  384.         exec '\ndef do(menuentries, type, run):\n    for menuentry in menuentries:\n\t\tif run == 2 and ( menuentry.MatchedInclude == True \t\tor menuentry.Allocated == True ):\n\t\t\tcontinue\n\t\telif %s:\n\t\t    if type == "Include":\n\t\t\t\tmenuentry.Add = True\n\t\t\t\tmenuentry.MatchedInclude = True\n\t\t    else:\n\t\t\t\tmenuentry.Add = False\n    return menuentries\n' % self.Rule in self.__dict__
  385.  
  386.     
  387.     def parseNode(self, node):
  388.         for child in node.childNodes:
  389.             if child.nodeType == ELEMENT_NODE:
  390.                 if child.tagName == 'Filename':
  391.                     
  392.                     try:
  393.                         self.parseFilename(child.childNodes[0].nodeValue)
  394.                     except IndexError:
  395.                         raise ValidationError('Filename cannot be empty', '???')
  396.                     except:
  397.                         None<EXCEPTION MATCH>IndexError
  398.                     
  399.  
  400.                 None<EXCEPTION MATCH>IndexError
  401.                 if child.tagName == 'Category':
  402.                     
  403.                     try:
  404.                         self.parseCategory(child.childNodes[0].nodeValue)
  405.                     except IndexError:
  406.                         raise ValidationError('Category cannot be empty', '???')
  407.                     except:
  408.                         None<EXCEPTION MATCH>IndexError
  409.                     
  410.  
  411.                 None<EXCEPTION MATCH>IndexError
  412.                 if child.tagName == 'All':
  413.                     self.parseAll()
  414.                 elif child.tagName == 'And':
  415.                     self.parseAnd(child)
  416.                 elif child.tagName == 'Or':
  417.                     self.parseOr(child)
  418.                 elif child.tagName == 'Not':
  419.                     self.parseNot(child)
  420.                 
  421.             child.tagName == 'All'
  422.         
  423.  
  424.     
  425.     def parseNew(self, set = True):
  426.         if not self.New:
  427.             self.Rule += ' ' + self.Expr[self.Depth] + ' '
  428.         
  429.         if not set:
  430.             self.New = True
  431.         elif set:
  432.             self.New = False
  433.         
  434.  
  435.     
  436.     def parseFilename(self, value):
  437.         self.parseNew()
  438.         self.Rule += "menuentry.DesktopFileID == '%s'" % value.strip().replace('\\', '\\\\').replace("'", "\\'")
  439.  
  440.     
  441.     def parseCategory(self, value):
  442.         self.parseNew()
  443.         self.Rule += "'%s' in menuentry.Categories" % value.strip()
  444.  
  445.     
  446.     def parseAll(self):
  447.         self.parseNew()
  448.         self.Rule += 'True'
  449.  
  450.     
  451.     def parseAnd(self, node):
  452.         self.parseNew(False)
  453.         self.Rule += '('
  454.         self.Depth += 1
  455.         self.Expr.append('and')
  456.         self.parseNode(node)
  457.         self.Depth -= 1
  458.         self.Expr.pop()
  459.         self.Rule += ')'
  460.  
  461.     
  462.     def parseOr(self, node):
  463.         self.parseNew(False)
  464.         self.Rule += '('
  465.         self.Depth += 1
  466.         self.Expr.append('or')
  467.         self.parseNode(node)
  468.         self.Depth -= 1
  469.         self.Expr.pop()
  470.         self.Rule += ')'
  471.  
  472.     
  473.     def parseNot(self, node):
  474.         self.parseNew(False)
  475.         self.Rule += 'not ('
  476.         self.Depth += 1
  477.         self.Expr.append('or')
  478.         self.parseNode(node)
  479.         self.Depth -= 1
  480.         self.Expr.pop()
  481.         self.Rule += ')'
  482.  
  483.  
  484.  
  485. class MenuEntry:
  486.     """Wrapper for 'Menu Style' Desktop Entries"""
  487.     
  488.     def __init__(self, filename, dir = '', prefix = ''):
  489.         self.DesktopEntry = DesktopEntry(os.path.join(dir, filename))
  490.         self.setAttributes(filename, dir, prefix)
  491.         self.Show = True
  492.         self.Original = None
  493.         self.Parents = []
  494.         self.Allocated = False
  495.         self.Add = False
  496.         self.MatchedInclude = False
  497.         self.Categories = self.DesktopEntry.getCategories()
  498.  
  499.     
  500.     def save(self):
  501.         if self.DesktopEntry.tainted == True:
  502.             self.DesktopEntry.write()
  503.         
  504.  
  505.     
  506.     def getDir(self):
  507.         return self.DesktopEntry.filename.replace(self.Filename, '')
  508.  
  509.     
  510.     def getType(self):
  511.         if xdg.Config.root_mode == False:
  512.             if self.Original:
  513.                 return 'Both'
  514.             if xdg_data_dirs[0] in self.DesktopEntry.filename:
  515.                 return 'User'
  516.             return 'System'
  517.         xdg.Config.root_mode == False
  518.         return 'User'
  519.  
  520.     
  521.     def setAttributes(self, filename, dir = '', prefix = ''):
  522.         self.Filename = filename
  523.         self.Prefix = prefix
  524.         self.DesktopFileID = os.path.join(prefix, filename).replace('/', '-')
  525.         if not os.path.isabs(self.DesktopEntry.filename):
  526.             self._MenuEntry__setFilename()
  527.         
  528.  
  529.     
  530.     def updateAttributes(self):
  531.         if self.getType() == 'System':
  532.             self.Original = MenuEntry(self.Filename, self.getDir(), self.Prefix)
  533.             self._MenuEntry__setFilename()
  534.         
  535.  
  536.     
  537.     def __setFilename(self):
  538.         if xdg.Config.root_mode == False:
  539.             path = xdg_data_dirs[0]
  540.         else:
  541.             path = xdg_data_dirs[1]
  542.         if self.DesktopEntry.getType() == 'Application':
  543.             dir = os.path.join(path, 'applications')
  544.         else:
  545.             dir = os.path.join(path, 'desktop-directories')
  546.         self.DesktopEntry.filename = os.path.join(dir, self.Filename)
  547.  
  548.     
  549.     def __cmp__(self, other):
  550.         return locale.strcoll(self.DesktopEntry.getName(), other.DesktopEntry.getName())
  551.  
  552.     
  553.     def __eq__(self, other):
  554.         if self.DesktopFileID == str(other):
  555.             return True
  556.         return False
  557.  
  558.     
  559.     def __repr__(self):
  560.         return self.DesktopFileID
  561.  
  562.  
  563.  
  564. class Separator:
  565.     '''Just a dummy class for Separators'''
  566.     
  567.     def __init__(self, parent):
  568.         self.Parent = parent
  569.         self.Show = True
  570.  
  571.  
  572.  
  573. class Header:
  574.     '''Class for Inline Headers'''
  575.     
  576.     def __init__(self, name, generic_name, comment):
  577.         self.Name = name
  578.         self.GenericName = generic_name
  579.         self.Comment = comment
  580.  
  581.     
  582.     def __str__(self):
  583.         return self.Name
  584.  
  585.  
  586. tmp = { }
  587.  
  588. def __getFileName(filename):
  589.     dirs = xdg_config_dirs[:]
  590.     if xdg.Config.root_mode == True:
  591.         dirs.pop(0)
  592.     
  593.     for dir in dirs:
  594.         menuname = os.path.join(dir, 'menus', filename)
  595.         if os.path.isdir(dir) and os.path.isfile(menuname):
  596.             return menuname
  597.     
  598.  
  599.  
  600. def parse(filename = None):
  601.     if filename and not os.path.isabs(filename):
  602.         filename = __getFileName(filename)
  603.     
  604.     if not filename:
  605.         filename = __getFileName('applications.menu')
  606.     
  607.     if not filename:
  608.         raise ParsingError('File not found', '/etc/xdg/menus/applications.menu')
  609.     filename
  610.     if not os.path.splitext(filename)[1] == '.menu':
  611.         raise ParsingError('Not a .menu file', filename)
  612.     os.path.splitext(filename)[1] == '.menu'
  613.     
  614.     try:
  615.         doc = xml.dom.minidom.parse(filename)
  616.     except xml.parsers.expat.ExpatError:
  617.         raise ParsingError('Not a valid .menu file', filename)
  618.  
  619.     tmp['Root'] = ''
  620.     tmp['mergeFiles'] = []
  621.     tmp['DirectoryDirs'] = []
  622.     tmp['cache'] = MenuEntryCache()
  623.     __parse(doc, filename, tmp['Root'])
  624.     __parsemove(tmp['Root'])
  625.     __postparse(tmp['Root'])
  626.     tmp['Root'].Doc = doc
  627.     tmp['Root'].Filename = filename
  628.     __genmenuNotOnlyAllocated(tmp['Root'])
  629.     __genmenuOnlyAllocated(tmp['Root'])
  630.     sort(tmp['Root'])
  631.     return tmp['Root']
  632.  
  633.  
  634. def __parse(node, filename, parent = None):
  635.     for child in node.childNodes:
  636.         if child.nodeType == ELEMENT_NODE:
  637.             if child.tagName == 'Menu':
  638.                 __parseMenu(child, filename, parent)
  639.             elif child.tagName == 'AppDir':
  640.                 
  641.                 try:
  642.                     __parseAppDir(child.childNodes[0].nodeValue, filename, parent)
  643.                 except IndexError:
  644.                     raise ValidationError('AppDir cannot be empty', filename)
  645.                 except:
  646.                     None<EXCEPTION MATCH>IndexError
  647.                 
  648.  
  649.             None<EXCEPTION MATCH>IndexError
  650.             if child.tagName == 'DefaultAppDirs':
  651.                 __parseDefaultAppDir(filename, parent)
  652.             elif child.tagName == 'DirectoryDir':
  653.                 
  654.                 try:
  655.                     __parseDirectoryDir(child.childNodes[0].nodeValue, filename, parent)
  656.                 except IndexError:
  657.                     raise ValidationError('DirectoryDir cannot be empty', filename)
  658.                 except:
  659.                     None<EXCEPTION MATCH>IndexError
  660.                 
  661.  
  662.             None<EXCEPTION MATCH>IndexError
  663.             if child.tagName == 'DefaultDirectoryDirs':
  664.                 __parseDefaultDirectoryDir(filename, parent)
  665.             elif child.tagName == 'Name':
  666.                 
  667.                 try:
  668.                     parent.Name = child.childNodes[0].nodeValue
  669.                 except IndexError:
  670.                     raise ValidationError('Name cannot be empty', filename)
  671.                 except:
  672.                     None<EXCEPTION MATCH>IndexError
  673.                 
  674.  
  675.             None<EXCEPTION MATCH>IndexError
  676.             if child.tagName == 'Directory':
  677.                 
  678.                 try:
  679.                     parent.Directories.append(child.childNodes[0].nodeValue)
  680.                 except IndexError:
  681.                     raise ValidationError('Directory cannot be empty', filename)
  682.                 except:
  683.                     None<EXCEPTION MATCH>IndexError
  684.                 
  685.  
  686.             None<EXCEPTION MATCH>IndexError
  687.             if child.tagName == 'OnlyUnallocated':
  688.                 parent.OnlyUnallocated = True
  689.             elif child.tagName == 'NotOnlyUnallocated':
  690.                 parent.OnlyUnallocated = False
  691.             elif child.tagName == 'Deleted':
  692.                 parent.Deleted = True
  693.             elif child.tagName == 'NotDeleted':
  694.                 parent.Deleted = False
  695.             elif child.tagName == 'Include' or child.tagName == 'Exclude':
  696.                 parent.Rules.append(Rule(child.tagName, child))
  697.             elif child.tagName == 'MergeFile':
  698.                 
  699.                 try:
  700.                     if child.getAttribute('type') == 'parent':
  701.                         __parseMergeFile('applications.menu', child, filename, parent)
  702.                     else:
  703.                         __parseMergeFile(child.childNodes[0].nodeValue, child, filename, parent)
  704.                 except IndexError:
  705.                     raise ValidationError('MergeFile cannot be empty', filename)
  706.                 except:
  707.                     None<EXCEPTION MATCH>IndexError
  708.                 
  709.  
  710.             None<EXCEPTION MATCH>IndexError
  711.             if child.tagName == 'MergeDir':
  712.                 
  713.                 try:
  714.                     __parseMergeDir(child.childNodes[0].nodeValue, child, filename, parent)
  715.                 except IndexError:
  716.                     raise ValidationError('MergeDir cannot be empty', filename)
  717.                 except:
  718.                     None<EXCEPTION MATCH>IndexError
  719.                 
  720.  
  721.             None<EXCEPTION MATCH>IndexError
  722.             if child.tagName == 'DefaultMergeDirs':
  723.                 __parseDefaultMergeDirs(child, filename, parent)
  724.             elif child.tagName == 'Move':
  725.                 parent.Moves.append(Move(child))
  726.             elif child.tagName == 'Layout':
  727.                 if len(child.childNodes) > 1:
  728.                     parent.Layout = Layout(child)
  729.                 
  730.             elif child.tagName == 'DefaultLayout':
  731.                 if len(child.childNodes) > 1:
  732.                     parent.DefaultLayout = Layout(child)
  733.                 
  734.             elif child.tagName == 'LegacyDir':
  735.                 
  736.                 try:
  737.                     __parseLegacyDir(child.childNodes[0].nodeValue, child.getAttribute('prefix'), filename, parent)
  738.                 except IndexError:
  739.                     raise ValidationError('LegacyDir cannot be empty', filename)
  740.                 except:
  741.                     None<EXCEPTION MATCH>IndexError
  742.                 
  743.  
  744.             None<EXCEPTION MATCH>IndexError
  745.             if child.tagName == 'KDELegacyDirs':
  746.                 __parseKDELegacyDirs(filename, parent)
  747.             
  748.         child.tagName == 'KDELegacyDirs'
  749.     
  750.  
  751.  
  752. def __parsemove(menu):
  753.     for submenu in menu.Submenus:
  754.         __parsemove(submenu)
  755.     
  756.     for move in menu.Moves:
  757.         move_from_menu = menu.getMenu(move.Old)
  758.         if move_from_menu:
  759.             move_to_menu = menu.getMenu(move.New)
  760.             menus = move.New.split('/')
  761.             oldparent = None
  762.             while len(menus) > 0:
  763.                 if not oldparent:
  764.                     oldparent = menu
  765.                 
  766.                 newmenu = oldparent.getMenu(menus[0])
  767.                 if not newmenu:
  768.                     newmenu = Menu()
  769.                     newmenu.Name = menus[0]
  770.                     if len(menus) > 1:
  771.                         newmenu.NotInXml = True
  772.                     
  773.                     oldparent.addSubmenu(newmenu)
  774.                 
  775.                 oldparent = newmenu
  776.                 menus.pop(0)
  777.             newmenu += move_from_menu
  778.             move_from_menu.Parent.Submenus.remove(move_from_menu)
  779.             continue
  780.     
  781.  
  782.  
  783. def __postparse(menu):
  784.     if menu.Deleted == 'notset':
  785.         menu.Deleted = False
  786.     
  787.     if menu.OnlyUnallocated == 'notset':
  788.         menu.OnlyUnallocated = False
  789.     
  790.     if not (menu.Layout) or not (menu.DefaultLayout):
  791.         if menu.DefaultLayout:
  792.             menu.Layout = menu.DefaultLayout
  793.         elif menu.Layout:
  794.             if menu.Depth > 0:
  795.                 menu.DefaultLayout = menu.Parent.DefaultLayout
  796.             else:
  797.                 menu.DefaultLayout = Layout()
  798.         elif menu.Depth > 0:
  799.             menu.Layout = menu.Parent.DefaultLayout
  800.             menu.DefaultLayout = menu.Parent.DefaultLayout
  801.         else:
  802.             menu.Layout = Layout()
  803.             menu.DefaultLayout = Layout()
  804.     
  805.     if menu.Depth > 0:
  806.         menu.AppDirs = menu.Parent.AppDirs + menu.AppDirs
  807.         menu.DirectoryDirs = menu.Parent.DirectoryDirs + menu.DirectoryDirs
  808.     
  809.     menu.Directories = __removeDuplicates(menu.Directories)
  810.     menu.DirectoryDirs = __removeDuplicates(menu.DirectoryDirs)
  811.     menu.AppDirs = __removeDuplicates(menu.AppDirs)
  812.     for submenu in menu.Submenus:
  813.         __postparse(submenu)
  814.     
  815.     menu.Directories.reverse()
  816.     menu.DirectoryDirs.reverse()
  817.     menu.AppDirs.reverse()
  818.     for directory in menu.Directories:
  819.         for dir in menu.DirectoryDirs:
  820.             if os.path.isfile(os.path.join(dir, directory)):
  821.                 menuentry = MenuEntry(directory, dir)
  822.                 if not menu.Directory:
  823.                     menu.Directory = menuentry
  824.                 elif menuentry.getType() == 'System':
  825.                     if menu.Directory.getType() == 'User':
  826.                         menu.Directory.Original = menuentry
  827.                     
  828.                 
  829.             menu.Directory
  830.         
  831.         if menu.Directory:
  832.             break
  833.             continue
  834.     
  835.  
  836.  
  837. def __parseMenu(child, filename, parent):
  838.     m = Menu()
  839.     __parse(child, filename, m)
  840.     if parent:
  841.         parent.addSubmenu(m)
  842.     else:
  843.         tmp['Root'] = m
  844.  
  845.  
  846. def __check(value, filename, type):
  847.     path = os.path.dirname(filename)
  848.     if not os.path.isabs(value):
  849.         value = os.path.join(path, value)
  850.     
  851.     value = os.path.abspath(value)
  852.     if type == 'dir' and os.path.exists(value) and os.path.isdir(value):
  853.         return value
  854.     if type == 'file' and os.path.exists(value) and os.path.isfile(value):
  855.         return value
  856.     return False
  857.  
  858.  
  859. def __parseAppDir(value, filename, parent):
  860.     value = __check(value, filename, 'dir')
  861.     if value:
  862.         parent.AppDirs.append(value)
  863.     
  864.  
  865.  
  866. def __parseDefaultAppDir(filename, parent):
  867.     for dir in reversed(xdg_data_dirs):
  868.         __parseAppDir(os.path.join(dir, 'applications'), filename, parent)
  869.     
  870.  
  871.  
  872. def __parseDirectoryDir(value, filename, parent):
  873.     value = __check(value, filename, 'dir')
  874.     if value:
  875.         parent.DirectoryDirs.append(value)
  876.     
  877.  
  878.  
  879. def __parseDefaultDirectoryDir(filename, parent):
  880.     for dir in reversed(xdg_data_dirs):
  881.         __parseDirectoryDir(os.path.join(dir, 'desktop-directories'), filename, parent)
  882.     
  883.  
  884.  
  885. def __parseMergeFile(value, child, filename, parent):
  886.     if child.getAttribute('type') == 'parent':
  887.         for dir in xdg_config_dirs:
  888.             rel_file = filename.replace(dir, '').strip('/')
  889.             if rel_file != filename:
  890.                 for p in xdg_config_dirs:
  891.                     if dir == p:
  892.                         continue
  893.                     
  894.                     if os.path.isfile(os.path.join(p, rel_file)):
  895.                         __mergeFile(os.path.join(p, rel_file), child, parent)
  896.                         break
  897.                         continue
  898.                 
  899.         
  900.     else:
  901.         value = __check(value, filename, 'file')
  902.         if value:
  903.             __mergeFile(value, child, parent)
  904.         
  905.  
  906.  
  907. def __parseMergeDir(value, child, filename, parent):
  908.     value = __check(value, filename, 'dir')
  909.     if value:
  910.         for item in os.listdir(value):
  911.             
  912.             try:
  913.                 if os.path.splitext(item)[1] == '.menu':
  914.                     __mergeFile(os.path.join(value, item), child, parent)
  915.             continue
  916.             except UnicodeDecodeError:
  917.                 continue
  918.                 continue
  919.             
  920.  
  921.         
  922.     
  923.  
  924.  
  925. def __parseDefaultMergeDirs(child, filename, parent):
  926.     basename = os.path.splitext(os.path.basename(filename))[0]
  927.     for dir in reversed(xdg_config_dirs):
  928.         __parseMergeDir(os.path.join(dir, 'menus', basename + '-merged'), child, filename, parent)
  929.     
  930.  
  931.  
  932. def __mergeFile(filename, child, parent):
  933.     if filename in tmp['mergeFiles']:
  934.         if debug:
  935.             raise ParsingError('Infinite MergeFile loop detected', filename)
  936.         debug
  937.         return None
  938.     filename in tmp['mergeFiles']
  939.     tmp['mergeFiles'].append(filename)
  940.     
  941.     try:
  942.         doc = xml.dom.minidom.parse(filename)
  943.     except IOError:
  944.         if debug:
  945.             raise ParsingError('File not found', filename)
  946.         debug
  947.         return None
  948.     except xml.parsers.expat.ExpatError:
  949.         if debug:
  950.             raise ParsingError('Not a valid .menu file', filename)
  951.         debug
  952.         return None
  953.  
  954.     for child in doc.childNodes:
  955.         if child.nodeType == ELEMENT_NODE:
  956.             __parse(child, filename, parent)
  957.             break
  958.             continue
  959.     
  960.  
  961.  
  962. def __parseLegacyDir(dir, prefix, filename, parent):
  963.     m = __mergeLegacyDir(dir, prefix, filename, parent)
  964.     if m:
  965.         parent += m
  966.     
  967.  
  968.  
  969. def __mergeLegacyDir(dir, prefix, filename, parent):
  970.     dir = __check(dir, filename, 'dir')
  971.     if dir and dir not in tmp['DirectoryDirs']:
  972.         tmp['DirectoryDirs'].append(dir)
  973.         m = Menu()
  974.         m.AppDirs.append(dir)
  975.         m.DirectoryDirs.append(dir)
  976.         m.Name = os.path.basename(dir)
  977.         m.NotInXml = True
  978.         for item in os.listdir(dir):
  979.             
  980.             try:
  981.                 if item == '.directory':
  982.                     m.Directories.append(item)
  983.                 elif os.path.isdir(os.path.join(dir, item)):
  984.                     m.addSubmenu(__mergeLegacyDir(os.path.join(dir, item), prefix, filename, parent))
  985.             continue
  986.             except UnicodeDecodeError:
  987.                 continue
  988.                 continue
  989.             
  990.  
  991.         
  992.         tmp['cache'].addMenuEntries([
  993.             dir], prefix, True)
  994.         menuentries = tmp['cache'].getMenuEntries([
  995.             dir], False)
  996.         for menuentry in menuentries:
  997.             categories = menuentry.Categories
  998.             if len(categories) == 0:
  999.                 r = Rule('Include')
  1000.                 r.parseFilename(menuentry.DesktopFileID)
  1001.                 r.compile()
  1002.                 m.Rules.append(r)
  1003.             
  1004.             if dir not in parent.AppDirs:
  1005.                 categories.append('Legacy')
  1006.                 menuentry.Categories = categories
  1007.                 continue
  1008.         
  1009.         return m
  1010.  
  1011.  
  1012. def __parseKDELegacyDirs(filename, parent):
  1013.     f = os.popen3('kde-config --path apps')
  1014.     output = f[1].readlines()
  1015.     
  1016.     try:
  1017.         for dir in output[0].split(':'):
  1018.             __parseLegacyDir(dir, 'kde', filename, parent)
  1019.     except IndexError:
  1020.         pass
  1021.  
  1022.  
  1023.  
  1024. def __removeDuplicates(list):
  1025.     set = { }
  1026.     list.reverse()
  1027.     list = _[1]
  1028.     list.reverse()
  1029.     return list
  1030.  
  1031.  
  1032. def __genmenuNotOnlyAllocated(menu):
  1033.     for submenu in menu.Submenus:
  1034.         __genmenuNotOnlyAllocated(submenu)
  1035.     
  1036.     if menu.OnlyUnallocated == False:
  1037.         tmp['cache'].addMenuEntries(menu.AppDirs)
  1038.         menuentries = []
  1039.         for rule in menu.Rules:
  1040.             menuentries = rule.do(tmp['cache'].getMenuEntries(menu.AppDirs), rule.Type, 1)
  1041.         
  1042.         for menuentry in menuentries:
  1043.             if menuentry.Add == True:
  1044.                 menuentry.Parents.append(menu)
  1045.                 menuentry.Add = False
  1046.                 menuentry.Allocated = True
  1047.                 menu.MenuEntries.append(menuentry)
  1048.                 continue
  1049.         
  1050.     
  1051.  
  1052.  
  1053. def __genmenuOnlyAllocated(menu):
  1054.     for submenu in menu.Submenus:
  1055.         __genmenuOnlyAllocated(submenu)
  1056.     
  1057.     if menu.OnlyUnallocated == True:
  1058.         tmp['cache'].addMenuEntries(menu.AppDirs)
  1059.         menuentries = []
  1060.         for rule in menu.Rules:
  1061.             menuentries = rule.do(tmp['cache'].getMenuEntries(menu.AppDirs), rule.Type, 2)
  1062.         
  1063.         for menuentry in menuentries:
  1064.             if menuentry.Add == True:
  1065.                 menuentry.Parents.append(menu)
  1066.                 menu.MenuEntries.append(menuentry)
  1067.                 continue
  1068.         
  1069.     
  1070.  
  1071.  
  1072. def sort(menu):
  1073.     menu.Entries = []
  1074.     menu.Visible = 0
  1075.     for submenu in menu.Submenus:
  1076.         sort(submenu)
  1077.     
  1078.     tmp_s = []
  1079.     tmp_e = []
  1080.     for order in menu.Layout.order:
  1081.         if order[0] == 'Filename':
  1082.             tmp_e.append(order[1])
  1083.             continue
  1084.         if order[0] == 'Menuname':
  1085.             tmp_s.append(order[1])
  1086.             continue
  1087.     
  1088.     for order in menu.Layout.order:
  1089.         if order[0] == 'Separator':
  1090.             separator = Separator(menu)
  1091.             if len(menu.Entries) > 0 and isinstance(menu.Entries[-1], Separator):
  1092.                 separator.Show = False
  1093.             
  1094.             menu.Entries.append(separator)
  1095.             continue
  1096.         if order[0] == 'Filename':
  1097.             menuentry = menu.getMenuEntry(order[1])
  1098.             if menuentry:
  1099.                 menu.Entries.append(menuentry)
  1100.             
  1101.         menuentry
  1102.         if order[0] == 'Menuname':
  1103.             submenu = menu.getMenu(order[1])
  1104.             if submenu:
  1105.                 __parse_inline(submenu, menu)
  1106.             
  1107.         submenu
  1108.         if order[0] == 'Merge':
  1109.             if order[1] == 'files' or order[1] == 'all':
  1110.                 menu.MenuEntries.sort()
  1111.                 for menuentry in menu.MenuEntries:
  1112.                     if menuentry not in tmp_e:
  1113.                         menu.Entries.append(menuentry)
  1114.                         continue
  1115.                 
  1116.             elif order[1] == 'menus' or order[1] == 'all':
  1117.                 menu.Submenus.sort()
  1118.                 for submenu in menu.Submenus:
  1119.                     if submenu.Name not in tmp_s:
  1120.                         __parse_inline(submenu, menu)
  1121.                         continue
  1122.                 
  1123.             
  1124.         order[1] == 'all'
  1125.     
  1126.     for entry in menu.Entries:
  1127.         entry.Show = True
  1128.         menu.Visible += 1
  1129.         if isinstance(entry, Menu):
  1130.             if entry.Deleted == True:
  1131.                 entry.Show = 'Deleted'
  1132.                 menu.Visible -= 1
  1133.             elif isinstance(entry.Directory, MenuEntry):
  1134.                 if entry.Directory.DesktopEntry.getNoDisplay() == True:
  1135.                     entry.Show = 'NoDisplay'
  1136.                     menu.Visible -= 1
  1137.                 elif entry.Directory.DesktopEntry.getHidden() == True:
  1138.                     entry.Show = 'Hidden'
  1139.                     menu.Visible -= 1
  1140.                 
  1141.             
  1142.         entry.Deleted == True
  1143.         if isinstance(entry, MenuEntry):
  1144.             if entry.DesktopEntry.getNoDisplay() == True:
  1145.                 entry.Show = 'NoDisplay'
  1146.                 menu.Visible -= 1
  1147.             elif entry.DesktopEntry.getHidden() == True:
  1148.                 entry.Show = 'Hidden'
  1149.                 menu.Visible -= 1
  1150.             elif entry.DesktopEntry.getTryExec() and not __try_exec(entry.DesktopEntry.getTryExec()):
  1151.                 entry.Show = 'NoExec'
  1152.                 menu.Visible -= 1
  1153.             elif xdg.Config.windowmanager:
  1154.                 if entry.DesktopEntry.getOnlyShowIn() != [] or xdg.Config.windowmanager not in entry.DesktopEntry.getOnlyShowIn() or xdg.Config.windowmanager in entry.DesktopEntry.getNotShowIn():
  1155.                     entry.Show = 'NotShowIn'
  1156.                     menu.Visible -= 1
  1157.                 
  1158.             
  1159.         not __try_exec(entry.DesktopEntry.getTryExec())
  1160.         if isinstance(entry, Separator):
  1161.             menu.Visible -= 1
  1162.             continue
  1163.         menu
  1164.     
  1165.     if len(menu.Entries) > 0:
  1166.         if isinstance(menu.Entries[0], Separator):
  1167.             menu.Entries[0].Show = False
  1168.         
  1169.     
  1170.     if len(menu.Entries) > 1:
  1171.         if isinstance(menu.Entries[-1], Separator):
  1172.             menu.Entries[-1].Show = False
  1173.         
  1174.     
  1175.     for entry in menu.Entries:
  1176.         if isinstance(entry, Menu) and entry.Layout.show_empty == 'false' and entry.Visible == 0:
  1177.             entry.Show = 'Empty'
  1178.             menu.Visible -= 1
  1179.             if entry.NotInXml == True:
  1180.                 menu.Entries.remove(entry)
  1181.             
  1182.         entry.NotInXml == True
  1183.     
  1184.  
  1185.  
  1186. def __try_exec(executable):
  1187.     paths = os.environ['PATH'].split(os.pathsep)
  1188.     if not os.path.isfile(executable):
  1189.         for p in paths:
  1190.             f = os.path.join(p, executable)
  1191.             if os.path.isfile(f):
  1192.                 if os.access(f, os.X_OK):
  1193.                     return True
  1194.                 continue
  1195.             os.access(f, os.X_OK)
  1196.         
  1197.     elif os.access(executable, os.X_OK):
  1198.         return True
  1199.     return False
  1200.  
  1201.  
  1202. def __parse_inline(submenu, menu):
  1203.     if submenu.Layout.inline == 'true':
  1204.         if len(submenu.Entries) == 1 and submenu.Layout.inline_alias == 'true':
  1205.             menuentry = submenu.Entries[0]
  1206.             menuentry.DesktopEntry.set('Name', submenu.getName(), locale = True)
  1207.             menuentry.DesktopEntry.set('GenericName', submenu.getGenericName(), locale = True)
  1208.             menuentry.DesktopEntry.set('Comment', submenu.getComment(), locale = True)
  1209.             menu.Entries.append(menuentry)
  1210.         elif len(submenu.Entries) <= submenu.Layout.inline_limit or submenu.Layout.inline_limit == 0:
  1211.             if submenu.Layout.inline_header == 'true':
  1212.                 header = Header(submenu.getName(), submenu.getGenericName(), submenu.getComment())
  1213.                 menu.Entries.append(header)
  1214.             
  1215.             for entry in submenu.Entries:
  1216.                 menu.Entries.append(entry)
  1217.             
  1218.         else:
  1219.             menu.Entries.append(submenu)
  1220.     else:
  1221.         menu.Entries.append(submenu)
  1222.  
  1223.  
  1224. class MenuEntryCache:
  1225.     '''Class to cache Desktop Entries'''
  1226.     
  1227.     def __init__(self):
  1228.         self.cacheEntries = { }
  1229.         self.cacheEntries['legacy'] = []
  1230.         self.cache = { }
  1231.  
  1232.     
  1233.     def addMenuEntries(self, dirs, prefix = '', legacy = False):
  1234.         for dir in dirs:
  1235.             if not self.cacheEntries.has_key(dir):
  1236.                 self.cacheEntries[dir] = []
  1237.                 self._MenuEntryCache__addFiles(dir, '', prefix, legacy)
  1238.                 continue
  1239.         
  1240.  
  1241.     
  1242.     def __addFiles(self, dir, subdir, prefix, legacy):
  1243.         for item in os.listdir(os.path.join(dir, subdir)):
  1244.             if os.path.splitext(item)[1] == '.desktop':
  1245.                 
  1246.                 try:
  1247.                     menuentry = MenuEntry(os.path.join(subdir, item), dir, prefix)
  1248.                 except ParsingError:
  1249.                     continue
  1250.  
  1251.                 self.cacheEntries[dir].append(menuentry)
  1252.                 if legacy == True:
  1253.                     self.cacheEntries['legacy'].append(menuentry)
  1254.                 
  1255.             legacy == True
  1256.             if os.path.isdir(os.path.join(dir, subdir, item)) and legacy == False:
  1257.                 self._MenuEntryCache__addFiles(dir, os.path.join(subdir, item), prefix, legacy)
  1258.                 continue
  1259.         
  1260.  
  1261.     
  1262.     def getMenuEntries(self, dirs, legacy = True):
  1263.         list = []
  1264.         ids = []
  1265.         appdirs = dirs[:]
  1266.         if legacy == True:
  1267.             appdirs.append('legacy')
  1268.         
  1269.         key = ''.join(appdirs)
  1270.         
  1271.         try:
  1272.             return self.cache[key]
  1273.         except KeyError:
  1274.             pass
  1275.  
  1276.         for dir in appdirs:
  1277.             for menuentry in self.cacheEntries[dir]:
  1278.                 
  1279.                 try:
  1280.                     if menuentry.DesktopFileID not in ids:
  1281.                         ids.append(menuentry.DesktopFileID)
  1282.                         list.append(menuentry)
  1283.                     elif menuentry.getType() == 'System':
  1284.                         i = list.index(menuentry)
  1285.                         e = list[i]
  1286.                         if e.getType() == 'User':
  1287.                             e.Original = menuentry
  1288.                         
  1289.                 continue
  1290.                 except UnicodeDecodeError:
  1291.                     continue
  1292.                     continue
  1293.                 
  1294.  
  1295.             
  1296.         
  1297.         self.cache[key] = list
  1298.         return list
  1299.  
  1300.  
  1301.