Beispiel #1
0
class AppsStock(bigboard.stock.AbstractMugshotStock):
    STATIC_SET_SIZE = 7
    DYNAMIC_SET_SIZE = 7    
    STATIFICATION_TIME_SEC = 60 * 60 #* 24 * 3; # 3 days
    __gsignals__ = {
        "all-apps-loaded" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
    }    
    def __init__(self, *args, **kwargs):
        super(AppsStock, self).__init__(*args, **kwargs)        
        
        self.__box = CanvasVBox(spacing=3)
        self.__message = hippo.CanvasText()
        self.__message_link = ActionLink()
        self.__message_link.connect("button-press-event", lambda link, event: self.__on_message_link())
        self.__message_link_url = None
        self.__subtitle = hippo.CanvasText(font="Bold 12px")
        self.__static_set = CanvasVBox()
        self.__dynamic_set = CanvasVBox()
        
        self.__box.append(self.__message)
        self.__box.append(self.__message_link)        
        self.__box.append(self.__subtitle)        
        
        self.__box.append(self.__static_set)
        self.__box.append(self.__dynamic_set)        
        self.__box.set_child_visible(self.__dynamic_set, False)
        
        self.__app_browser = None
        self._add_more_link(self.__on_more_link)

        self._mugshot.connect("all-apps-loaded", lambda mugshot: self.__merge_apps())  
        self._mugshot.connect("global-top-apps-changed", lambda mugshot, apps: self.__sync())  
        self._mugshot.connect("my-top-apps-changed", lambda mugshot, apps: self.__sync())      
        self._mugshot.connect("pinned-apps-changed", lambda mugshot, apps: self.__sync())        
        self._mugshot.connect("pref-changed", lambda mugshot, key, value: self.__handle_pref_change(key, value))          
        
        self.__usage_enabled = False
        
        self.__static_set_ids = {}
        self.__set_message('Loading...')
        
        self.__apps = {} # mugshot app -> app
        # apps installed locally and not known in Mugshot
        self.__local_apps = {} # desktop -> app

        ad = apps_directory.get_app_directory()
        for app in ad.get_apps():
            self.get_local_app(app)

    def __on_more_link(self):
        self._logger.debug("more!")
        if self.__app_browser is None:
            self.__app_browser = appbrowser.AppBrowser(self)            
        self.__app_browser.present()
        
    def __on_message_link(self):
        libbig.show_url(self.__message_link_url)
        
    def __set_message(self, text, link=None):
        self.__box.set_child_visible(self.__message, (not text is None) and link is None)
        self.__box.set_child_visible(self.__message_link, not (text is None or link is None))        
        if text:
            self.__message.set_property("text", text)
            self.__message_link.set_property("text", text)
        if link:
            self.__message_link_url = link
            
    def __set_subtitle(self, text):
        self.__box.set_child_visible(self.__subtitle, not text is None)
        if text:
            self.__subtitle.set_property("text", text)        

    def _on_mugshot_initialized(self):
        super(AppsStock, self)._on_mugshot_initialized()
        self._mugshot.get_global_top_apps()        
        self._mugshot.request_all_apps()

    def _on_mugshot_ready(self):
        super(AppsStock, self)._on_mugshot_ready()
        self._mugshot.get_pinned_apps()        
        self._mugshot.get_my_top_apps()

    def get_authed_content(self, size):
        return self.__box

    def get_unauthed_content(self, size):
        return self.__box
            
    def __set_item_size(self, item, size):
        if size == bigboard.stock.Stock.SIZE_BULL:
            item.set_property('xalign', hippo.ALIGNMENT_FILL)
        else:
            item.set_property('xalign', hippo.ALIGNMENT_CENTER)
        item.set_size(size)            
            
    def set_size(self, size):
        super(AppsStock, self).set_size(size)
        for child in self.__static_set.get_children() + self.__dynamic_set.get_children():
            self.__set_item_size(child, size)        

    def __handle_pref_change(self, key, value):          
        if key != 'applicationUsageEnabled':
            return
        self._logger.debug("handling %s pref change: %s", key, value)              
        self.__sync()
            
    def __on_pinned_apps_success(self, pinned_ids):
        self._logger.debug("app pin set succeeded")       
        self._mugshot.get_pinned_apps(force=True)
            
    def __set_dynamic_set(self, mugshot_apps):
        self.__dynamic_set.remove_all()        
        for i, mugshot_app in enumerate(mugshot_apps or []):
            app = self.get_app(mugshot_app)
            if self.__static_set_ids.has_key(app.get_id()):
                continue
            if app.get_is_excluded():
                continue
            if i >= self.DYNAMIC_SET_SIZE:
                break
            if not app.is_installed():
                continue            
            self._logger.debug("setting dynamic app: %s", app)            
            display = apps_widgets.AppDisplay(app)
            display.connect("button-press-event", lambda display, event: display.launch())             
            self.__dynamic_set.append(display)
        if mugshot_apps:
            self.__box.set_child_visible(self.__dynamic_set,True)
                        
    def get_app(self, mugshot_app):
        if not self.__apps.has_key(mugshot_app.get_id()):
            ad = apps_directory.get_app_directory()
            for desktop_name in mugshot_app.get_desktop_names().split(';'):
                try:
                    target_menuitem = ad.lookup(desktop_name)
                except KeyError, e:
                    continue
                if self.__local_apps.has_key(target_menuitem.get_name()):
                    self._logger.debug("moving app %s from local to apps", target_menuitem.get_name())
                    existing_app = self.__local_apps[target_menuitem.get_name()]
                    del self.__local_apps[target_menuitem.get_name()]
                    existing_app.set_app(mugshot_app)
                    self.__apps[mugshot_app.get_id()] = existing_app
                    return existing_app
            self._logger.debug("creating app %s", mugshot_app.get_id())
            self.__apps[mugshot_app.get_id()] = Application(mugshot_app=mugshot_app)
        return self.__apps[mugshot_app.get_id()]
Beispiel #2
0
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()
Beispiel #3
0
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()
Beispiel #4
0
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())
Beispiel #5
0
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()
Beispiel #7
0
class AppsStock(bigboard.stock.AbstractMugshotStock):
    STATIC_SET_SIZE = 4
    DYNAMIC_SET_SIZE = 0
    STATIFICATION_TIME_SEC = 60 * 60 #* 24 * 3; # 3 days
    __gsignals__ = {

    }    
    def __init__(self, *args, **kwargs):
        super(AppsStock, self).__init__(*args, **kwargs)

        search.enable_search_provider('apps')

        self.__box = CanvasVBox(spacing=3)
        self.__message = hippo.CanvasText()
        self.__message_link = ActionLink()
        self.__message_link.connect("button-press-event", lambda link, event: self.__on_message_link())
        self.__message_link_url = None
        self.__subtitle = hippo.CanvasText(font="Bold 12px")
        self.__static_set = CanvasVBox()
        self.__dynamic_set = CanvasVBox()
        
        self.__box.append(self.__message)
        self.__box.append(self.__message_link)        
        self.__box.append(self.__subtitle)
        self.__box.append(self.__static_set)
        self.__box.append(self.__dynamic_set)        
        self.__box.set_child_visible(self.__dynamic_set, False)
        
        self.__app_browser = None
        self._add_more_button(self.__on_more_button)
        
        self.__static_set_ids = {}

        gconf.client_get_default().notify_add(GCONF_KEY_APP_SIZE, self.__on_app_size_changed)
         
        self.__set_message('Loading...')

        self.__repo = apps.get_apps_repo()

        self.__repo.connect('enabled-changed', self.__on_usage_enabled_changed)
        self.__repo.connect('all-apps-loaded', self.__on_all_apps_loaded)
        self.__repo.connect('my-pinned-apps-changed', self.__on_my_pinned_apps_changed)
        self.__repo.connect('my-top-apps-changed', self.__on_my_top_apps_changed)
        self.__repo.connect('global-top-apps-changed', self.__on_global_top_apps_changed)
        self.__repo.connect('app-launched', self.__on_app_launched)

        self.__sync()

    def _on_ready(self):
        # When we disconnect from the server we freeze existing content, then on reconnect
        # we clear everything and start over.
        _logger.debug("Connected to data model")

    def __on_query_error(self, where, error_code, message):
        _logger.warn("Query '" + where + "' failed, code " + str(error_code) + " message: " + str(message))

    def __on_usage_enabled_changed(self, repo):
        _logger.debug("usage enabled changed")
        self.__sync()

    def __on_all_apps_loaded(self, repo):
        _logger.debug("all apps are loaded")
        self.__sync()

    def __on_my_pinned_apps_changed(self, repo, pinned_apps):
        _logger.debug("Pinned apps changed from apps repo: " + str(pinned_apps))
        self.__sync()

    def __on_my_top_apps_changed(self, repo, my_top_apps):
        _logger.debug("My top apps changed from apps repo: " + str(my_top_apps))
        self.__sync()

    def __on_global_top_apps_changed(self, repo, global_top_apps):
        _logger.debug("Global top apps changed from apps repo: " + str(global_top_apps))
        self.__sync()
        
    def __on_app_size_changed(self, *args):
        _logger.debug("app size changed")  
        self.__sync()

    def __on_app_launched(self, repo, app):
        self._panel.action_taken()

    def __on_more_button(self):
        _logger.debug("more!")
        if self.__app_browser is None:
            self.__app_browser = appbrowser.AppBrowser()  
        if self.__app_browser.get_property('is-active'):
            self.__app_browser.hide()
        else:
            self.__app_browser.present()
        
    def __on_message_link(self):
        libbig.show_url(self.__message_link_url)
        
    def __set_message(self, text, link=None):
        self.__box.set_child_visible(self.__message, (not text is None) and link is None)
        self.__box.set_child_visible(self.__message_link, not (text is None or link is None))        
        if text:
            self.__message.set_property("text", text)
            self.__message_link.set_property("text", text)
        if link:
            self.__message_link_url = link
            
    def __set_subtitle(self, text):
        self.__box.set_child_visible(self.__subtitle, not text is None)
        if text:
            self.__subtitle.set_property("text", text)        

    def get_authed_content(self, size):
        return self.__box

    def get_unauthed_content(self, size):
        return self.__box
            
    def __set_item_size(self, item, size):
        if size == bigboard.stock.Stock.SIZE_BULL:
            item.set_property('xalign', hippo.ALIGNMENT_FILL)
        else:
            item.set_property('xalign', hippo.ALIGNMENT_CENTER)
        item.set_size(size)            
            
    def set_size(self, size):
        super(AppsStock, self).set_size(size)
        for child in self.__static_set.get_children() + self.__dynamic_set.get_children():
            self.__set_item_size(child, size)        

    def __fill_static_set(self):
        self.__static_set.remove_all()
        self.__static_set_ids = {}

        usage = self.__repo.get_app_usage_enabled()
        pinned_apps = self.__repo.get_pinned_apps()
        global_top_apps = self.__repo.get_global_top_apps()
        local_apps = self.__repo.get_local_apps()
        static_size = gconf.client_get_default().get_int(GCONF_KEY_APP_SIZE) or 7

        self.__set_subtitle(None)
        apps_in_set = []
        using_local_apps = False
        if usage:
            apps_in_set = pinned_apps
        if len(apps_in_set) == 0:
            if len(global_top_apps) > 0:
                apps_in_set = global_top_apps
                self.__set_subtitle("Popular Applications")
            elif len(local_apps) > 0:
                apps_in_set = local_apps
                using_local_apps = True

        if using_local_apps:
            apps_in_set = filter(lambda a: POPULAR_APPS.count(a.get_app_name_from_file_name()) > 0, apps_in_set)
            apps_in_set.sort(lambda a, b: cmp(POPULAR_APPS.index(a.get_app_name_from_file_name()), POPULAR_APPS.index(b.get_app_name_from_file_name())))
        else: 
            ## note the "-" in front of the cmp to sort descending
            apps_in_set.sort(lambda a, b: - cmp(a.get_usage_count(), b.get_usage_count()))
   
        for i, app in enumerate(apps_in_set):
            if i >= static_size:
                break

            # don't display apps that are not installed if the user is not logged in
            if not self._model.self_resource and not app.is_installed():
                continue

            display = apps_widgets.AppDisplay(apps_widgets.AppLocation.STOCK, app)
            display.connect("button-press-event", lambda display, event: display.launch()) 
            #_logger.debug("setting static set app: %s", app)
            self.__static_set.append(display)
            self.__static_set_ids[app.get_id()] = True

    @defer_idle_func(logger=_logger)
    def __sync(self):
        #_logger.debug("doing sync")
        
        self.__set_message(None)        
             
        self.__box.set_child_visible(self.__dynamic_set, False)

        usage = self.__repo.get_app_usage_enabled()

        #_logger.debug("usage: %s", usage)

        if usage is False and self._model.ready and self._model.global_resource.online:
            self.__set_message("Enable application tracking", 
                               globals.get_baseurl() + "/account")        

        self.__fill_static_set()

        self.__repo.pin_stuff_if_we_have_none()