def __init__(self, ga): super(LabelSlideout, self).__init__() vbox = CanvasVBox(border_color=0x0000000ff, spacing=4) self.get_root().append(vbox) header = Header(topborder=False) account_text = ThemedText(theme_hints=['header'], text=ga.name, font="14px Bold") header.append(account_text, hippo.PACK_EXPAND) vbox.append(header) folderCounts = ga.getFolderCounts() folderCounts["unread"] = ga.getUnreadMsgCount() for label, number in folderCounts.iteritems(): box = PrelightingCanvasBox() box.connect('button-release-event', self.on_button_release_event, label) vbox.append(box) hbox = CanvasHBox(spacing=4, padding=4) text= hippo.CanvasText(text=label, xalign=hippo.ALIGNMENT_START) hbox.append(text) text= hippo.CanvasText(text=number, xalign=hippo.ALIGNMENT_START) hbox.append(text, flags=hippo.PACK_END) box.append(hbox)
def __init__(self, track): hippo.CanvasWindow.__init__(self, gtk.WINDOW_POPUP) DataBoundItem.__init__(self, track) self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0xffff,0xffff,0xffff)) root = CanvasHBox(border=1, border_color=0x000000ff) self.set_root(root) box = CanvasHBox(border=5) root.append(box) image = CanvasMugshotURLImage(box_width=track.imageWidth, box_height=track.imageHeight) image.set_url(track.imageUrl) box.append(image) details = CanvasVBox(border_left=6) box.append(details) artist_text = hippo.CanvasText(text=track.artist, font="13px", xalign=hippo.ALIGNMENT_START) details.append(artist_text) title_text = hippo.CanvasText(text=track.name, font="13px", xalign=hippo.ALIGNMENT_START) details.append(title_text)
class PhotosStock(AbstractMugshotStock): SLIDE_TIMEOUT_SEC = 1 * 60 # 1 minute MAX_PREV_IMAGES = 5 """Cycles between photos from friends in Mugshot network""" def __init__(self, *args, **kwargs): super(PhotosStock,self).__init__(*args, **kwargs) self.__images = None self.__images_reverse = [] self.__images_forward = [] self.__current_image = None self.__box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, spacing=4) self.__successive_load_failures = 0 self.__photosize = 120 self.__idle_display_id = 0 self.__text = hippo.CanvasText(text="No thumbnails found") self.__displaymode = "uninitialized" # "none", "photo" self.__displaybox = CanvasVBox(spacing=4) self.__photo_header = CanvasHBox(spacing=4) self.__favicon = CanvasMugshotURLImage() self.__title = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__title.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__photo_header.append(self.__favicon) self.__photo_header.append(self.__title) self.__displaybox.append(self.__photo_header) self.__photobox = CanvasHBox(spacing=6) self.__photo = TransitioningURLImage(self._logger, dimension=self.__photosize) self.__photo.connect("loaded", lambda photo, loaded: self.__on_image_load(loaded)) self.__photo.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__metabox = CanvasVBox() self.__metabox.append(hippo.CanvasText(text="from")) self.__fromphoto = CanvasMugshotURLImage() self.__fromphoto.set_clickable(True) self.__fromphoto.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromphoto) self.__fromname = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__fromname.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromname) self.__photobox.append(self.__photo) self.__photobox.append(self.__metabox) self.__displaybox.append(self.__photobox) self.__controlbox = CanvasHBox() prev_link = ActionLink(text=u"\u00ab Prev", xalign=hippo.ALIGNMENT_START) prev_link.connect("button-press-event", lambda b,e: self.__do_prev()) self.__controlbox.append(prev_link) next_link = ActionLink(text=u"Next \u00bb", xalign=hippo.ALIGNMENT_END) next_link.connect("button-press-event", lambda b,e: self.__do_next()) self.__controlbox.append(next_link, hippo.PACK_EXPAND) self.__displaybox.append(self.__controlbox) self.__person_accts_len = {} # <Person,int> self.__bearbox = CanvasVBox() self.__bearphoto = TransitioningURLImage(self._logger, dimension=self.SIZE_BEAR_CONTENT_PX-6) self.__bearphoto.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__bearbox.append(self.__bearphoto) self._mugshot.connect("network-changed", lambda mugshot: self.__handle_network_change()) def _on_mugshot_ready(self): super(PhotosStock, self)._on_mugshot_ready() self._mugshot.get_network() def get_authed_content(self, size): return size == self.SIZE_BULL and self.__box or self.__bearbox def __visit_photo(self): self._logger.debug("visiting photo for %s", self.__current_image) if not self.__current_image: return libbig.show_url(self.__current_image[2].get_href()) def __visit_person(self): self._logger.debug("visiting person for %s", self.__current_image) if not self.__current_image: return libbig.show_url(mugshot.get_mugshot().get_baseurl() + self.__current_image[0].get_home_url()) def __thumbnails_generator(self): """The infinite photos function. Cool.""" found_one = False while True: for entity in self._mugshot.get_network(): accts = entity.get_external_accounts() if not accts: continue for acct in accts: if acct.get_thumbnails(): for thumbnail in acct.get_thumbnails(): found_one = True yield (entity, acct, thumbnail) if not found_one: return def __next_image(self): if self.__current_image: self.__images_reverse.append(self.__current_image) if len(self.__images_reverse) > self.MAX_PREV_IMAGES: self.__images_reverse.pop(0) if self.__images_forward: return self.__images_forward.pop() else: return self.__images.next() def __prev_image(self): if self.__current_image: self.__images_forward.append(self.__current_image) return self.__images_reverse.pop() def __set_image(self, imageinfo): self.__current_image = imageinfo (entity, acct, thumbnail) = imageinfo self._logger.debug("starting load of url %s" % (thumbnail.get_src(),)) self.__photo.set_url(thumbnail.get_src()) self.__bearphoto.set_url(thumbnail.get_src()) def __on_image_load(self, success): if self.__current_image is None: self._logger.debug("image load complete, but no current image") return if not success: self.__successive_load_failures = max(self.__successive_load_failures+1, 17) self._logger.debug("image load failed, queueing skip to next") gobject.timeout_add(8000 + (2 ** self.__successive_load_failures) * 1000, self.__do_next) else: self.__successive_load_failures = 0 self._logger.debug("image load success, syncing metadata") (entity, acct, thumbnail) = self.__current_image self.__favicon.set_url(acct.get_icon()) self.__title.set_property("text", thumbnail.get_title() or "(untitled)") self.__fromname.set_property("text", entity.get_name()) self.__fromphoto.set_url(entity.get_photo_url()) def __idle_display_image(self): self._logger.debug("in idle, doing next image") self.__idle_display_id = 0 self.__do_next() return False def __handle_person_change(self, person): need_reset = False accts = person.get_external_accounts() if not self.__person_accts_len.has_key(person): need_reset = True self.__person_accts_len[person] = -1 elif accts and self.__person_accts_len[person] != len(accts): self.__person_accts_len[person] = len(accts) need_reset = True if need_reset: self.__reset() def __handle_network_change(self): self._logger.debug("handling network change") for person in self._mugshot.get_network(): if not self.__person_accts_len.has_key(person): person.connect("changed", self.__handle_person_change) accts = person.get_external_accounts() self.__person_accts_len[person] = accts and len(accts) or 0 not_in_network = [] for person in self.__person_accts_len.iterkeys(): if not person in self._mugshot.get_network(): not_in_network.append(person) for person in not_in_network: self._logger.debug("removing not-in-network person %s", person.get_guid()) del self.__person_accts_len[person] self.__reset() def __do_direction(self, is_next): self._logger.debug("skipping to %s" % (is_next and "next" or "prev",)) try: self.__set_image(is_next and self.__next_image() or self.__prev_image()) if self.__displaymode == 'text': self.__box.remove(self.__text) if self.__displaymode != 'photo': self.__box.append(self.__displaybox) self.__displaymode = 'photo' except StopIteration: self._logger.debug("caught StopIteration, displaying no photos text") if self.__displaymode == 'photo': self.__box.remove(self.__displaybox) if self.__displaymode != 'text': self.__box.append(self.__text) self.__displaymode = 'text' if self.__idle_display_id > 0: gobject.source_remove(self.__idle_display_id) self.__idle_display_id = gobject.timeout_add(self.SLIDE_TIMEOUT_SEC * 1000, self.__idle_display_image) def __do_next(self): self.__do_direction(True) def __do_prev(self): self.__do_direction(False) def __reset(self): self._logger.debug("resetting") self.__images = self.__thumbnails_generator() self.__box.remove_all() self.__displaymode = 'uninitialized' self.__do_next()
def __init__(self, fobj): super(FileSlideout, self).__init__() vbox = CanvasVBox(border_color=0x0000000ff, spacing=4) self.get_root().append(vbox) self.__header = Header(topborder=False) text = ThemedText(theme_hints=['header'], text=fobj.get_name(), font="14px Bold", xalign=hippo.ALIGNMENT_START) self.__header.append(text, hippo.PACK_EXPAND) vbox.append(self.__header) hbox = CanvasHBox(spacing=4, padding=4) img = hippo.CanvasImage(scale_width=60, scale_height=60, xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START) img.set_property('image-name', fobj.get_image_name()) hbox.append(img) vbox.append(hbox) detailvbox = CanvasVBox(spacing=3) hbox.append(detailvbox) mime = fobj.get_mimetype() if mime: mimename = gnomevfs.mime_get_description(mime) text = ThemedText(theme_hints=['subforeground'], text=mimename, font='12px', xalign=hippo.ALIGNMENT_START) detailvbox.append(text) size = fobj.get_size() if size is not None: sizestr = format_file_size(size) text = ThemedText(theme_hints=['subforeground'], text=sizestr, font='12px', xalign=hippo.ALIGNMENT_START) detailvbox.append(text) fname = os.path.dirname(fobj.get_full_name()) if fname.startswith('file://'): fname = fname[7:] home = os.path.expanduser('~') if fname.startswith(home): fname = fname[:len(home)] fname = urllib.unquote(fname) text = ThemedText(theme_hints=['subforeground'], text=fname, font='12px', xalign=hippo.ALIGNMENT_START) detailvbox.append(text) apps = gnomevfs.mime_get_all_applications(mime) if apps: text = ThemedText(text='Open With: ', font='14px') detailvbox.append(text) def on_app_clicked(button, app): self.emit('close', True) _logger.debug("launching app %s", app) _launch_vfsmimeapp(app, fobj.get_url()) directory = apps_directory.get_app_directory() for app in apps: _logger.debug("mime type: %s got app %s", mime, app) button = hippo.CanvasButton() labelhbox = gtk.HBox() labelhbox.set_border_width(1) labelhbox.set_spacing(2) try: menu = directory.lookup(app[0]) except KeyError, e: _logger.debug("failed to find desktop file %s", app[0]) menu = None img = gtk.Image() if menu: pixbuf = get_menu_pixbuf(menu, size=16) img.set_from_pixbuf(pixbuf) else: img.set_size_request(16, 16) labelhbox.pack_start(img, False, False) textlabel = gtk.Label(app[1]) labelhbox.pack_start(textlabel, False) labelhbox.show_all() button.get_property('widget').add(labelhbox) button.get_property('widget').connect('clicked', on_app_clicked, app) button.get_property('widget').set_name('bigboard-nopad-button') detailvbox.append(button)
class PhotosStock(AbstractMugshotStock): SLIDE_TIMEOUT_SEC = 1 * 60 # 1 minute MAX_PREV_IMAGES = 5 """Cycles between photos from friends in Mugshot network""" def __init__(self, *args, **kwargs): super(PhotosStock, self).__init__(*args, **kwargs) self.__images = None self.__images_reverse = [] self.__images_forward = [] self.__current_image = None self.__box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, spacing=4) self.__successive_load_failures = 0 self.__photosize = 120 self.__idle_display_id = 0 self.__text = hippo.CanvasText(text="No thumbnails found") self.__displaymode = "uninitialized" # "none", "photo" self.__displaybox = CanvasVBox(spacing=4) self.__photo_header = CanvasHBox(spacing=4) self.__favicon = CanvasMugshotURLImage() self.__title = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__title.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__photo_header.append(self.__favicon) self.__photo_header.append(self.__title) self.__displaybox.append(self.__photo_header) self.__photobox = CanvasHBox(spacing=6) self.__photo = TransitioningURLImage(dimension=self.__photosize) self.__photo.connect("loaded", lambda photo, loaded: self.__on_image_load(loaded)) self.__photo.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__metabox = CanvasVBox() self.__metabox.append(hippo.CanvasText(text="from")) self.__fromphoto = CanvasMugshotURLImage() self.__fromphoto.set_clickable(True) self.__fromphoto.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromphoto) self.__fromname = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__fromname.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromname) self.__photobox.append(self.__photo) self.__photobox.append(self.__metabox) self.__displaybox.append(self.__photobox) self.__controlbox = CanvasHBox() prev_link = ActionLink(text=u"\u00ab Prev", xalign=hippo.ALIGNMENT_START) prev_link.connect("button-press-event", lambda b, e: self.__do_prev()) self.__controlbox.append(prev_link) next_link = ActionLink(text=u"Next \u00bb", xalign=hippo.ALIGNMENT_END) next_link.connect("button-press-event", lambda b, e: self.__do_next()) self.__controlbox.append(next_link, hippo.PACK_EXPAND) self.__displaybox.append(self.__controlbox) self.__person_accts_len = {} # <Person,int> self.__bearbox = CanvasVBox() self.__bearphoto = TransitioningURLImage(dimension=self.SIZE_BEAR_CONTENT_PX - 6) self.__bearphoto.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__bearbox.append(self.__bearphoto) def _on_ready(self): if self._model.self_resource != None: query = self._model.query_resource( self._model.self_resource, "contacts user [+;lovedAccounts [+;thumbnails +]]" ) query.add_handler(self.__on_got_self) query.execute() def __on_got_self(self, myself): self.__reset() def get_authed_content(self, size): return size == self.SIZE_BULL and self.__box or self.__bearbox def __visit_photo(self): _logger.debug("visiting photo for %s", self.__current_image) if not self.__current_image: return libbig.show_url(self.__current_image[2].get_href()) def __visit_person(self): _logger.debug("visiting person for %s", self.__current_image) if not self.__current_image: return libbig.show_url(urlparse.urljoin(globals.get_baseurl(), self.__current_image[0].get_home_url())) def __thumbnails_generator(self): """The infinite photos function. Cool.""" while True: found_one = False # Iterate through all thumbnails for all "loved accounts" for all contacts. # We don't handle change notification ... if something changes we'll pick # it up next time around. Note the use of temporary copies of lists to avoid # problems if a list is mutated by a change notification while we are iterating it. if self._model.self_resource: for contact in list(getattr(self._model.self_resource, "contacts", [])): user = getattr(contact, "user", None) if user != None: lovedAccounts = getattr(user, "lovedAccounts", None) if lovedAccounts: for externalAccount in lovedAccounts: thumbnails = getattr(externalAccount, "thumbnails", None) if thumbnails: for thumbnail in thumbnails: yield (user, externalAccount, thumbnail) # If we didn't find any photos, we go into a "no photos" state; we'll keep on trying # to restart the iterator in the timeout, so when things appear we'll display them if not found_one: return def __next_image(self): if self.__current_image: self.__images_reverse.append(self.__current_image) if len(self.__images_reverse) > self.MAX_PREV_IMAGES: self.__images_reverse.pop(0) if self.__images_forward: return self.__images_forward.pop() else: return self.__images.next() def __prev_image(self): if self.__current_image: self.__images_forward.append(self.__current_image) return self.__images_reverse.pop() def __set_image(self, imageinfo): self.__current_image = imageinfo (user, account, thumbnail) = imageinfo _logger.debug("starting load of url %s" % (thumbnail.src,)) self.__photo.set_url(thumbnail.src) self.__bearphoto.set_url(thumbnail.src) def __on_image_load(self, success): if self.__current_image is None: _logger.debug("image load complete, but no current image") return if not success: self.__successive_load_failures = max(self.__successive_load_failures + 1, 17) _logger.debug("image load failed, queueing skip to next") gobject.timeout_add(8000 + (2 ** self.__successive_load_failures) * 1000, self.__do_next) else: self.__successive_load_failures = 0 _logger.debug("image load success, syncing metadata") (user, account, thumbnail) = self.__current_image self.__favicon.set_url(account.iconUrl) title = getattr(thumbnail, "title", None) if not title: title = "(untitled)" self.__title.set_property("text", title) self.__fromname.set_property("text", user.name) self.__fromphoto.set_url(user.photoUrl) def __idle_display_image(self): _logger.debug("in idle, doing next image") self.__idle_display_id = 0 self.__do_next() return False def __do_direction(self, is_next): _logger.debug("skipping to %s" % (is_next and "next" or "prev",)) try: self.__set_image(is_next and self.__next_image() or self.__prev_image()) if self.__displaymode == "text": self.__box.remove(self.__text) if self.__displaymode != "photo": self.__box.append(self.__displaybox) self.__displaymode = "photo" except StopIteration: _logger.debug("caught StopIteration, displaying no photos text") if self.__displaymode == "photo": self.__box.remove(self.__displaybox) if self.__displaymode != "text": self.__box.append(self.__text) self.__displaymode = "text" if self.__idle_display_id > 0: gobject.source_remove(self.__idle_display_id) self.__idle_display_id = gobject.timeout_add(self.SLIDE_TIMEOUT_SEC * 1000, self.__idle_display_image) def __do_next(self): self.__do_direction(True) def __do_prev(self): self.__do_direction(False) def __reset(self): _logger.debug("resetting") self.__images = self.__thumbnails_generator() self.__images_reverse = [] self.__box.remove_all() self.__displaymode = "uninitialized" self.__do_next()
class PersonItem(PhotoContentItem): def __init__(self, person, themed=False, **kwargs): PhotoContentItem.__init__(self, **kwargs) self.person = person self.__themed = themed if themed: self.set_themed() model = DataModel(bigboard.globals.server_name) self.set_clickable(True) self.__photo = CanvasMugshotURLImage(scale_width=45, scale_height=45, border=1, border_color=0x000000ff) self.set_photo(self.__photo) self.__details_box = CanvasVBox() self.set_child(self.__details_box) nameklass = themed and ThemedText or hippo.CanvasText self.__name = nameklass(xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__details_box.append(self.__name) self.__presence_box = CanvasHBox(spacing=4) self.__details_box.append(self.__presence_box) self.__statuses = [] self.__status_box = CanvasHBox() self.__details_box.append(self.__status_box) self.connect('button-press-event', self.__handle_button_press) self.connect('button-release-event', self.__handle_button_release) self.__pressed = False self.__aim_icon = None self.__xmpp_icon = None self.__current_track = None self.__current_track_timeout = None if self.person.is_contact: try: user = self.person.resource.user except AttributeError: user = None if user: query = model.query_resource(user, "currentTrack +;currentTrackPlayTime") query.execute() user.connect(self.__update_current_track, 'currentTrack') user.connect(self.__update_current_track, 'currentTrackPlayTime') self.__update_current_track(user) self.person.connect('display-name-changed', self.__update) self.person.connect('icon-url-changed', self.__update) self.person.connect('aim-buddy-changed', self.__update_aim_buddy) self.person.connect('xmpp-buddy-changed', self.__update_xmpp_buddy) self.__update(self.person) self.__update_aim_buddy(self.person) self.__update_xmpp_buddy(self.person) def __update_color(self): if self.__pressed: self.set_property('background-color', 0x00000088) else: self.sync_prelight_color() def __handle_button_press(self, self2, event): if event.button != 1 or event.count != 1: return False self.__pressed = True self.__update_color() return False def __handle_button_release(self, self2, event): if event.button != 1: return False self.__pressed = False self.__update_color() return False def get_person(self): return self.person def set_size(self, size): if size == bigboard.stock.SIZE_BULL: self.set_child_visible(self.__details_box, True) self.__photo.set_property('xalign', hippo.ALIGNMENT_START) self.__photo.set_property('yalign', hippo.ALIGNMENT_START) else: self.set_child_visible(self.__details_box, False) self.__photo.set_property('xalign', hippo.ALIGNMENT_CENTER) self.__photo.set_property('yalign', hippo.ALIGNMENT_CENTER) def __update(self, person): self.__name.set_property("text", self.person.display_name) #+ " " + str(self.person._debug_rank)) self.__photo.set_url(self.person.icon_url) def __reset_im_status(self): buddies = self.person.aim_buddies + self.person.xmpp_buddies if len(buddies) > 0: sm = StatusMessage(themed=self.__themed) sm.set_buddies(buddies) self.__set_status(STATUS_IM, sm) def __update_aim_buddy(self, person): if person.aim_buddy: if not self.__aim_icon: self.__aim_icon = AimIcon(person.aim_buddy, theme_hints=(not self.__themed and 'notheme' or [])) self.__presence_box.append(self.__aim_icon) else: if self.__aim_icon: self.__aim_icon.destroy() self.__aim_icon = None self.__reset_im_status() def __update_xmpp_buddy(self, person): if person.xmpp_buddy: if not self.__xmpp_icon: self.__xmpp_icon = XMPPIcon(person.xmpp_buddy, theme_hints=(not self.__themed and 'notheme' or [])) self.__presence_box.append(self.__xmpp_icon) else: if self.__xmpp_icon: self.__xmpp_icon.destroy() self.__xmpp_icon = None self.__reset_im_status() def __timeout_track(self): self.__current_track_timeout = None self.__update_current_track(self.person.resource.user) return False def __update_current_track(self, user): try: current_track = user.currentTrack current_track_play_time = user.currentTrackPlayTime / 1000. except AttributeError: current_track = None current_track_play_time = -1 _logger.debug("current track %s" % str(current_track)) # current_track_play_time < 0, current_track != None might indicate stale # current_track data if current_track_play_time < 0: current_track = None if current_track != None: now = time.time() if current_track.duration < 0: endTime = current_track_play_time + 30 * 60 # Half hour else: endTime = current_track_play_time + current_track.duration / 1000. # msec => sec if now >= endTime: current_track = None if current_track != self.__current_track: self.__current_track = current_track if self.__current_track_timeout: gobject.source_remove(self.__current_track_timeout) if current_track != None: # We give 30 seconds of lee-way, so that the track is pretty reliably really stopped self.__current_track_timeout = gobject.timeout_add(int((endTime + 30 - now) * 1000), self.__timeout_track) if current_track != None: self.__set_status(STATUS_MUSIC, TrackItem(current_track)) else: self.__set_status(STATUS_MUSIC, None) def __set_status(self, type, contents): if len(self.__statuses) > 0: old_contents = self.__statuses[0][1] else: old_contents = None for i in range(0,len(self.__statuses)): (i_type,i_contents) = self.__statuses[i] if i_type == type: i_contents.destroy() del self.__statuses[i] if i == 0: old_contents = None break if old_contents != None: old_contents.set_visible(False) if contents != None: self.__statuses.insert(0, (type, contents)) self.__status_box.append(contents) if len(self.__statuses) > 0: new_contents = self.__statuses[0][1] new_contents.set_visible(True) def get_screen_coords(self): return self.get_context().translate_to_screen(self)
def __init__(self): super(AppBrowser, self).__init__(gtk.WINDOW_TOPLEVEL) self.__repo = apps.get_apps_repo() self.__all_apps = [] self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65535,65535,65535)) self.set_title('Applications') self.__box = CanvasHBox() self.__left_box = CanvasVBox(spacing=6, padding=6, box_width=250) self.__left_box.set_property('background-color', 0xEEEEEEFF) self.__box.append(self.__left_box) self.__search_text = hippo.CanvasText(text="Search All Applications:", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START) self.__left_box.append(self.__search_text) self.__search_input = hippo.CanvasEntry() #self.__search_input.set_property('border-color', 0xAAAAAAFF) self.__search_input.connect("notify::text", self.__on_search_changed) self.__idle_search_id = 0 self.__left_box.append(self.__search_input) self.__overview = AppOverview() self.__overview.connect("more-info", lambda o, app: self.__on_show_more_info(app)) self.__overview.connect("toggle-pinned", lambda o, app, active: self.__on_toggle_app_pinned(app, active)) self.__overview.connect("move-up", lambda o, app: self.__on_move_app(app, True)) self.__overview.connect("move-down", lambda o, app: self.__on_move_app(app, False)) self.__overview.get_header().connect("button-press-event", lambda l,e: self.__on_app_launch()) self.__overview.get_action_button().connect("activated", lambda l: self.__on_app_launch()) self.__left_box.append(self.__overview) self.__cat_usage = AppCategoryUsage() self.__left_box.append(self.__cat_usage) self.__left_box.append(hippo.CanvasText(text="Tools", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START)) browse_link = ActionLink(text="Find New Applications", underline=pango.UNDERLINE_LOW, xalign=hippo.ALIGNMENT_START) browse_link.connect("button-press-event", lambda l,e: self.__on_browse_popular_apps()) self.__left_box.append(browse_link) spinbox = CanvasHBox() spinbox.append(hippo.CanvasText(text='Visible applications: ')) self.__apps_spinner = CanvasSpinner() gconf.client_get_default().notify_add(GCONF_KEY_APP_SIZE, self.__on_visible_apps_key_changed) self.__apps_spinner.spinner.connect('value-changed', self.__on_visible_apps_spin_changed) self.__apps_spinner.spinner.get_adjustment().set_all(gconf.client_get_default().get_int(GCONF_KEY_APP_SIZE), 1, 20, 1, 1, 1) spinbox.append(self.__apps_spinner) self.__left_box.append(spinbox) self.__right_scroll = hippo.CanvasScrollbars() self.__right_scroll.set_policy(hippo.ORIENTATION_HORIZONTAL, hippo.SCROLLBAR_NEVER) self.__right_box = CanvasVBox(border=0, background_color=0xFFFFFFFF) self.__box.append(self.__right_scroll, hippo.PACK_EXPAND) self.__app_list = AppList() self.__right_box.append(self.__app_list, hippo.PACK_EXPAND) self.__app_list.connect("selected", lambda list, app: self.__on_app_selected(app)) self.__app_list.connect("launch", lambda list: self.__on_app_launch()) self.__app_list.connect("more-info", lambda list, app: self.__on_show_more_info(app)) self.__right_scroll.set_root(self.__right_box) self.set_default_size(1000, 600) self.connect("delete-event", lambda *args: self.__hide_reset() or True) self.connect("key-press-event", lambda win, event: self.__on_keypress(event)) self.set_root(self.__box) self.__repo.connect("my-pinned-apps-changed", self.__on_pinned_apps_changed)
class AppBrowser(hippo.CanvasWindow): def __init__(self): super(AppBrowser, self).__init__(gtk.WINDOW_TOPLEVEL) self.__repo = apps.get_apps_repo() self.__all_apps = [] self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65535,65535,65535)) self.set_title('Applications') self.__box = CanvasHBox() self.__left_box = CanvasVBox(spacing=6, padding=6, box_width=250) self.__left_box.set_property('background-color', 0xEEEEEEFF) self.__box.append(self.__left_box) self.__search_text = hippo.CanvasText(text="Search All Applications:", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START) self.__left_box.append(self.__search_text) self.__search_input = hippo.CanvasEntry() #self.__search_input.set_property('border-color', 0xAAAAAAFF) self.__search_input.connect("notify::text", self.__on_search_changed) self.__idle_search_id = 0 self.__left_box.append(self.__search_input) self.__overview = AppOverview() self.__overview.connect("more-info", lambda o, app: self.__on_show_more_info(app)) self.__overview.connect("toggle-pinned", lambda o, app, active: self.__on_toggle_app_pinned(app, active)) self.__overview.connect("move-up", lambda o, app: self.__on_move_app(app, True)) self.__overview.connect("move-down", lambda o, app: self.__on_move_app(app, False)) self.__overview.get_header().connect("button-press-event", lambda l,e: self.__on_app_launch()) self.__overview.get_action_button().connect("activated", lambda l: self.__on_app_launch()) self.__left_box.append(self.__overview) self.__cat_usage = AppCategoryUsage() self.__left_box.append(self.__cat_usage) self.__left_box.append(hippo.CanvasText(text="Tools", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START)) browse_link = ActionLink(text="Find New Applications", underline=pango.UNDERLINE_LOW, xalign=hippo.ALIGNMENT_START) browse_link.connect("button-press-event", lambda l,e: self.__on_browse_popular_apps()) self.__left_box.append(browse_link) spinbox = CanvasHBox() spinbox.append(hippo.CanvasText(text='Visible applications: ')) self.__apps_spinner = CanvasSpinner() gconf.client_get_default().notify_add(GCONF_KEY_APP_SIZE, self.__on_visible_apps_key_changed) self.__apps_spinner.spinner.connect('value-changed', self.__on_visible_apps_spin_changed) self.__apps_spinner.spinner.get_adjustment().set_all(gconf.client_get_default().get_int(GCONF_KEY_APP_SIZE), 1, 20, 1, 1, 1) spinbox.append(self.__apps_spinner) self.__left_box.append(spinbox) self.__right_scroll = hippo.CanvasScrollbars() self.__right_scroll.set_policy(hippo.ORIENTATION_HORIZONTAL, hippo.SCROLLBAR_NEVER) self.__right_box = CanvasVBox(border=0, background_color=0xFFFFFFFF) self.__box.append(self.__right_scroll, hippo.PACK_EXPAND) self.__app_list = AppList() self.__right_box.append(self.__app_list, hippo.PACK_EXPAND) self.__app_list.connect("selected", lambda list, app: self.__on_app_selected(app)) self.__app_list.connect("launch", lambda list: self.__on_app_launch()) self.__app_list.connect("more-info", lambda list, app: self.__on_show_more_info(app)) self.__right_scroll.set_root(self.__right_box) self.set_default_size(1000, 600) self.connect("delete-event", lambda *args: self.__hide_reset() or True) self.connect("key-press-event", lambda win, event: self.__on_keypress(event)) self.set_root(self.__box) self.__repo.connect("my-pinned-apps-changed", self.__on_pinned_apps_changed) @defer_idle_func(logger=_logger) def __on_visible_apps_spin_changed(self, *args): _logger.debug("spinner changed") count = self.__apps_spinner.spinner.get_value() curval = gconf.client_get_default().get_int(GCONF_KEY_APP_SIZE) or 4 if curval != count: gconf.client_get_default().set_int(GCONF_KEY_APP_SIZE, int(count)) def __on_visible_apps_key_changed(self, *args): _logger.debug("apps count key changed") curval = gconf.client_get_default().get_int(GCONF_KEY_APP_SIZE) or 4 if curval != self.__apps_spinner.spinner.get_value(): self.__apps_spinner.set_value(curval) def __on_app_selected(self, app): self.__overview.set_app(app) def __reset(self): self.__search_input.set_property('text', '') self.__app_list.reset_category() def __hide_reset(self): self.__reset() self.hide() @log_except(_logger) def __on_show_more_info(self, app): if app: _logger.debug("showing app: %s", app) libbig.show_url(urlparse.urljoin(globals.get_baseurl(), "application?id=" + app.get_id())) self.__hide_reset() def __on_toggle_app_pinned(self, app, active): _logger.debug("Toggle app " + app.get_id() + " pinned = " + str(active)) self.__repo.set_app_pinned(app, active) def __on_move_app(self, app, up): _logger.debug("Move app up= " + str(up)) if up: pass else: pass def __on_app_launch(self): self.__overview.launch() self.__hide_reset() def __on_keypress(self, event): if event.keyval == 65307: self.__hide_reset() def __on_browse_popular_apps(self): libbig.show_url(urlparse.urljoin(globals.get_baseurl(), "applications")) self.__hide_reset() def __on_search_changed(self, input, text): if self.__idle_search_id > 0: return self.__idle_search_id = gobject.timeout_add(1500, self.__idle_do_search) def __idle_do_search(self): search_terms = self.__search_input.get_property("text") _logger.debug("Search terms: " + str(search_terms)) self.__app_list.set_search(search_terms) self.__idle_search_id = 0 def __on_pinned_apps_changed(self, mugshot, pinned_apps): _logger.debug("Pinned apps changed: " + str(map(lambda x: x.get_id(), pinned_apps))) self.__overview.sync_pinned_checkbox()
class AppExtras(CanvasVBox): __gsignals__ = { "more-info" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) } def __init__(self, filterfunc, **args): super(AppExtras, self).__init__(background_color=0xFFF9DDFF, color=0x3F3F3FFF, **args) self.__search = False self.__search_filter = filterfunc self.__catname = None self.__apps = None self.__have_search_hits = False self.__found_app_count = 0 self.__headerbox = CanvasHBox(padding=6) self.append(self.__headerbox) thing = self.__get_section_name() self.__left_title = hippo.CanvasText(text="New Popular %s" % (thing,), font="12px Bold", xalign=hippo.ALIGNMENT_START) self.__headerbox.append(self.__left_title) # TODO this won't underline properly until ActionLink->set_underline listens for text changes # underline=pango.UNDERLINE_LOW self.__right_title = ActionLink(font="12px", xalign=hippo.ALIGNMENT_END) self.__right_title.connect("activated", self.__on_more_popular) self.__headerbox.append(self.__right_title, hippo.PACK_EXPAND) self.__app_pair = CanvasHBox(box_height=120) self.__app_pair2 = CanvasHBox(box_height=120) self.append(self.__app_pair) self.append(self.__app_pair2) self.__repo = apps.get_apps_repo() def __get_section_name(self): return self.__catname or 'Apps' def have_apps(self): return not not self.__found_app_count def __on_search_results(self, applications, category, search_terms): _logger.debug("Got %d search results for category '%s' terms '%s'" % (len(applications), str(category), str(search_terms))) if search_terms != self.__search or category != self.__catname: _logger.debug("Search terms have changed since starting search, ignoring results") return if search_terms is not None: self.__have_search_hits = len(applications) > 0 else: self.__have_search_hits = False self.__apps = applications self.__sync() def set_search_parameters(self, catname, search): if self.__catname != catname or self.__search != search: self.__catname = catname self.__search = search self.__repo.search(self.__catname, self.__search, self.__on_search_results) def __on_more_popular(self, w): subquery = (self.__search and ("?q=" + urllib.quote(self.__search))) \ or self.__catname and ("?category=" + urllib.quote(self.__catname)) \ or '' libbig.show_url(urlparse.urljoin(globals.get_baseurl(), "applications%s" % (subquery,))) # more-info with None just means hide window self.emit("more-info", None) def __sync(self): thing = self.__get_section_name() if self.__apps: if self.__search: if self.__have_search_hits: self.__left_title.set_property('markup', "Searching for <b>%s</b>" % (gobject.markup_escape_text(self.__search),)) else: self.__left_title.set_property('markup', "No results for <b>%s</b>" % (gobject.markup_escape_text(self.__search),)) else: self.__left_title.set_property('text', "New Popular %s" % (thing,)) self.__right_title.set_property('text', u"More Popular %s" % (thing,)) elif self.__apps is None: self.__left_title.set_property('text', '') self.__right_title.set_property("text", "Loading popular %s..." % (thing,)) else: self.__left_title.set_property('text', '') self.__right_title.set_property("text", "No popular %s found" % (thing,)) self.__app_pair.clear() self.__app_pair2.clear() self.set_child_visible(self.__app_pair, not not self.__apps) found = 0 for i,app in enumerate(self.__apps or []): if app.is_installed(): continue if self.__search_filter and (not self.__search_filter(app)): continue app_view = apps_widgets.AppDisplay(apps_widgets.AppLocation.APP_BROWSER, app, color=0x3F3F3FFF) app_view.connect("title-clicked", self.__on_app_clicked) app_view.set_description_mode(True) if found > 1: self.__app_pair2.append(app_view, hippo.PACK_EXPAND) else: self.__app_pair.append(app_view, hippo.PACK_EXPAND) found += 1 if found > 3: break self.set_child_visible(self.__app_pair, found > 0) self.set_child_visible(self.__app_pair2, found > 2 and (not not self.__search)) self.__found_app_count = found def __on_app_clicked(self, app_view): self.emit("more-info", app_view.get_app())
class AppOverview(CanvasVBox): __gsignals__ = { "more-info" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), "toggle-pinned" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN,)), "move-up" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), "move-down" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) } def __init__(self, app=None): super(AppOverview, self).__init__(xalign=hippo.ALIGNMENT_FILL, yalign=hippo.ALIGNMENT_FILL, box_width=200, box_height=260, border=1, border_color=0xAAAAAAFF, background_color=0xFFFFFFFF, padding=5) self.__unselected = True self.__app_unselected_text = hippo.CanvasText(text="Click an application to see its description here.\n\nDouble-click to launch.", size_mode=hippo.CANVAS_SIZE_WRAP_WORD, xalign=hippo.ALIGNMENT_CENTER, yalign=hippo.ALIGNMENT_CENTER, color=0x3F3F3FFF) self.append(self.__app_unselected_text, hippo.PACK_CLEAR_RIGHT) self.__header = apps_widgets.AppDisplay(apps_widgets.AppLocation.DESCRIPTION_HEADER) self.__description = hippo.CanvasText(font="12px",size_mode=hippo.CANVAS_SIZE_WRAP_WORD) self.__controls_box = CanvasVBox(xalign=hippo.ALIGNMENT_START, yalign=hippo.ALIGNMENT_END) self.__icon_button_combo = CanvasHBox(spacing=4, padding_bottom=4) self.__action_button_image = hippo.CanvasImage(scale_width=16, scale_height=16, xalign=hippo.ALIGNMENT_CENTER, yalign=hippo.ALIGNMENT_CENTER) self.__icon_button_combo.append(self.__action_button_image) self.__action_button = Button(label_xpadding=10) self.__action_button.set_property("xalign", hippo.ALIGNMENT_START) self.__action_button.get_button().set_focus_on_click(False) self.__icon_button_combo.append(self.__action_button) self.__controls_box.append(self.__icon_button_combo) self.__more_info = IconLink(text="More Info", prelight=False, img_scale_width=16, img_scale_height=16, spacing=2, underline=pango.UNDERLINE_LOW, xalign=hippo.ALIGNMENT_START) self.__more_info.link.connect("button-press-event", lambda l,e: self.emit("more-info", self.__app)) self.__more_info.img.set_property('image-name', '/usr/share/icons/gnome/16x16/status/info.png') self.__controls_box.append(self.__more_info) self.__check_showing = CanvasCheckbox("Show in sidebar") self.__check_showing.checkbox.connect('toggled', self.__on_show_in_sidebar_toggled) self.__controls_box.append(self.__check_showing) self.__up_button = hippo.CanvasLink(text="Up", border_right=10) self.__down_button = hippo.CanvasLink(text="Down") self.__up_down_controls = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.__up_down_controls.append(self.__up_button) self.__up_down_controls.append(self.__down_button) self.__up_button.connect("activated", lambda ci: self.emit("move-up", self.__app)) self.__down_button.connect("activated", lambda ci: self.emit("move-down", self.__app)) # FIXME - don't show up-down controls until they work #self.__controls_box.append(self.__up_down_controls) self.__app = None if app: self.set_app(app) def __on_show_in_sidebar_toggled(self, checkbox): active = checkbox.get_active() _logger.debug("Checkbox toggled, active = " + str(active)) if self.__app: pinned = self.__app.get_pinned() _logger.debug("App is currently pinned = " + str(pinned)) if active != pinned: self.emit("toggle-pinned", self.__app, active) def sync_pinned_checkbox(self): _logger.debug("Syncing pinned checkbox") if self.__app: _logger.debug(str(self.__app) + " pinned: " + str(self.__app.get_pinned())) self.__controls_box.set_child_visible(self.__check_showing, not self.__app.is_local()) self.__check_showing.checkbox.set_active(self.__app.get_pinned()) def set_app(self, app): if self.__unselected: self.__unselected = False self.remove(self.__app_unselected_text) self.append(self.__header) self.append(self.__description) self.append(self.__controls_box, hippo.PACK_EXPAND) self.__app = app self.__header.set_app(app) self.__description.set_property("text", app.get_description()) self.sync_pinned_checkbox() self.__controls_box.set_child_visible(self.__more_info, not self.__app.is_local()) if app.is_installed(): self.__action_button_image.set_property("image-name", "/usr/share/icons/gnome/16x16/actions/gnome-run.png") self.__action_button.set_label_text("Run...") else: self.__action_button_image.set_property("image-name", "/usr/share/icons/gnome/16x16/apps/system-software-installer.png") self.__action_button.set_label_text("Install...") def launch(self): return self.__header.launch() def get_app(self): return self.__app def get_header(self): return self.__header def get_action_button(self): return self.__action_button
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)
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()
class PeopleBrowser(hippo.CanvasWindow): def __init__(self, stock): super(PeopleBrowser, self).__init__(gtk.WINDOW_TOPLEVEL) self.__stock = stock self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65535,65535,65535)) self.set_title('People') self.__box = CanvasHBox() self.__left_box = CanvasVBox(spacing=6, padding=6, box_width=250) self.__left_box.set_property('background-color', 0xEEEEEEFF) self.__box.append(self.__left_box) self.__search_text = hippo.CanvasText(text="Search People:", font="Bold 12px", color=0x3F3F3FFF, xalign=hippo.ALIGNMENT_START) self.__left_box.append(self.__search_text) self.__search_input = hippo.CanvasEntry() #self.__search_input.set_property('border-color', 0xAAAAAAFF) 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.__left_box.append(self.__search_input) self.__profile_box = CanvasVBox(border=1, border_color=0x999999FF, background_color=0xFFFFFFFF) self.__left_box.append(self.__profile_box) self.__set_profile_person(None) self.__right_scroll = hippo.CanvasScrollbars() self.__right_scroll.set_policy(hippo.ORIENTATION_HORIZONTAL, hippo.SCROLLBAR_NEVER) self.__right_box = CanvasVBox(border=0, background_color=0xFFFFFFFF) self.__box.append(self.__right_scroll, hippo.PACK_EXPAND) self.__people_list = PeopleList() self.__right_box.append(self.__people_list, hippo.PACK_EXPAND) self.__people_list.connect("selected", self.__on_person_selected) self.__right_scroll.set_root(self.__right_box) self.set_default_size(750, 600) self.connect("delete-event", lambda *args: self.__hide_reset() or True) self.connect("key-press-event", lambda win, event: self.__on_keypress(event)) self.set_root(self.__box) self.__tracker = PeopleTracker() self.__tracker.contacts.connect("added", self.__on_contact_added) self.__tracker.contacts.connect("removed", self.__on_contact_removed) self.__tracker.local_people.connect("added", self.__on_local_person_added) self.__tracker.local_people.connect("removed", self.__on_local_person_removed) self.__tracker.aim_people.connect("added", self.__on_aim_person_added) self.__tracker.aim_people.connect("removed", self.__on_aim_person_removed) self.__tracker.xmpp_people.connect("added", self.__on_xmpp_person_added) self.__tracker.xmpp_people.connect("removed", self.__on_xmpp_person_removed) self.__model = DataModel(bigboard.globals.server_name) for person in self.__tracker.contacts: self.__on_contact_added(self.__tracker.contacts, person) for person in self.__tracker.local_people: self.__on_local_person_added(self.__tracker.local_people, person) for person in self.__tracker.aim_people: self.__on_aim_person_added(self.__tracker.aim_people, person) for person in self.__tracker.xmpp_people: self.__on_xmpp_person_added(self.__tracker.xmpp_people, person) def __set_profile_person(self, person): self.__profile_box.clear() if person == None: self.__profile_box.set_property("box-height", 300) else: self.__profile_box.set_property("box_height", -1) self.__profile_box.append(ProfileItem(person)) def __reset(self): self.__search_input.set_property('text', '') def __hide_reset(self): self.__reset() self.hide() def __idle_do_search(self): self.__people_list.set_search(self.__search_input.get_property("text")) self.__idle_search_id = 0 def __on_keypress(self, event): if event.keyval == 65307: self.__hide_reset() 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: self.__people_list.select_single_visible_person() def __on_person_selected(self, list, person): self.__set_profile_person(person) def __on_contact_added(self, list, contact): self.__people_list.add_person(contact, CONTACTS) def __on_contact_removed(self, list, contact): self.__people_list.remove_person(contact, CONTACTS) def __on_local_person_added(self, list, person): if person == self.__model.self_resource: return self.__people_list.add_person(person, LOCAL_PEOPLE) def __on_local_person_removed(self, list, person): self.__people_list.remove_person(person, LOCAL_PEOPLE) def __on_aim_person_added(self, list, person): if person == self.__model.self_resource: return self.__people_list.add_person(person, AIM_PEOPLE) def __on_aim_person_removed(self, list, person): self.__people_list.remove_person(person, AIM_PEOPLE) def __on_xmpp_person_added(self, list, person): if person == self.__model.self_resource: return self.__people_list.add_person(person, XMPP_PEOPLE) def __on_xmpp_person_removed(self, list, person): self.__people_list.remove_person(person, XMPP_PEOPLE)