home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / AppInstall / Menu.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  13.9 KB  |  403 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. import pygtk
  5. pygtk.require('2.0')
  6. import gtk
  7. import gtk.gdk as gtk
  8. import gobject
  9. import xdg.Menu as xdg
  10. import sys
  11. import os
  12. import gettext
  13. import common
  14. from warnings import warn
  15. from gettext import gettext as _
  16. from Util import *
  17. (SHOW_ALL, SHOW_ALL_SUPPORTED, SHOW_ALL_FREE, SHOW_ONLY_MAIN, SHOW_ONLY_PROPRIETARY, SHOW_ONLY_THIRD_PARTY) = range(6)
  18.  
  19. class MenuItem(object):
  20.     ''' base class for a object in the menu '''
  21.     
  22.     def __init__(self, name, iconname = None):
  23.         self.name = name
  24.         self.iconname = iconname
  25.         self.icontheme = None
  26.  
  27.     
  28.     def __repr__(self):
  29.         return 'MenuItem: %s' % self.name
  30.  
  31.  
  32.  
  33. class Category(MenuItem):
  34.     ''' represents a category '''
  35.     
  36.     def __init__(self, parent, name, iconname = None):
  37.         MenuItem.__init__(self, name, iconname)
  38.  
  39.     
  40.     def initListStores(self, parent):
  41.         self.icontheme = parent.icons
  42.         self.all_applications = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_INT)
  43.         self.filtered_applications = self.all_applications.filter_new()
  44.         self.filtered_applications.set_visible_func(parent._visible_filter)
  45.         self.applications = gtk.TreeModelSort(self.filtered_applications)
  46.  
  47.  
  48.  
  49. class Application(MenuItem):
  50.     ''' this class represents a application '''
  51.     
  52.     def __init__(self, name, iconname = None):
  53.         MenuItem.__init__(self, name, iconname)
  54.         self.pkgname = None
  55.         self.description = ''
  56.         self.html = None
  57.         self.mime = None
  58.         self.execCmd = None
  59.         self.needsTerminal = False
  60.         self.available = False
  61.         self.component = None
  62.         self.channel = None
  63.         self.isInstalled = False
  64.         self.toInstall = False
  65.         self.popcon = 1
  66.         self.rank = 1
  67.         self.free = False
  68.         self.licenseUri = None
  69.         self.supported = False
  70.         self.thirdparty = False
  71.         self.architectures = []
  72.         self.menupath = ''
  73.  
  74.  
  75.  
  76. class ApplicationMenu(object):
  77.     ''' this represents the application menu, the interessting bits are:
  78.         - store that can be attached to a TreeView
  79.         - pkg_to_app a dictionary that maps the apt pkgname to the application
  80.                      items
  81.     '''
  82.     debug = 0
  83.     
  84.     def __init__(self, datadir, cachedir, cache, treeview_categories, treeview_packages, progress, filter = SHOW_ONLY_MAIN, dontPopulate = False):
  85.         self.menudir = datadir + '/desktop'
  86.         self.cache = cache
  87.         self.treeview_categories = treeview_categories
  88.         self.treeview_packages = treeview_packages
  89.         self.popcon_max = 1
  90.         self.pickle = { }
  91.         self.icons = common.ToughIconTheme()
  92.         self.icons.prepend_search_path(os.path.join(datadir, 'icons'))
  93.         
  94.         try:
  95.             gtk.window_set_default_icon(self.icons.load_icon('gnome-settings-default-applications', 32, 0))
  96.         except gobject.GError:
  97.             pass
  98.  
  99.         self.searchTerms = []
  100.         self.mimeSearch = None
  101.         self.filter = filter
  102.         self.pkg_to_app = { }
  103.         self.desktopEntriesSeen = set()
  104.         self.real_categories_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
  105.         if dontPopulate:
  106.             return None
  107.         
  108.         if os.path.exists('%s/menu.p' % cachedir):
  109.             print 'using existing cache'
  110.             import cPickle
  111.             self.pickle = cPickle.load(open('%s/menu.p' % cachedir))
  112.         else:
  113.             print 'no cache found'
  114.             self.desktopEntriesSeen.clear()
  115.             menu = xdg.Menu.parse(os.path.join(self.menudir, 'applications.menu'))
  116.             self._populateFromEntry(menu)
  117.         self.refresh(progress)
  118.         self.store = self.real_categories_store
  119.         self.treeview_categories.set_model(self.real_categories_store)
  120.         self.treeview_packages.set_model(None)
  121.  
  122.     
  123.     def _refilter(self):
  124.         model = self.treeview_packages.get_model()
  125.         name = None
  126.         (path, colum) = self.treeview_packages.get_cursor()
  127.         if path:
  128.             name = model.get_value(model.get_iter(path), COL_NAME)
  129.         
  130.         self.treeview_packages.set_model(None)
  131.         if model != None:
  132.             model.get_model().refilter()
  133.         
  134.         self.treeview_packages.set_model(model)
  135.         self.treeview_packages.columns_autosize()
  136.         if name != None:
  137.             for it in iterate_list_store(model, model.get_iter_first()):
  138.                 aname = model.get_value(it, COL_NAME)
  139.                 if name == aname:
  140.                     self.treeview_packages.set_cursor(model.get_path(it))
  141.                     return None
  142.                     continue
  143.             
  144.         elif len(model) > 0:
  145.             self.treeview_packages.set_cursor(0)
  146.         
  147.  
  148.     
  149.     def _ranking_sort_func(self, model, iter1, iter2):
  150.         '''
  151.         Sort by the search result rank
  152.         '''
  153.         item1 = model.get_value(iter1, COL_ITEM)
  154.         item2 = model.get_value(iter2, COL_ITEM)
  155.         if item1 == None or item2 == None:
  156.             return 0
  157.         
  158.         if item1.rank < item2.rank:
  159.             return 1
  160.         elif item1.rank > item2.rank:
  161.             return -1
  162.         else:
  163.             return 0
  164.  
  165.     
  166.     def _visible_filter(self, model, iter):
  167.         item = model.get_value(iter, COL_ITEM)
  168.         if item:
  169.             if self.mimeSearch and not self.mimeSearch.approved(item.component, item.pkgname):
  170.                 return False
  171.             
  172.             if self.filter == SHOW_ONLY_MAIN and item.component != 'main':
  173.                 return False
  174.             
  175.             if self.filter == SHOW_ALL_SUPPORTED and item.supported != True:
  176.                 return False
  177.             
  178.             if self.filter == SHOW_ALL_FREE and item.free == False:
  179.                 return False
  180.             
  181.             if self.filter == SHOW_ONLY_PROPRIETARY and item.free == True:
  182.                 return False
  183.             
  184.             if self.filter == SHOW_ONLY_THIRD_PARTY and item.thirdparty != True:
  185.                 return False
  186.             
  187.             if len(self.searchTerms) > 0:
  188.                 rank = self._filterAndRank(item)
  189.                 if rank == None:
  190.                     return False
  191.                 else:
  192.                     item.rank = rank
  193.             
  194.         
  195.         return True
  196.  
  197.     
  198.     def _filterAndRank(self, item):
  199.         '''
  200.         Watch out, Google!
  201.         '''
  202.         trigger = ''
  203.         rank = item.popcon
  204.         if self.mimeSearch:
  205.             if self._mimeFilter(item):
  206.                 return rank
  207.             else:
  208.                 return None
  209.         
  210.         for term in self.searchTerms:
  211.             hit = False
  212.             if term == item.name.lower() or term == item.pkgname.lower():
  213.                 rank += 1500
  214.                 hit = True
  215.             
  216.             if term in item.name.lower():
  217.                 rank += item.popcon * 3
  218.                 trigger += ' name'
  219.                 hit = True
  220.             
  221.             if term in item.pkgname.lower():
  222.                 rank += item.popcon * 3
  223.                 trigger += ' pkg_name'
  224.                 hit = True
  225.             
  226.             if self._mimeMatch(item, term, fuzzy = True):
  227.                 rank += item.popcon * 2
  228.                 trigger += ' mime'
  229.                 hit = True
  230.             
  231.             if term in item.description.lower():
  232.                 rank += item.popcon
  233.                 trigger += ' desc'
  234.                 hit = True
  235.             
  236.             if self.cache.has_key(item.pkgname) and term in self.cache[item.pkgname].description.lower():
  237.                 rank += item.popcon
  238.                 trigger += ' pkg_desc'
  239.                 hit = True
  240.             
  241.             if hit == False:
  242.                 return None
  243.                 continue
  244.         
  245.         return rank
  246.  
  247.     
  248.     def _mimeMatch(self, item, term, fuzzy = False):
  249.         for re_pattern in item.mime:
  250.             pattern = re_pattern.pattern
  251.             if fuzzy and term in pattern:
  252.                 return True
  253.                 continue
  254.             if not fuzzy and re_pattern.match(term):
  255.                 return True
  256.                 continue
  257.         
  258.         return False
  259.  
  260.     
  261.     def _mimeFilter(self, item):
  262.         for mime_type in self.searchTerms:
  263.             if self._mimeMatch(item, mime_type):
  264.                 return True
  265.                 continue
  266.         
  267.         return False
  268.  
  269.     
  270.     def doMimeSearch(self, mime_type, fuzzy = False):
  271.         res = set()
  272.         model = self.real_categories_store.get_value(self.all_category_iter, COL_ITEM).all_applications
  273.         for it in iterate_list_store(model, model.get_iter_first()):
  274.             item = model.get_value(it, COL_ITEM)
  275.             for re_pattern in item.mime:
  276.                 pattern = re_pattern.pattern
  277.                 if fuzzy and mime_type in pattern:
  278.                     res.add(item)
  279.                     continue
  280.                 if not fuzzy and re_pattern.match(mime_type):
  281.                     res.add(item)
  282.                     continue
  283.             
  284.         
  285.         return res
  286.  
  287.     
  288.     def createMenuCache(self, targetdir):
  289.         self.desktopEntriesSeen.clear()
  290.         self.pkg_to_app.clear()
  291.         menu = xdg.Menu.parse(os.path.abspath(os.path.join(self.menudir, 'applications.menu')))
  292.         self._populateFromEntry(menu)
  293.         import pickle
  294.         pickle.dump(self.pickle, open('%s/menu.p' % targetdir, 'w'))
  295.  
  296.     
  297.     def refresh(self, progress):
  298.         self.real_categories_store.clear()
  299.         self.all_category_iter = self.real_categories_store.append()
  300.         item = Category(self, '<b>%s</b>' % _('All'), 'distributor-logo')
  301.         item.initListStores(self)
  302.         self.real_categories_store.set(self.all_category_iter, COL_NAME, '<b>%s</b>' % _('All'), COL_ITEM, item)
  303.         i = 0
  304.         lenx = len(self.pickle.keys())
  305.         keys = self.pickle.keys()
  306.         keys.sort(cmp = (lambda x, y: cmp(x.name.lower(), y.name.lower())))
  307.         for category in keys:
  308.             category.initListStores(self)
  309.             self.real_categories_store.set(self.real_categories_store.append(), COL_NAME, category.name, COL_ITEM, category)
  310.             i += 1
  311.             progress.update((i / float(lenx)) * 100.0)
  312.             for item in self.pickle[category]:
  313.                 item.name = xmlescape(item.desktop_entry.getName())
  314.                 item.description = xmlescape(item.desktop_entry.getComment())
  315.                 if not item.description:
  316.                     item.description = xmlescape(item.desktop_entry.get('GenericName'))
  317.                 
  318.                 item.icontheme = self.icons
  319.                 category.all_applications.set(category.all_applications.append(), COL_NAME, item.name, COL_ITEM, item, COL_POPCON, item.popcon)
  320.                 store = self.real_categories_store.get_value(self.all_category_iter, COL_ITEM).all_applications
  321.                 store.set(store.append(), COL_NAME, item.name, COL_ITEM, item, COL_POPCON, item.popcon)
  322.                 if item.popcon > self.popcon_max:
  323.                     self.popcon_max = item.popcon
  324.                 
  325.                 pkgname = item.pkgname
  326.                 if self.cache.has_key(pkgname):
  327.                     item.isInstalled = self.cache[pkgname].isInstalled
  328.                 else:
  329.                     item.isInstalled = False
  330.                 item.toInstall = item.isInstalled
  331.             
  332.         
  333.  
  334.     
  335.     def getChanges(self, get_paths = False):
  336.         ''' return the selected changes in the tree
  337.             TODO: what is get_paths?
  338.         '''
  339.         to_inst = set()
  340.         to_rm = set()
  341.         for name, item in self.store:
  342.             for name, item, popcon in item.all_applications:
  343.                 if item.isInstalled and not (item.toInstall):
  344.                     to_rm.add(item)
  345.                 
  346.                 if not (item.isInstalled) and item.toInstall:
  347.                     to_inst.add(item)
  348.                     continue
  349.             
  350.         
  351.         return (to_inst, to_rm)
  352.  
  353.     
  354.     def isChanged(self):
  355.         ''' check if there are changes at all '''
  356.         for cat_name, cat in self.store:
  357.             for name, item, popcon in cat.all_applications:
  358.                 if item.toInstall != item.isInstalled:
  359.                     return True
  360.                     continue
  361.             
  362.         
  363.         return False
  364.  
  365.     
  366.     def _populateFromEntry(self, node, parent = None, progress = None):
  367.         for entry in node.getEntries(hidden = True):
  368.             self._dbg(2, 'entry: %s' % entry)
  369.             if isinstance(entry, xdg.Menu.Menu):
  370.                 name = xmlescape(entry.getName())
  371.                 self._dbg(1, 'we have a sub-menu %s ' % name)
  372.                 item = Category(self, name, entry.getIcon())
  373.                 self.pickle[item] = []
  374.                 self._populateFromEntry(entry, item, progress = progress)
  375.                 continue
  376.             if isinstance(entry, xdg.Menu.MenuEntry):
  377.                 self._dbg(3, node.getPath() + '/\t' + entry.DesktopFileID + '\t' + entry.DesktopEntry.getFileName())
  378.                 name = xmlescape(entry.DesktopEntry.getName())
  379.                 self._dbg(1, 'we have a application %s (%s) ' % (name, entry.DesktopFileID))
  380.             None if name and entry.DesktopEntry.hasKey('X-AppInstall-Package') else None<EXCEPTION MATCH>UnicodeEncodeError
  381.             if isinstance(entry, xdg.Menu.Header):
  382.                 print 'got header'
  383.                 continue
  384.         
  385.  
  386.     
  387.     def _dbg(self, level, msg):
  388.         '''Write debugging output to sys.stderr.
  389.         '''
  390.         if level <= self.debug:
  391.             print >>sys.stderr, msg
  392.         
  393.  
  394.  
  395. if __name__ == '__main__':
  396.     print 'testing the menu'
  397.     desktopdir = '/usr/share/app-install'
  398.     from Util import MyCache
  399.     cache = MyCache()
  400.     treeview = gtk.TreeView()
  401.     menu = ApplicationMenu(desktopdir, cache, treeview, treeview, apt.progress.OpProgress())
  402.  
  403.