def __init__(self, db, cache, icons, icon_size=48, global_icon_cache=False): GObject.GObject.__init__(self) self.db = db self.cache = cache # get all categories cat_parser = CategoriesParser(db) self.all_categories = cat_parser.parse_applications_menu( softwarecenter.paths.APP_INSTALL_PATH) # reviews stats loader self.review_loader = get_review_loader(cache, db) # icon jazz self.icons = icons self.icon_size = icon_size # cache the 'missing icon' used in the treeview for apps without an # icon self._missing_icon = icons.load_icon(Icons.MISSING_APP, icon_size, 0) if global_icon_cache: self.icon_cache = _app_icon_cache else: self.icon_cache = {}
def __init__(self, cache, db, icons, apps_filter, apps_limit=0): CategoriesView.__init__(self, cache, db, icons, apps_filter, apps_limit=0) self.top_rated = None self.exhibit_banner = None # sections self.departments = None self.appcount = None # get categories self.categories_parser = CategoriesParser(db) self.categories = self.categories_parser.parse_applications_menu() # build before connecting the signals to avoid race self.build() # ensure that on db-reopen we refresh the whats-new titles self.db.connect("reopen", self._on_db_reopen) # ensure that updates to the stats are reflected in the UI self.reviews_loader = get_review_loader(self.cache) self.reviews_loader.connect( "refresh-review-stats-finished", self._on_refresh_review_stats)
def __init__(self, db, cache, icons, icon_size=48, global_icon_cache=False): GObject.GObject.__init__(self) self.db = db self.cache = cache # get all categories cat_parser = CategoriesParser(db) self.all_categories = cat_parser.parse_applications_menu( softwarecenter.paths.APP_INSTALL_PATH) # reviews stats loader self.review_loader = get_review_loader(cache, db) # icon jazz self.icons = icons self.icon_size = icon_size self._missing_icon = None # delay this until actually needed if global_icon_cache: self.icon_cache = _app_icon_cache else: self.icon_cache = {}
def __init__(self, parent=None): super(ReviewsListModel, self).__init__() self._reviews = [] roles = dict(enumerate(ReviewsListModel.COLUMNS)) self.setRoleNames(roles) # FIXME: make this async self.cache = get_pkg_info() self.reviews = get_review_loader(self.cache)
def __init__(self, parent=None): super(ReviewsListModel, self).__init__() self._reviews = [] roles = dict(enumerate(ReviewsListModel.COLUMNS)) self.setRoleNames(roles) # FIXME: make this async self.cache = get_pkg_info() self.reviews = get_review_loader(self.cache) self.reviews.connect("refresh-review-stats-finished", self._on_refresh_review_stats_finished) self.reviews.connect("get-reviews-finished", self._on_reviews_ready_callback)
def __init__(self, db, distro, icons, cache, datadir): self.db = db self.distro = distro self.icons = icons self.cache = cache self.backend = get_install_backend() self.cache.connect("cache-ready", self._on_cache_ready) self.datadir = datadir self.app = None self.appdetails = None self.addons_to_install = [] self.addons_to_remove = [] # reviews self.review_loader = get_review_loader(self.cache, self.db)
def __init__(self, parent=None): super(PkgListModel, self).__init__() self._docs = [] roles = dict(enumerate(PkgListModel.COLUMNS)) self.setRoleNames(roles) self._query = "" self._category = "" pathname = os.path.join(XAPIAN_BASE_PATH, "xapian") self.cache = get_pkg_info() self.db = StoreDatabase(pathname, self.cache) self.db.open(use_axi=False) self.backend = get_install_backend() self.backend.connect("transaction-progress-changed", self._on_backend_transaction_progress_changed) self.reviews = get_review_loader(self.cache) # FIXME: get this from a parent self._catparser = CategoriesParser(self.db) self._categories = self._catparser.parse_applications_menu("/usr/share/app-install")
def __init__(self, parent=None): super(PkgListModel, self).__init__() self._docs = [] roles = dict(enumerate(PkgListModel.COLUMNS)) self.setRoleNames(roles) self._query = "" self._category = "" pathname = os.path.join(XAPIAN_BASE_PATH, "xapian") self.cache = get_pkg_info() self.db = StoreDatabase(pathname, self.cache) self.db.open(use_axi=False) self.backend = get_install_backend() self.backend.connect("transaction-progress-changed", self._on_backend_transaction_progress_changed) self.reviews = get_review_loader(self.cache) # FIXME: get this from a parent self._catparser = CategoriesParser(self.db) self._categories = self._catparser.parse_applications_menu( '/usr/share/app-install')
def __init__(self, datadir, desktopdir, cache, db, icons, apps_filter, apps_limit=0): CategoriesViewGtk.__init__(self, datadir, desktopdir, cache, db, icons, apps_filter, apps_limit=0) # sections self.departments = None self.appcount = None # ensure that on db-reopen we refresh the whats-new titles self.db.connect("reopen", self._on_db_reopen) # ensure that updates to the stats are reflected in the UI self.reviews_loader = get_review_loader(self.cache) self.reviews_loader.connect( "refresh-review-stats-finished", self._on_refresh_review_stats) self.build(desktopdir) return
def __init__(self, db, cache, icons, icon_size, global_icon_cache): # the usual suspects self.db = db self.cache = cache # reviews stats loader self.review_loader = get_review_loader(cache, db) # backend stuff self.backend = get_install_backend() self.backend.connect("transaction-progress-changed", self._on_transaction_progress_changed) self.backend.connect("transaction-started", self._on_transaction_started) self.backend.connect("transaction-finished", self._on_transaction_finished) # keep track of paths for transactions in progress self.transaction_path_map = {} # icon jazz self.icons = icons self.icon_size = icon_size if global_icon_cache: self.icon_cache = _app_icon_cache else: self.icon_cache = {} # active row path self.active_row = None # cache the 'missing icon' used in the treeview for apps without an icon self._missing_icon = icons.load_icon(Icons.MISSING_APP, icon_size, 0) self._in_progress = False self._break = False # other stuff self.active = False return
def show_top_rated_apps(): # get the ratings cache = get_pkg_info() loader = get_review_loader(cache) review_stats = loader.REVIEW_STATS_CACHE # recalculate using different default power results = {} for i in [0.5, 0.4, 0.3, 0.2, 0.1, 0.05]: for (key, value) in review_stats.iteritems(): value.dampened_rating = calc_dr(value.rating_spread, power=i) top_rated = loader.get_top_rated_apps(quantity=25) print "For power: %s" % i for (i, key) in enumerate(top_rated): item = review_stats[key] print "%(rang)2i: %(pkgname)-25s avg=%(avg)1.2f total=%(total)03i dampened=%(dampened)1.5f spread=%(spread)s" % { 'rang' : i+1, 'pkgname' : item.app.pkgname, 'avg' : item.ratings_average, 'total' : item.ratings_total, 'spread' : item.rating_spread, 'dampened' : item.dampened_rating, } print results[i] = top_rated[:]
def show_top_rated_apps(): # get the ratings cache = get_pkg_info() loader = get_review_loader(cache) review_stats = loader.REVIEW_STATS_CACHE # recalculate using different default power results = {} for i in [0.5, 0.4, 0.3, 0.2, 0.1, 0.05]: for (key, value) in review_stats.iteritems(): value.dampened_rating = calc_dr(value.rating_spread, power=i) top_rated = loader.get_top_rated_apps(quantity=25) print "For power: %s" % i for (i, key) in enumerate(top_rated): item = review_stats[key] print "%(rang)2i: %(pkgname)-25s avg=%(avg)1.2f total=%(total)03i dampened=%(dampened)1.5f spread=%(spread)s" % { 'rang': i + 1, 'pkgname': item.app.pkgname, 'avg': item.ratings_average, 'total': item.ratings_total, 'spread': item.rating_spread, 'dampened': item.dampened_rating, } print results[i] = top_rated[:]
def __init__(self, bus_name, object_path=DBUS_DATA_PROVIDER_PATH, main_loop=None): dbus.service.Object.__init__(self, bus_name, object_path) self.bus_name = bus_name if main_loop is None: main_loop = GLib.MainLoop(GLib.main_context_default()) self.main_loop = main_loop # the database self.db = StoreDatabase() self.db.open() self.db._aptcache.open(blocking=True) # categories self.categories = CategoriesParser(self.db).parse_applications_menu() # ensure reviews get refreshed self.review_loader = get_review_loader(self.db._aptcache, self.db) self.review_loader.refresh_review_stats() # ensure we query new applications run_software_center_agent(self.db) # setup inactivity timer self._update_activity_timestamp() self._idle_timeout = GLib.timeout_add_seconds(self.IDLE_CHECK_INTERVAL, self._check_inactivity)
def _blocking_perform_search(self): # WARNING this call may run in a thread, so its *not* # allowed to touch gtk, otherwise hell breaks loose # performance only: this is only needed to avoid the # python __call__ overhead for each item if we can avoid it # use a unique instance of both enquire and xapian database # so concurrent queries dont result in an inconsistent database # an alternative would be to serialise queries enquire = xapian.Enquire(self.db.xapiandb) if self.filter and self.filter.required: xfilter = self.filter else: xfilter = None # go over the queries self.nr_apps, self.nr_pkgs = 0, 0 _matches = self._matches match_docids = self.match_docids for q in self.search_query: LOG.debug("initial query: '%s'" % q) # for searches we may want to disable show/hide terms = [term for term in q] exact_pkgname_query = (len(terms) == 1 and terms[0].startswith("XP")) with ExecutionTime("calculate nr_apps and nr_pkgs: "): nr_apps, nr_pkgs = self._get_estimate_nr_apps_and_nr_pkgs(enquire, q, xfilter) self.nr_apps += nr_apps self.nr_pkgs += nr_pkgs # only show apps by default (unless in always visible mode) if self.nonapps_visible != NonAppVisibility.ALWAYS_VISIBLE: if not exact_pkgname_query: q = xapian.Query(xapian.Query.OP_AND, xapian.Query("ATapplication"), q) LOG.debug("nearly completely filtered query: '%s'" % q) # filter out docs of pkgs of which there exists a doc of the app # FIXME: make this configurable again? enquire.set_query(xapian.Query(xapian.Query.OP_AND_NOT, q, xapian.Query("XD"))) # sort results # cataloged time - what's new category if self.sortmode == SortMethods.BY_CATALOGED_TIME: if (self.db._axi_values and "catalogedtime" in self.db._axi_values): enquire.set_sort_by_value( self.db._axi_values["catalogedtime"], reverse=True) else: LOG.warning("no catelogedtime in axi") elif self.sortmode == SortMethods.BY_TOP_RATED: from softwarecenter.backend.reviews import get_review_loader review_loader = get_review_loader(self.cache, self.db) sorter = TopRatedSorter(self.db, review_loader) enquire.set_sort_by_key(sorter, reverse=True) # search ranking - when searching elif self.sortmode == SortMethods.BY_SEARCH_RANKING: #enquire.set_sort_by_value(XapianValues.POPCON) # use the default enquire.set_sort_by_relevance() pass # display name - all categories / channels elif (self.db._axi_values and "display_name" in self.db._axi_values): enquire.set_sort_by_key(LocaleSorter(self.db), reverse=False) # fallback to pkgname - if needed? # fallback to pkgname - if needed? else: enquire.set_sort_by_value_then_relevance( XapianValues.PKGNAME, False) #~ try: if self.limit == 0: matches = enquire.get_mset(0, len(self.db), None, xfilter) else: matches = enquire.get_mset(0, self.limit, None, xfilter) LOG.debug("found ~%i matches" % matches.get_matches_estimated()) #~ except: #~ logging.exception("get_mset") #~ matches = [] # promote exact matches to a "app", this will make the # show/hide technical items work correctly if exact_pkgname_query and len(matches) == 1: self.nr_apps += 1 self.nr_pkgs -= 2 # add matches, but don't duplicate docids with ExecutionTime("append new matches to existing ones:"): for match in matches: if not match.docid in match_docids: _matches.append(match) match_docids.add(match.docid) # if we have no results, try forcing pkgs to be displayed # if not NonAppVisibility.NEVER_VISIBLE is set if (not _matches and self.nonapps_visible not in (NonAppVisibility.ALWAYS_VISIBLE, NonAppVisibility.NEVER_VISIBLE)): self.nonapps_visible = NonAppVisibility.ALWAYS_VISIBLE self._blocking_perform_search() # wake up the UI if run in a search thread self._perform_search_complete = True return
def _blocking_perform_search(self): # WARNING this call may run in a thread, so it's *not* # allowed to touch gtk, otherwise hell breaks loose # performance only: this is only needed to avoid the # python __call__ overhead for each item if we can avoid it # use a unique instance of both enquire and xapian database # so concurrent queries don't result in an inconsistent database # an alternative would be to serialise queries enquire = xapian.Enquire(self.db.xapiandb) if self.filter and self.filter.required: xfilter = self.filter else: xfilter = None # go over the queries self.nr_apps, self.nr_pkgs = 0, 0 _matches = self._matches match_docids = self.match_docids for q in self.search_query: LOG.debug("initial query: '%s'" % q) # for searches we may want to disable show/hide terms = [term for term in q] exact_pkgname_query = (len(terms) == 1 and terms[0].startswith("XP")) # see if we should do a app query and skip the pkg query # see bug #891613 and #1043159 if exact_pkgname_query: with ExecutionTime("de-duplication"): q_app = xapian.Query(terms[0].replace("XP", "AP")) nr_apps, nr_pkgs = self._get_estimate_nr_apps_and_nr_pkgs( enquire, q_app, xfilter) if nr_apps == 1: q = q_app # this is a app query now exact_pkgname_query = False with ExecutionTime("calculate nr_apps and nr_pkgs: "): nr_apps, nr_pkgs = self._get_estimate_nr_apps_and_nr_pkgs( enquire, q, xfilter) self.nr_apps += nr_apps self.nr_pkgs += nr_pkgs # only show apps by default (unless in always visible mode) if self.nonapps_visible != NonAppVisibility.ALWAYS_VISIBLE: if not exact_pkgname_query: q = xapian.Query(xapian.Query.OP_AND, xapian.Query("ATapplication"), q) LOG.debug("nearly completely filtered query: '%s'" % q) # filter out docs of pkgs of which there exists a doc of the app # FIXME: make this configurable again? enquire.set_query(xapian.Query(xapian.Query.OP_AND_NOT, q, xapian.Query("XD"))) # sort results # cataloged time - what's new category if self.sortmode == SortMethods.BY_CATALOGED_TIME: sorter = xapian.MultiValueKeyMaker() if (self.db._axi_values and "catalogedtime" in self.db._axi_values): sorter.add_value( self.db._axi_values["catalogedtime"]) sorter.add_value(XapianValues.DB_CATALOGED_TIME) enquire.set_sort_by_key(sorter, reverse=True) elif self.sortmode == SortMethods.BY_TOP_RATED: from softwarecenter.backend.reviews import get_review_loader review_loader = get_review_loader(self.cache, self.db) sorter = TopRatedSorter(self.db, review_loader) enquire.set_sort_by_key(sorter, reverse=True) # search ranking - when searching elif self.sortmode == SortMethods.BY_SEARCH_RANKING: #enquire.set_sort_by_value(XapianValues.POPCON) # use the default enquire.set_sort_by_relevance() pass # display name - all categories / channels elif (self.db._axi_values and "display_name" in self.db._axi_values): enquire.set_sort_by_key(LocaleSorter(self.db), reverse=False) # fallback to pkgname - if needed? # fallback to pkgname - if needed? else: enquire.set_sort_by_value_then_relevance( XapianValues.PKGNAME, False) #~ try: if self.limit == 0: matches = enquire.get_mset(0, len(self.db), None, xfilter) else: matches = enquire.get_mset(0, self.limit, None, xfilter) LOG.debug("found ~%i matches" % matches.get_matches_estimated()) #~ except: #~ logging.exception("get_mset") #~ matches = [] # promote exact matches to a "app", this will make the # show/hide technical items work correctly if exact_pkgname_query and len(matches) == 1: self.nr_apps += 1 self.nr_pkgs -= 2 # add matches, but don't duplicate docids with ExecutionTime("append new matches to existing ones:"): for match in matches: if not match.docid in match_docids: _matches.append(match) match_docids.add(match.docid) # if we have no results, try forcing pkgs to be displayed # if not NonAppVisibility.NEVER_VISIBLE is set if (not _matches and self.nonapps_visible not in (NonAppVisibility.ALWAYS_VISIBLE, NonAppVisibility.NEVER_VISIBLE)): self.nonapps_visible = NonAppVisibility.ALWAYS_VISIBLE self._blocking_perform_search() # wake up the UI if run in a search thread self._perform_search_complete = True