class AppList(CanvasVBox): __gsignals__ = { "selected" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), "launch" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), "more-info" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) } def __init__(self): super(AppList, self).__init__(padding=6) self.__table = OverviewTable(min_column_width=200, max_column_width=250) self.append(self.__table, hippo.PACK_EXPAND) self.__extras_section = AppExtras(self._filter_app, yalign=hippo.ALIGNMENT_END) self.__extras_section.connect("more-info", lambda e, app: self.emit("more-info", app)) self.append(self.__extras_section) self.__repo = apps.get_apps_repo() self.__search = None self.__all_apps = set() self.__used_apps = set() self.__categorized = None self.__selected_app = None self.__selected_cat = None self.__repo.connect("local-apps-changed", self.__on_apps_changed) self.__repo.connect("my-top-apps-changed", self.__on_apps_changed) self.__repo.connect("global-top-apps-changed", self.__on_apps_changed) self.__repo.connect("all-apps-loaded", lambda repo: self.__on_apps_changed(repo, [])) self.__on_apps_changed(self.__repo, []) ## whatever_apps is ignored, we pass junk for it usually, or whatever the signal ## provides def __on_apps_changed(self, repo, whatever_apps): self.__all_apps = self.__repo.get_all_apps() self.__used_apps = self.__repo.get_my_top_apps() self.__sync_display() @defer_idle_func(logger=_logger) def __sync_display(self): self.__table.remove_all() categories = categorize(filter(self.__filter_app_and_installed_or_used, self.__all_apps)) # _logger.debug(str(categories)) self.__categorized = categories cat_keys = categories.keys() cat_keys.sort() self.__extras_section.set_search_parameters(self.__selected_cat, self.__search) section_key = 0 display_only_used = (len(self.__used_apps) > 0) and (not self.__selected_cat) and (not self.__search) for catname in (self.__selected_cat and not self.__search) and [self.__selected_cat] or cat_keys: cat_used_apps = filter(lambda app: app in self.__used_apps, categories[catname]) cat_used_apps_count = len(cat_used_apps) if display_only_used: right_button = Button() right_button.set_label_text("More (%d)" % (len(categories[catname]) - cat_used_apps_count,)) right_button.connect("activated", self.__handle_category_more, catname) left_link = None else: if self.__selected_cat: left_link = ActionLink(text=u"All Applications /") left_link.connect("activated", self.__handle_nocategory) right_button = Button() right_button.set_label_text("Back") right_button.connect("activated", self.__handle_nocategory) else: right_button = None left_link = None self.__table.add_section_head(section_key, catname, left_control=left_link, right_control=right_button) if display_only_used: appsource = cat_used_apps else: appsource = categories[catname] for app in appsource: overview = apps_widgets.AppDisplay(apps_widgets.AppLocation.APP_BROWSER, app) overview.connect("button-press-event", self.__on_overview_click) self.__table.add_column_item(section_key, overview) section_key += 1 def reset_category(self): self.__handle_nocategory(None) ## called when user chooses "all applications" def __handle_nocategory(self, l): _logger.debug("no category selected") self.__selected_cat = None self.__sync_display() ## called when user clicks a category filter def __handle_category_more(self, l, catname): _logger.debug("category %s selected", catname) self.__selected_cat = catname self.__sync_display() def __filter_app_and_installed_or_used(self, app): if not app.is_installed() and not app in self.__used_apps: return False return self._filter_app(app) def _filter_app(self, app): if not self.__search: return True search = self.__search.lower() keys = (app.get_name(), app.get_description(), app.get_generic_name(), app.get_tooltip()) for key in keys: if key.lower().find(search) >= 0: return True return False def set_search(self, search): if search.strip() == "": self.__search = None else: self.__search = search.lower() self.__sync_display() def __on_overview_click(self, overview, event): _logger.debug("pressed %s %d", overview, event.count) if event.count == 1: if overview == self.__selected_app: self.emit("launch") return if self.__selected_app: self.__selected_app.set_force_prelight(False) app = overview.get_app() self.__selected_app = overview self.__selected_app.set_force_prelight(True) self.emit("selected", app) elif event.count == 2: self.emit("launch")
class FileBrowser(hippo.CanvasWindow): __gsignals__ = { "activated" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) } def __init__(self, stock): super(FileBrowser, self).__init__(gtk.WINDOW_TOPLEVEL) self.__stock = stock self.__single_selected_item = None self.__multiple_items_visible = False self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65535,65535,65535)) self.set_title('Files') self.set_default_size(750, 600) self.__box = CanvasVBox(xalign=hippo.ALIGNMENT_FILL, yalign=hippo.ALIGNMENT_FILL) self.__box.set_property('background-color', 0xEEEEEEFF) browse_box = CanvasHBox(xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START, padding_top=4) self.__box.append(browse_box) browse_text = hippo.CanvasText(text="Browse:", font="Bold 12px", color=0x3F3F3FFF, padding_right=6, xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START) browse_box.append(browse_text) browse_options = CanvasVBox(xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START) browse_box.append(browse_options) local_files_link = ActionLink(text="Local Files", font="14px", padding_bottom=4, xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START) local_files_link.connect("activated", self.__on_browse_local_files_clicked) browse_options.append(local_files_link) for google_account in self.__stock.googles: # don't list invalid accounts we might have picked up from the signons file if google_account.get_current_auth_credentials_known_bad(): continue google_docs_link = ActionLink(text=google_account.get_account().get_username_as_google_email() + " Docs", font="14px", padding_bottom=4, xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START) google_docs_link.connect("activated", webbrowser.open, create_account_url(google_account.get_account().get_username_as_google_email())) browse_options.append(google_docs_link) self.__search_box = CanvasHBox(padding_top=4, padding_bottom=4) self.__search_text = hippo.CanvasText(text="Search Recent Files:", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START, padding_right=4) self.__search_box.append(self.__search_text) self.__search_input = hippo.CanvasEntry(box_width=250) self.__search_input.connect("notify::text", self.__on_search_changed) self.__search_input.connect("key-press-event", self.__on_search_keypress) self.__idle_search_id = 0 self.__search_box.append(self.__search_input) search_local_files_link = ActionLink(text="Search All Local Files", font="14px", padding_left=10) search_local_files_link.connect("activated", self.__on_search_local_files_clicked) self.__search_box.append(search_local_files_link) self.__box.append(self.__search_box) self.__section_head = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, color=0xAAAAAAFF, border_bottom=1, border_color=0xAAAAAAFF) self.__section_head.append(hippo.CanvasText(text="Recent Files", font="Bold 14px", xalign=hippo.ALIGNMENT_START)) self.__box.append(self.__section_head) self.__files_outter_box = CanvasVBox(background_color=0xFFFFFFFF) self.__box.append(self.__files_outter_box, hippo.PACK_EXPAND) self.__right_scroll = hippo.CanvasScrollbars() self.__right_scroll.set_policy(hippo.ORIENTATION_HORIZONTAL, hippo.SCROLLBAR_NEVER) self.__files_box = CanvasVBox(border=0, background_color=0xFFFFFFFF, padding=2) self.__files_outter_box.append(self.__right_scroll, hippo.PACK_EXPAND) self.__file_list = OverviewTable() self.__files_box.append(self.__file_list, hippo.PACK_EXPAND) self.__right_scroll.set_root(self.__files_box) self.__file_items = [] self.refresh_files() self.connect("delete-event", lambda *args: self.__hide() or True) self.connect("key-press-event", lambda win, event: self.__on_keypress(event)) self.set_root(self.__box) def __set_visibility(self, item): search = self.__get_search_text() visible = search == None or item.link.get_property("text").lower().find(search) >= 0 item.set_force_prelight(False) item.set_visible(visible) if self.__single_selected_item is None and visible: self.__single_selected_item = item elif visible: self.__multiple_items_visible = True def __prelight_single_selected_item(self): if not self.__multiple_items_visible and self.__single_selected_item is not None: self.__single_selected_item.set_force_prelight(True) def refresh_files(self): self.__single_selected_item = None self.__multiple_items_visible = False self.__file_list.remove_all() self.__file_items = [] for a_file in self.__stock.get_files(): if a_file.is_valid(): link = a_file.create_icon_link() self.__file_list.add_column_item(0, link) self.__file_items.append(link) self.__set_visibility(link) self.__prelight_single_selected_item() def __on_search_changed(self, input, text): if self.__idle_search_id > 0: return self.__idle_search_id = gobject.timeout_add(500, self.__idle_do_search) def __on_search_keypress(self, entry, event): if event.key == hippo.KEY_RETURN: search = self.__get_search_text() # if there is only one file that matches the search, we'll open it # don't open the file if the search has changed, but we haven't updated the results yet if self.__single_selected_item is not None and (len(self.__stock.get_files()) == 1 or search is not None and self.__single_selected_item.link.get_property("text").lower().find(search) >= 0): self.__single_selected_item.link.emit("activated") def __get_search_text(self): search = self.__search_input.get_property("text") if search.strip() == "": return None else: return search.lower() def __idle_do_search(self): self.__single_selected_item = None self.__multiple_items_visible = False for item in self.__file_items: self.__set_visibility(item) self.__prelight_single_selected_item() self.__idle_search_id = 0 def __on_browse_local_files_clicked(self, canvas_item): subprocess.Popen(['nautilus', '--browser', self.__stock.desktop_path]) def __on_search_local_files_clicked(self, canvas_item): # we don't want to turn "" into None, or change everything to be lowercase search = self.__search_input.get_property("text") if not command_works(['beagle-search', search]): if not command_works(['tracker-search-tool', search]): subprocess.Popen(['gnome-search-tool', '--named', search]) def __on_link_clicked(self, canvas_item, url): subprocess.Popen(['gnome-open', url]) def __hide(self): self.hide() def __on_keypress(self, event): if event.keyval == 65307: self.__hide()