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)
def __init__(self, app=None, **kwargs): PhotoContentItem.__init__(self, border_right=6, **kwargs) self.__app = None self.__description_mode = False self._logger = logging.getLogger('bigboard.AppDisplay') self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30) self.set_photo(self.__photo) self.__box = CanvasVBox(spacing=2, border_right=4) sub_kwargs = {} if kwargs.has_key('color'): sub_kwargs['color'] = kwargs['color'] self.__title = ActionLink(font="14px",xalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END, **sub_kwargs) self.__title.connect("activated", lambda t: self.emit("title-clicked")) self.__subtitle = hippo.CanvasText(font="10px",xalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) attrs = pango.AttrList() attrs.insert(pango.AttrForeground(0x6666, 0x6666, 0x6666, 0, 0xFFFF)) self.__subtitle.set_property("attributes", attrs) self.__box.append(self.__title) self.__box.append(self.__subtitle) self.set_child(self.__box) self.__description = hippo.CanvasText(size_mode=hippo.CANVAS_SIZE_WRAP_WORD, **sub_kwargs) self.__box.append(self.__description) if app: self.set_app(app)
def __init__(self, profiles, **kwargs): kwargs['orientation'] = hippo.ORIENTATION_VERTICAL kwargs['border'] = 1 kwargs['border-color'] = 0x0000000ff hippo.CanvasBox.__init__(self, **kwargs) self.__profiles = profiles self.__entity = None self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.append(self.__top_box) self.__photo = CanvasMugshotURLImage(scale_width=60, scale_height=60, border=5) self.__top_box.append(self.__photo) self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) self.__top_box.append(self.__address_box) self.__online = hippo.CanvasText(text='Offline') self.append(self.__online) self.__ribbon_bar = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=2) self.append(self.__ribbon_bar)
def __init__(self, acct): super(ExternalAccountIcon, self).__init__(box_width=16, box_height=16) self.__acct = None self.__img = CanvasMugshotURLImage() self.append(self.__img) self.connect("activated", lambda s2: self.__launch_browser()) self.set_clickable(True) self.set_acct(acct)
class ExternalAccountIcon(CanvasHBox): def __init__(self, acct): super(ExternalAccountIcon, self).__init__(box_width=16, box_height=16) self.__acct = None self.__img = CanvasMugshotURLImage() self.append(self.__img) self.connect("activated", lambda s2: self.__launch_browser()) self.set_clickable(True) self.set_acct(acct) def set_acct(self, acct): if self.__acct: self.__acct.disconnect(self.__sync) self.__acct = acct self.__acct.connect(self.__sync) self.__sync() def __sync(self): self.__img.set_url(self.__acct.iconUrl) def __launch_browser(self): libbig.show_url(self.__acct.link)
def __init__(self, app_location, app=None, **kwargs): if app_location == AppLocation.STOCK: kwargs['enable_theme'] = True PhotoContentItem.__init__(self, border_right=6, **kwargs) self.__app = None self.__description_mode = False self._logger = logging.getLogger('bigboard.AppDisplay') self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30) self.set_photo(self.__photo) self.__box = CanvasVBox(spacing=2, border_right=4) sub_kwargs = {} if kwargs.has_key('color'): sub_kwargs['color'] = kwargs['color'] title_kwargs = dict(sub_kwargs) title_kwargs.update({'font': '14px', 'xalign': hippo.ALIGNMENT_START, 'size-mode': hippo.CANVAS_SIZE_ELLIPSIZE_END }) if app_location == AppLocation.STOCK: self.__title = ThemedLink(**title_kwargs) else: self.__title = ActionLink(**title_kwargs) self.__title.connect("activated", lambda t: self.emit("title-clicked")) subtitle_kwargs = {'font': '10px', 'xalign': hippo.ALIGNMENT_START, 'size-mode': hippo.CANVAS_SIZE_ELLIPSIZE_END } if app_location == AppLocation.STOCK: self.__subtitle = ThemedText(theme_hints=['subforeground'], **subtitle_kwargs) else: self.__subtitle = hippo.CanvasText(**subtitle_kwargs) self.__box.append(self.__title) self.__box.append(self.__subtitle) self.set_child(self.__box) self.__description = hippo.CanvasText(size_mode=hippo.CANVAS_SIZE_WRAP_WORD, **sub_kwargs) self.__box.append(self.__description) self.__photo.set_clickable(True) self.__box.set_clickable(True) self.__app_location = app_location if app: self.set_app(app)
def __init__(self, **kwargs): PhotoContentItem.__init__(self, **kwargs) self.__entity = None self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30, border=1, border_color=0x000000ff) self.set_photo(self.__photo) self.__name = hippo.CanvasText(xalign=hippo.ALIGNMENT_FILL, yalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.set_child(self.__name) self.connect('button-press-event', self.__handle_button_press) self.connect('button-release-event', self.__handle_button_release) self.__pressed = False
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()
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)
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, person, themed=False, **kwargs): kwargs['orientation'] = hippo.ORIENTATION_VERTICAL hippo.CanvasBox.__init__(self, **kwargs) self.person = person self.__themed = themed if themed: self.__header = Header(topborder=False) else: self.__header = hippo.CanvasGradient(orientation=hippo.ORIENTATION_HORIZONTAL, start_color=0xf2f2f2f2, end_color=0xc8c8c8ff) self.append(self.__header) textklass = themed and ThemedText or hippo.CanvasText linkklass = themed and ThemedLink or ActionLink name_vbox = hippo.CanvasBox(padding=6) self.__name = textklass(font="22px") name_vbox.append(self.__name) rename_link = linkklass(text='rename', font="10px", xalign=hippo.ALIGNMENT_END) name_vbox.append(rename_link) rename_link.connect('activated', self.__on_rename_activated) self.__header.append(name_vbox) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: mugshot_link = linkklass(text="Mugshot", padding=6) self.__header.append(mugshot_link, flags=hippo.PACK_END) mugshot_link.connect("activated", self.__on_activate_web) self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.append(self.__top_box) self.__photo = CanvasMugshotURLImage(scale_width=60, scale_height=60, border=5) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: self.__photo.set_clickable(True) self.__photo.connect("activated", self.__on_activate_web) self.__top_box.append(self.__photo) self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) self.__top_box.append(self.__address_box) self.__contact_status_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=4, border=4) self.append(self.__contact_status_box) if person.is_contact: self.__add_link = None self.__remove_link = linkklass() self.__remove_link.connect('activated', self.__remove_from_network_clicked) self.append(self.__remove_link) else: self.__remove_link = None self.__add_link = linkklass(text=('Add %s to network' % self.person.display_name)) self.__add_link.connect('activated', self.__add_to_network_clicked) self.append(self.__add_link) # self.__online = hippo.CanvasText(text='Offline') # self.append(self.__online) separator = hippo.CanvasBox(box_height=1, background_color=0xAAAAAAFF) self.append(separator) self.__ribbon_bar = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__ribbon_bar) self.__link_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__link_box) self.__local_files_link = None self.person.connect('display-name-changed', self.__update) self.person.connect('icon-url-changed', self.__update) self.person.connect('aim-changed', self.__update) self.person.connect('local-buddy-changed', self.__update_local_buddy) self.person.connect('xmpp-changed', self.__update) if person.is_contact: self.person.resource.connect(lambda *args: self.__update(self.person), 'emails') self.person.resource.connect(self.__update_contact_status, "status") try: user = person.resource.user except AttributeError: user = None if user: user.connect(self.__update_loved_accounts, "lovedAccounts") query = DataModel(bigboard.globals.server_name).query_resource(self.person.resource, "lovedAccounts +") query.add_handler(self.__update_loved_accounts) query.execute() self.__update(self.person) self.__update_local_buddy(self.person) if self.person.is_contact: self.__update_contact_status(self.person.resource) try: user = person.resource.user except AttributeError: user = None if user: self.__update_loved_accounts(user)
class ProfileItem(hippo.CanvasBox): __gsignals__ = { "close": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (bool,)) } def __init__(self, person, themed=False, **kwargs): kwargs['orientation'] = hippo.ORIENTATION_VERTICAL hippo.CanvasBox.__init__(self, **kwargs) self.person = person self.__themed = themed if themed: self.__header = Header(topborder=False) else: self.__header = hippo.CanvasGradient(orientation=hippo.ORIENTATION_HORIZONTAL, start_color=0xf2f2f2f2, end_color=0xc8c8c8ff) self.append(self.__header) textklass = themed and ThemedText or hippo.CanvasText linkklass = themed and ThemedLink or ActionLink name_vbox = hippo.CanvasBox(padding=6) self.__name = textklass(font="22px") name_vbox.append(self.__name) rename_link = linkklass(text='rename', font="10px", xalign=hippo.ALIGNMENT_END) name_vbox.append(rename_link) rename_link.connect('activated', self.__on_rename_activated) self.__header.append(name_vbox) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: mugshot_link = linkklass(text="Mugshot", padding=6) self.__header.append(mugshot_link, flags=hippo.PACK_END) mugshot_link.connect("activated", self.__on_activate_web) self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.append(self.__top_box) self.__photo = CanvasMugshotURLImage(scale_width=60, scale_height=60, border=5) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: self.__photo.set_clickable(True) self.__photo.connect("activated", self.__on_activate_web) self.__top_box.append(self.__photo) self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) self.__top_box.append(self.__address_box) self.__contact_status_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=4, border=4) self.append(self.__contact_status_box) if person.is_contact: self.__add_link = None self.__remove_link = linkklass() self.__remove_link.connect('activated', self.__remove_from_network_clicked) self.append(self.__remove_link) else: self.__remove_link = None self.__add_link = linkklass(text=('Add %s to network' % self.person.display_name)) self.__add_link.connect('activated', self.__add_to_network_clicked) self.append(self.__add_link) # self.__online = hippo.CanvasText(text='Offline') # self.append(self.__online) separator = hippo.CanvasBox(box_height=1, background_color=0xAAAAAAFF) self.append(separator) self.__ribbon_bar = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__ribbon_bar) self.__link_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__link_box) self.__local_files_link = None self.person.connect('display-name-changed', self.__update) self.person.connect('icon-url-changed', self.__update) self.person.connect('aim-changed', self.__update) self.person.connect('local-buddy-changed', self.__update_local_buddy) self.person.connect('xmpp-changed', self.__update) if person.is_contact: self.person.resource.connect(lambda *args: self.__update(self.person), 'emails') self.person.resource.connect(self.__update_contact_status, "status") try: user = person.resource.user except AttributeError: user = None if user: user.connect(self.__update_loved_accounts, "lovedAccounts") query = DataModel(bigboard.globals.server_name).query_resource(self.person.resource, "lovedAccounts +") query.add_handler(self.__update_loved_accounts) query.execute() self.__update(self.person) self.__update_local_buddy(self.person) if self.person.is_contact: self.__update_contact_status(self.person.resource) try: user = person.resource.user except AttributeError: user = None if user: self.__update_loved_accounts(user) def __add_status_link(self, text, current_status, new_status): textklass = self.__themed and ThemedText or hippo.CanvasText linkklass = self.__themed and ThemedLink or ActionLink if current_status == new_status: link = textklass(text=text) else: def set_new_status(object): model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "setContactStatus"), contact=self.person.resource, status=new_status) query.execute() link = linkklass(text=text) link.connect("activated", set_new_status) self.__contact_status_box.append(link) def __remove_from_network_clicked(self, link): dialog = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION) dialog.set_markup("<b>Remove %s from your network?</b>" % (self.person.display_name)) dialog.format_secondary_text("This will delete %s's contact information and remove %s from your sidebar" % (self.person.display_name, self.person.display_name)) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Remove", gtk.RESPONSE_ACCEPT) def remove_from_network_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("removing from network") model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "deleteContact"), contact=person.resource) query.execute() else: _logger.debug("not removing from network") dialog.connect("response", lambda dialog, response_id: remove_from_network_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show() def __on_rename_activated(self, link): dialog = gtk.Dialog(title="Rename a contact") entry = gtk.Entry() entry.set_text(self.person.display_name) entry.set_activates_default(True) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Name:'), False, False) hbox.pack_end(entry, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Rename", gtk.RESPONSE_ACCEPT) dialog.set_default_response(gtk.RESPONSE_ACCEPT) def rename_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("renaming this person") name = entry.get_text() model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "setContactName"), contact=person.resource, name=name) query.execute() else: _logger.debug("not renaming") dialog.connect("response", lambda dialog, response_id: rename_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show() def __create_contact(self, addressType, address): _logger.debug("creating contact %s %s" % (addressType, address)) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "createContact"), addressType=addressType, address=address) query.execute() def __create_user_contact(self, user_resource): _logger.debug("creating contact %s" % (str(user_resource))) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "createUserContact"), user=user_resource); query.execute() def __add_to_network_clicked(self, link): if self.person.aim: self.__create_contact('aim', self.person.aim) elif self.person.xmpp: self.__create_contact('xmpp', self.person.xmpp) elif self.person.local_buddy: self.__create_user_contact(self.person.local_buddy.user) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) def __update_contact_status(self, person): self.__contact_status_box.remove_all() try: status = self.person.resource.status except AttributeError: status = 0 if status == 0: status = 3 textklass = self.__themed and ThemedText or hippo.CanvasText self.__contact_status_box.append(textklass(text="In sidebar: ")) self.__add_status_link("Top", status, 4) self.__add_status_link("Middle", status, 3) self.__add_status_link("Bottom", status, 2) def __update_loved_accounts(self, person): try: accounts = self.person.resource.lovedAccounts except AttributeError: accounts = [] self.__ribbon_bar.clear() for a in accounts: icon = ExternalAccountIcon(a) self.__ribbon_bar.append(icon) def __update_local_buddy(self, person): if self.__local_files_link: self.__local_files_link.destroy() self.__local_files_link = None try: buddy = person.local_buddy except AttributeError: return if buddy != None: self.__local_files_link = LocalFilesLink(buddy) self.__link_box.append(self.__local_files_link) def __update(self, person): textklass = self.__themed and ThemedText or hippo.CanvasText linkklass = self.__themed and ThemedLink or ActionLink self.__name.set_property('text', self.person.display_name) self.__photo.set_url(self.person.icon_url) self.__address_box.remove_all() if self.__remove_link: self.__remove_link.set_property('text', "Remove %s from network" % self.person.display_name) emails = None if person.is_contact: try: emails = self.person.resource.emails except AttributeError: pass if emails != None and len(emails) > 0: email = linkklass(text=emails[0], xalign=hippo.ALIGNMENT_START) email.connect('activated', self.__on_activate_email) self.__address_box.append(email) if person.aim != None: aim = linkklass(text=person.aim, xalign=hippo.ALIGNMENT_START) aim.connect('activated', self.__on_activate_aim) self.__address_box.append(aim) if person.xmpp != None: xmpp = linkklass(text=person.aim, xalign=hippo.ALIGNMENT_START) xmpp.connect('activated', self.__on_activate_xmpp) self.__address_box.append(xmpp) add = linkklass(text='add address', xalign=hippo.ALIGNMENT_END, font_scale=0.8) add.connect('activated', self.__on_activate_add_address) self.__address_box.append(add) def __on_activate_web(self, canvas_item): self.emit("close", True) libbig.show_url(self.person.resource.user.homeUrl) def __on_activate_email(self, canvas_item): self.emit("close", True) # email should probably cgi.escape except it breaks if you escape the @ os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'mailto:' + self.person.resource.email) def __on_activate_aim(self, canvas_item): self.emit("close", True) _open_aim(self.person.aim) def __on_activate_xmpp(self, canvas_item): self.emit("close", True) _open_xmpp(self.person.xmpp) def __on_activate_add_address(self, canvas_item): dialog = gtk.Dialog(title=("Add an address for %s" % self.person.display_name)) entry = gtk.Entry() entry.set_activates_default(True) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Address:'), False, False) hbox.pack_end(entry, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) type_combo = gtk.combo_box_new_text() type_combo.append_text('AIM') type_combo.append_text('Email') type_combo.append_text('GTalk/XMPP') type_combo.set_active(0) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Type:'), False, False) hbox.pack_end(type_combo, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Add", gtk.RESPONSE_ACCEPT) dialog.set_default_response(gtk.RESPONSE_ACCEPT) def combo_get_address_type(combo): visible_type = type_combo.get_active_text() addressType = None if visible_type == 'Email': addressType = 'email' elif visible_type == 'AIM': addressType = 'aim' elif visible_type == 'GTalk/XMPP': addressType = xmpp else: _logger.warn('Bug: unknown combox box text for address type') if '@' in entry.get_text(): addressType = 'email' else: addressType = 'aim' return addressType def address_entry_changed(entry): address = entry.get_text() type = combo_get_address_type(type_combo) if '@' in address and type == 'aim': type_combo.set_active(1) ## set to email if an @ is typed elif '@' not in address and type == 'email': type_combo.set_active(0) ## set to AIM if no @ is found ## remember that @ can mean either email or xmpp entry.connect('changed', address_entry_changed) def add_address_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("adding address for this person") address = entry.get_text() addressType = combo_get_address_type(type_combo) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "addContactAddress"), contact=person.resource, addressType=addressType, address=address) query.execute() else: _logger.debug("not adding_address") dialog.connect("response", lambda dialog, response_id: add_address_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show()
class AppDisplay(PhotoContentItem): __gsignals__ = { "title-clicked" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__(self, app=None, **kwargs): PhotoContentItem.__init__(self, border_right=6, **kwargs) self.__app = None self.__description_mode = False self._logger = logging.getLogger('bigboard.AppDisplay') self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30) self.set_photo(self.__photo) self.__box = CanvasVBox(spacing=2, border_right=4) sub_kwargs = {} if kwargs.has_key('color'): sub_kwargs['color'] = kwargs['color'] self.__title = ActionLink(font="14px",xalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END, **sub_kwargs) self.__title.connect("activated", lambda t: self.emit("title-clicked")) self.__subtitle = hippo.CanvasText(font="10px",xalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) attrs = pango.AttrList() attrs.insert(pango.AttrForeground(0x6666, 0x6666, 0x6666, 0, 0xFFFF)) self.__subtitle.set_property("attributes", attrs) self.__box.append(self.__title) self.__box.append(self.__subtitle) self.set_child(self.__box) self.__description = hippo.CanvasText(size_mode=hippo.CANVAS_SIZE_WRAP_WORD, **sub_kwargs) self.__box.append(self.__description) if app: self.set_app(app) def set_description_mode(self, mode): self.__description_mode = mode self.__app_display_sync() def get_app(self): return self.__app def set_app(self, app): self.__app = app self.__app.connect("changed", lambda app: self.__app_display_sync()) self.__app_display_sync() def __get_name(self): if self.__app is None: return "unknown" return self.__app.get_name() def __str__(self): return '<AppDisplay name="%s">' % (self.__get_name()) # override def do_prelight(self): return self.__app.is_installed() def __app_display_sync(self): if not self.__app: return self.__box.set_child_visible(self.__subtitle, not self.__description_mode) self.__box.set_child_visible(self.__description, self.__description_mode) self.__photo.set_clickable(self.__app.is_installed()) self.__box.set_clickable(self.__app.is_installed()) self.__title.set_property("text", self.__app.get_name()) self.__subtitle.set_property("text", self.__app.get_generic_name() or self.__app.get_tooltip() or self.__app.get_comment()) self.__description.set_property("text", self.__app.get_description()) if self.__app.get_mugshot_app(): self.__photo.set_url(self.__app.get_mugshot_app().get_icon_url()) else: pixbuf = self.__app.get_local_pixbuf() if pixbuf: self.__photo.set_property("image", hippo.cairo_surface_from_gdk_pixbuf(pixbuf)) def launch(self): self._logger.debug("launching app %s", self) self.__app.launch()
class AppDisplay(PhotoContentItem): __gsignals__ = { "title-clicked" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__(self, app_location, app=None, **kwargs): if app_location == AppLocation.STOCK: kwargs['enable_theme'] = True PhotoContentItem.__init__(self, border_right=6, **kwargs) self.__app = None self.__description_mode = False self._logger = logging.getLogger('bigboard.AppDisplay') self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30) self.set_photo(self.__photo) self.__box = CanvasVBox(spacing=2, border_right=4) sub_kwargs = {} if kwargs.has_key('color'): sub_kwargs['color'] = kwargs['color'] title_kwargs = dict(sub_kwargs) title_kwargs.update({'font': '14px', 'xalign': hippo.ALIGNMENT_START, 'size-mode': hippo.CANVAS_SIZE_ELLIPSIZE_END }) if app_location == AppLocation.STOCK: self.__title = ThemedLink(**title_kwargs) else: self.__title = ActionLink(**title_kwargs) self.__title.connect("activated", lambda t: self.emit("title-clicked")) subtitle_kwargs = {'font': '10px', 'xalign': hippo.ALIGNMENT_START, 'size-mode': hippo.CANVAS_SIZE_ELLIPSIZE_END } if app_location == AppLocation.STOCK: self.__subtitle = ThemedText(theme_hints=['subforeground'], **subtitle_kwargs) else: self.__subtitle = hippo.CanvasText(**subtitle_kwargs) self.__box.append(self.__title) self.__box.append(self.__subtitle) self.set_child(self.__box) self.__description = hippo.CanvasText(size_mode=hippo.CANVAS_SIZE_WRAP_WORD, **sub_kwargs) self.__box.append(self.__description) self.__photo.set_clickable(True) self.__box.set_clickable(True) self.__app_location = app_location if app: self.set_app(app) def set_description_mode(self, mode): self.__description_mode = mode self.__app_display_sync() def get_app(self): return self.__app def set_app(self, app): self.__app = app self.__app_display_sync() def __get_name(self): if self.__app is None: return "unknown" return self.__app.get_name() def __str__(self): return '<AppDisplay name="%s">' % (self.__get_name()) def __app_display_sync(self): if not self.__app: return self.__box.set_child_visible(self.__subtitle, not self.__description_mode) self.__box.set_child_visible(self.__description, self.__description_mode) self.__title.set_property("text", self.__app.get_name()) if self.__app.is_installed() or self.__app_location == AppLocation.DESCRIPTION_HEADER: self.__subtitle.set_property("text", self.__app.get_generic_name() or self.__app.get_tooltip() or self.__app.get_comment()) ## for now, install won't work if not connected elif self.__app_location == AppLocation.STOCK and globals.get_data_model().ready and globals.get_data_model().global_resource.online: self.__subtitle.set_property('text', "(Click to Install)") else: self.__subtitle.set_property('text', "(Not Installed)") self.__description.set_property("text", self.__app.get_description()) if self.__app.get_icon_url(): self.__photo.set_url(self.__app.get_icon_url()) else: pixbuf = self.__app.get_local_pixbuf() if pixbuf: self.__photo.set_property("image", hippo.cairo_surface_from_gdk_pixbuf(pixbuf)) def launch(self): self._logger.debug("launching app %s", self) self.__app.launch()
class ProfileItem(hippo.CanvasBox): def __init__(self, profiles, **kwargs): kwargs['orientation'] = hippo.ORIENTATION_VERTICAL kwargs['border'] = 1 kwargs['border-color'] = 0x0000000ff hippo.CanvasBox.__init__(self, **kwargs) self.__profiles = profiles self.__entity = None self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.append(self.__top_box) self.__photo = CanvasMugshotURLImage(scale_width=60, scale_height=60, border=5) self.__top_box.append(self.__photo) self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) self.__top_box.append(self.__address_box) self.__online = hippo.CanvasText(text='Offline') self.append(self.__online) self.__ribbon_bar = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=2) self.append(self.__ribbon_bar) def set_entity(self, entity): if self.__entity == entity: return self.__entity = entity if self.__entity: if self.__entity.get_photo_url(): self.__photo.set_url(self.__entity.get_photo_url()) self.__profiles.fetch_profile(self.__entity.get_guid(), self.__on_profile_fetched) def __on_activate_email(self, canvas_item, profile): # email should probably cgi.escape except it breaks if you escape the @ os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'mailto:' + profile.get_email()) def __on_activate_aim(self, canvas_item, profile): os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'aim:GoIM?screenname=' + cgi.escape(profile.get_aim())) def __on_profile_fetched(self, profile): if not profile: print "failed to fetch profile" return #print str(profile) if profile.get_online(): self.__online.set_property('text', 'Online') else: self.__online.set_property('text', 'Offline') self.__ribbon_bar.remove_all() for a in profile.get_accounts(): badge = CanvasMugshotURLImageButton(scale_width=16, scale_height=16) badge.set_url(a['icon']) badge.set_property('tooltip', a['linkText']) # doesn't work... self.__ribbon_bar.append(badge) self.__address_box.remove_all() if profile.get_email(): email = hippo.CanvasLink(text=profile.get_email(), xalign=hippo.ALIGNMENT_START) email.connect('activated', self.__on_activate_email, profile) self.__address_box.append(email) if profile.get_aim(): aim = hippo.CanvasLink(text=profile.get_aim(), xalign=hippo.ALIGNMENT_START) aim.connect('activated', self.__on_activate_aim, profile) self.__address_box.append(aim)
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, *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())
class EntityItem(PhotoContentItem): def __init__(self, **kwargs): PhotoContentItem.__init__(self, **kwargs) self.__entity = None self.__photo = CanvasMugshotURLImage(scale_width=30, scale_height=30, border=1, border_color=0x000000ff) self.set_photo(self.__photo) self.__name = hippo.CanvasText(xalign=hippo.ALIGNMENT_FILL, yalign=hippo.ALIGNMENT_START, size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.set_child(self.__name) self.connect('button-press-event', self.__handle_button_press) self.connect('button-release-event', self.__handle_button_release) self.__pressed = False 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: return False self.__pressed = True self.__update_color() def __handle_button_release(self, self2, event): if event.button != 1: return False self.__pressed = False self.__update_color() def set_entity(self, entity): if self.__entity == entity: return self.__entity = entity self.__update() def get_guid(self): return self.__entity.get_guid() def get_entity(self): return self.__entity def set_size(self, size): if size == bigboard.stock.SIZE_BULL: self.set_child_visible(self.__name, True) self.__photo.set_property('xalign', hippo.ALIGNMENT_START) self.__photo.set_property('yalign', hippo.ALIGNMENT_START) else: self.set_child_visible(self.__name, False) self.__photo.set_property('xalign', hippo.ALIGNMENT_CENTER) self.__photo.set_property('yalign', hippo.ALIGNMENT_CENTER) def __update(self): if not self.__entity: return self.__name.set_property("text", self.__entity.get_name()) if self.__entity.get_photo_url(): self.__photo.set_url(self.__entity.get_photo_url()) def get_screen_coords(self): return self.get_context().translate_to_screen(self)