Exemplo n.º 1
0
    def __init__(self, icon_theme=None):
        """
        Creates an enhanced IconEntry that triggers a timeout when typing
        """
        Gtk.Entry.__init__(self)
        self.set_size_request(em(9), em(1.7))

        if not icon_theme:
            icon_theme = Gtk.IconTheme.get_default()

        self._handler_changed = self.connect_after("changed",
                                                   self._on_changed)

        self.connect("icon-press", self._on_icon_pressed)

        self.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,
            'edit-find-symbolic')
        self.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, None)

        # set sensible atk name
        atk_desc = self.get_accessible()
        atk_desc.set_name(_("Search"))

        # data
        self._timeout_id = 0
        self._undo_stack = [""]
        self._redo_stack = []
Exemplo n.º 2
0
    def __init__(self, icon_theme=None):
        """
        Creates an enhanced IconEntry that triggers a timeout when typing
        """
        Gtk.Entry.__init__(self)
        self.set_size_request(em(16), em(1.7))

        if not icon_theme:
            icon_theme = Gtk.IconTheme.get_default()

        self._handler_changed = self.connect_after("changed", self._on_changed)

        self.connect("icon-press", self._on_icon_pressed)

        self.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,
                                     'edit-find-symbolic')
        self.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, None)

        # set sensible atk name
        atk_desc = self.get_accessible()
        atk_desc.set_name(_("Search"))

        # data
        self._timeout_id = 0
        self._undo_stack = [""]
        self._redo_stack = []
Exemplo n.º 3
0
    def __init__(self):
        GObject.GObject.__init__(self)
        self.set_redraw_on_allocate(False)
        self.set_size_request(-1, em(1.75))
        self._allocation = None

        # Accessibility info
        atk_desc = self.get_accessible()
        atk_desc.set_name(_("You are here:"))
        atk_desc.set_role(Atk.Role.PANEL)

        self.use_animations = True
        self.animator = PathBarAnimator(self)

        self.out_of_width = False
        self.psuedo_parts = []

        # used for certain button press logic
        self._press_origin = None
        # tracks the id of the revealer timeout
        self._revealer = None

        # values derived from the gtk settings
        s = Gtk.Settings.get_default()
        # time to wait before revealing a part on enter event in ms
        self._timeout_reveal = s.get_property("gtk-tooltip-timeout")
        # time to wait until emitting click event in ms
        self._timeout_initial = s.get_property("gtk-timeout-initial")

        # les signales!
        self.connect('size-allocate', self._on_allocate)
        self.connect('draw', self._on_draw)
    def __init__(self):
        GObject.GObject.__init__(self)
        self.set_redraw_on_allocate(False)
        self.set_size_request(-1, em(1.75))
        self._allocation = None

        # Accessibility info
        atk_desc = self.get_accessible()
        atk_desc.set_name(_("You are here:"))
        atk_desc.set_role(Atk.Role.PANEL)

        self.use_animations = True
        self.animator = PathBarAnimator(self)

        self.out_of_width = False
        self.psuedo_parts = []

        # used for certain button press logic
        self._press_origin = None
        # tracks the id of the revealer timeout
        self._revealer = None

        # values derived from the gtk settings
        s = Gtk.Settings.get_default()
        # time to wait before revealing a part on enter event in ms
        self._timeout_reveal = s.get_property("gtk-tooltip-timeout")
        # time to wait until emitting click event in ms
        self._timeout_initial = s.get_property("gtk-timeout-initial")

        # les signales!
        self.connect('size-allocate', self._on_allocate)
        self.connect('draw', self._on_draw)
        return
Exemplo n.º 5
0
    def _calc_row_heights(self, tr):
        ypad = StockEms.SMALL
        tr.set_property('xpad', StockEms.MEDIUM)
        tr.set_property('ypad', ypad)

        for btn in tr.get_buttons():
            # recalc button geometry and cache
            btn.configure_geometry(self.create_pango_layout(""))

        btn_h = btn.height

        tr.normal_height = max(32 + 2 * ypad, em(2.5) + ypad)
        tr.selected_height = tr.normal_height + btn_h + StockEms.MEDIUM
Exemplo n.º 6
0
    def _calc_row_heights(self, tr):
        ypad = StockEms.SMALL
        tr.set_property('xpad', StockEms.MEDIUM)
        tr.set_property('ypad', ypad)

        for btn in tr.get_buttons():
            # recalc button geometry and cache
            btn.configure_geometry(self.create_pango_layout(""))

        btn_h = btn.height

        tr.normal_height = max(32 + 2 * ypad, em(2.5) + ypad)
        tr.selected_height = tr.normal_height + btn_h + StockEms.MEDIUM
Exemplo n.º 7
0
    def __init__(self, label, icon, icon_size=Gtk.IconSize.DIALOG):
        TileButton.__init__(self)
        self.set_size_request(em(8), -1)
        self.build_default(label, icon, icon_size)
        self.label.set_justify(Gtk.Justification.CENTER)
        self.label.set_alignment(0.5, 0.0)
        self.label.set_line_wrap(True)
        self.box.set_border_width(StockEms.SMALL)

        context = self.label.get_style_context()
        context.add_class("category-tile")

        self.connect("enter-notify-event", self.on_enter)
        self.connect("leave-notify-event", self.on_leave)
Exemplo n.º 8
0
    def __init__(self, label, icon, icon_size=Gtk.IconSize.DIALOG):
        TileButton.__init__(self)
        self.set_size_request(em(8), -1)
        self.build_default(label, icon, icon_size)
        self.label.set_justify(Gtk.Justification.CENTER)
        self.label.set_alignment(0.5, 0.0)
        self.label.set_line_wrap(True)
        self.box.set_border_width(StockEms.SMALL)

        context = self.label.get_style_context()
        context.add_class("category-tile")

        self.connect("enter-notify-event", self.on_enter)
        self.connect("leave-notify-event", self.on_leave)
Exemplo n.º 9
0
class _Tile(object):

    MIN_WIDTH = em(7)

    def __init__(self):
        self.set_focus_on_click(False)
        self.set_relief(Gtk.ReliefStyle.NONE)
        self.box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        self.box.set_size_request(self.MIN_WIDTH, -1)
        self.add(self.box)
        return

    def build_default(self, label, icon, icon_size):
        if icon is not None:
            self.image = _parse_icon(icon, icon_size)
            self.box.pack_start(self.image, True, True, 0)

        self.label = Gtk.Label.new(label)
        self.box.pack_start(self.label, True, True, 0)
        return
Exemplo n.º 10
0
    def __init__(self, app_view, db, icons, show_ratings, store=None):
        Gtk.TreeView.__init__(self)
        self._logger = logging.getLogger("softwarecenter.view.appview")

        self.app_view = app_view
        self.db = db

        self.pressed = False
        self.focal_btn = None
        self._action_block_list = []
        self._needs_collapse = []
        self.expanded_path = None
        self.selected_row_renderer = None

        # pixbuf for the icon that is displayed in the selected row
        self.selected_row_icon = None

        #~ # if this hacked mode is available everything will be fast
        #~ # and we can set fixed_height mode and still have growing rows
        #~ # (see upstream gnome #607447)
        try:
            self.set_property("ubuntu-almost-fixed-height-mode", True)
            self.set_fixed_height_mode(True)
        except:
            self._logger.warn(
                "ubuntu-almost-fixed-height-mode extension not available")

        self.set_headers_visible(False)

        # our custom renderer
        self._renderer = CellRendererAppView(icons,
                                             self.create_pango_layout(''),
                                             show_ratings,
                                             Icons.INSTALLED_OVERLAY)
        self._renderer.set_pixbuf_width(32)
        self._renderer.set_button_spacing(em(0.3))

        # create buttons and set initial strings
        info = CellButtonRenderer(self, name=CellButtonIDs.INFO)
        info.set_markup_variants({self.VARIANT_INFO: _('More Info')})

        action = CellButtonRenderer(self, name=CellButtonIDs.ACTION)

        action.set_markup_variants({
            self.VARIANT_INSTALL: _('Install'),
            self.VARIANT_REMOVE: _('Remove'),
            self.VARIANT_PURCHASE: _(u'Buy\u2026')
        })

        self._renderer.button_pack_start(info)
        self._renderer.button_pack_end(action)

        self._column = Gtk.TreeViewColumn(
            "Applications",
            self._renderer,
            application=AppGenericStore.COL_ROW_DATA)
        self._column.set_cell_data_func(self._renderer,
                                        self._cell_data_func_cb)
        self._column.set_fixed_width(200)
        self._column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        self.append_column(self._column)

        # network status watcher
        watcher = get_network_watcher()
        watcher.connect("changed", self._on_net_state_changed, self._renderer)

        # custom cursor
        self._cursor_hand = Gdk.Cursor.new(Gdk.CursorType.HAND2)

        self.connect("style-updated", self._on_style_updated, self._renderer)
        # button and motion are "special"
        self.connect("button-press-event", self._on_button_press_event,
                     self._renderer)
        self.connect("button-release-event", self._on_button_release_event,
                     self._renderer)
        self.connect("key-press-event", self._on_key_press_event,
                     self._renderer)
        self.connect("key-release-event", self._on_key_release_event,
                     self._renderer)
        self.connect("motion-notify-event", self._on_motion, self._renderer)
        self.connect("cursor-changed", self._on_cursor_changed, self._renderer)
        # our own "activate" handler
        self.connect("row-activated", self._on_row_activated, self._renderer)

        self.backend = get_install_backend()
        self._transactions_connected = False
        self.connect('realize', self._on_realize, self._renderer)
Exemplo n.º 11
0
    def __init__(self, app_view, db, icons, show_ratings, store=None):
        Gtk.TreeView.__init__(self)
        self._logger = logging.getLogger("softwarecenter.view.appview")

        self.app_view = app_view
        self.db = db

        self.pressed = False
        self.focal_btn = None
        self._action_block_list = []
        self._needs_collapse = []
        self.expanded_path = None

        #~ # if this hacked mode is available everything will be fast
        #~ # and we can set fixed_height mode and still have growing rows
        #~ # (see upstream gnome #607447)
        try:
            self.set_property("ubuntu-almost-fixed-height-mode", True)
            self.set_fixed_height_mode(True)
        except:
            self._logger.warn("ubuntu-almost-fixed-height-mode extension not available")

        self.set_headers_visible(False)

        # a11y: this is a cell renderer that only displays a icon, but still
        #       has a markup property for orca and friends
        # we use it so that orca and other a11y tools get proper text to read
        # it needs to be the first one, because that is what the tools look
        # at by default
        tr = CellRendererAppView(icons,
                                 self.create_pango_layout(''),
                                 show_ratings,
                                 Icons.INSTALLED_OVERLAY)
        tr.set_pixbuf_width(32)
        tr.set_button_spacing(em(0.3))

        # create buttons and set initial strings
        info = CellButtonRenderer(self,
                                  name=CellButtonIDs.INFO)
        info.set_markup_variants(
                    {self.VARIANT_INFO: _('More Info')})

        action = CellButtonRenderer(self,
                                    name=CellButtonIDs.ACTION)

        action.set_markup_variants(
                {self.VARIANT_INSTALL: _('Install'),
                 self.VARIANT_REMOVE: _('Remove'),
                 self.VARIANT_PURCHASE: _(u'Buy\u2026')})

        tr.button_pack_start(info)
        tr.button_pack_end(action)

        column = Gtk.TreeViewColumn("Applications", tr,
                                    application=AppGenericStore.COL_ROW_DATA)
        column.set_cell_data_func(tr, self._cell_data_func_cb)
        column.set_fixed_width(200)
        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        self.append_column(column)

        # network status watcher
        watcher = get_network_watcher()
        watcher.connect("changed", self._on_net_state_changed, tr)

        # custom cursor
        self._cursor_hand = Gdk.Cursor.new(Gdk.CursorType.HAND2)

        self.connect("style-updated", self._on_style_updated, tr)
        # button and motion are "special"
        self.connect("button-press-event", self._on_button_press_event, tr)
        self.connect("button-release-event", self._on_button_release_event, tr)
        self.connect("key-press-event", self._on_key_press_event, tr)
        self.connect("key-release-event", self._on_key_release_event, tr)
        self.connect("motion-notify-event", self._on_motion, tr)
        self.connect("cursor-changed", self._on_cursor_changed, tr)
        # our own "activate" handler
        self.connect("row-activated", self._on_row_activated, tr)

        self.backend = get_install_backend()
        self._transactions_connected = False
        self.connect('realize', self._on_realize, tr)
class PendingSymbolicIcon(SymbolicIcon, RotationAboutCenterAnimation):

    BUBBLE_MAX_BORDER_RADIUS = em()
    BUBBLE_XPADDING = 5
    BUBBLE_YPADDING = 2
    BUBBLE_FONT_DESC = "Bold 8.5"

    def __init__(self, name):
        SymbolicIcon.__init__(self, name)
        RotationAboutCenterAnimation.__init__(self)

        # for painting the trans count bubble
        self.layout = self.create_pango_layout("")
        self.transaction_count = 0

    def on_draw(self, widget, cr, *args, **kwargs):
        cr.save()
        if self.is_animating():
            # translate to the center, then set the rotation
            a = widget.get_allocation()
            cr.translate(a.width * 0.5, a.height * 0.5)
            cr.rotate(self.rotation)
            # pass on the translation details
            kwargs['xo'] = -(a.width * 0.5)
            kwargs['yo'] = -(a.height * 0.5)

        # do icon drawing
        SymbolicIcon.on_draw(self, widget, cr, *args, **kwargs)
        cr.restore()

        if not self.is_animating() or not self.transaction_count:
            return

        # paint transactions bubble

        # get the layout extents and calc the bubble size
        ex = self.layout.get_pixel_extents()[1]
        x = ((a.width - self.icon.get_width()) / 2 +
            self.icon.get_width() - ex.width + 2)
        y = ((a.height - self.icon.get_height()) / 2 +
            self.icon.get_height() - ex.height + 2)
        w = ex.width + 2 * self.BUBBLE_XPADDING
        h = ex.height + 2 * self.BUBBLE_YPADDING

        border_radius = w / 3
        if border_radius > self.BUBBLE_MAX_BORDER_RADIUS:
            border_radius = self.BUBBLE_MAX_BORDER_RADIUS

        # paint background
        context = widget.get_style_context()
        context.save()
        color = context.get_background_color(Gtk.StateFlags.SELECTED)
        rounded_rect(cr, x + 1, y + 1, w - 2, h - 2, border_radius)
        Gdk.cairo_set_source_rgba(cr, color)
        cr.fill()
        context.restore()

        # paint outline
        rounded_rect(cr, x + 1.5, y + 1.5, w - 3, h - 3, border_radius - 1)
        cr.set_source_rgb(1, 1, 1)
        cr.set_line_width(1)
        cr.stroke()

        # paint layout
        cr.save()
        cr.translate(x + (w - ex.width) * 0.5, y + (h - ex.height) * 0.5)
        cr.move_to(0, 1)
        PangoCairo.layout_path(cr, self.layout)
        cr.set_source_rgba(0, 0, 0, 0.6)
        cr.fill()
        Gtk.render_layout(context, cr, 0, 0, self.layout)
        cr.restore()

    def set_transaction_count(self, count):
        if count == self.transaction_count:
            return
        self.transaction_count = count
        m = ('<span font_desc="%s" color="%s">%i</span>' %
            (self.BUBBLE_FONT_DESC, "white", count))
        self.layout.set_markup(m, -1)
        self.queue_draw()
Exemplo n.º 13
0
    def __init__(self, helper, doc, icon_size=48):
        TileButton.__init__(self)
        self._pressed = False

        label = helper.get_appname(doc)
        icon = helper.get_icon_at_size(doc, icon_size, icon_size)
        stats = helper.get_review_stats(doc)
        doc.installed = doc.available = None
        self.is_installed = helper.is_installed(doc)
        self._overlay = helper.icons.load_icon(Icons.INSTALLED_OVERLAY,
                                               self.INSTALLED_OVERLAY_SIZE,
                                               0) # flags

        self.box.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.box.set_spacing(StockEms.SMALL)

        self.content_left = Gtk.Box.new(Gtk.Orientation.VERTICAL, StockEms.MEDIUM)
        self.content_right = Gtk.Box.new(Gtk.Orientation.VERTICAL, 1)
        self.box.pack_start(self.content_left, False, False, 0)
        self.box.pack_start(self.content_right, False, False, 0)
        self.image = _parse_icon(icon, icon_size)
        self.content_left.pack_start(self.image, False, False, 0)

        self.title = Gtk.Label.new(self._MARKUP % GObject.markup_escape_text(label))
        self.title.set_alignment(0.0, 0.5)
        self.title.set_use_markup(True)
        self.title.set_ellipsize(Pango.EllipsizeMode.END)
        self.content_right.pack_start(self.title, False, False, 0)

        categories = helper.get_categories(doc)
        if categories is not None:
            self.category = Gtk.Label.new('<span font_desc="%i">%s</span>' % (em(0.6), GObject.markup_escape_text(categories)))
            self.category.set_use_markup(True)
            self.category.set_alignment(0.0, 0.5)
            self.category.set_ellipsize(Pango.EllipsizeMode.END)
            self.content_right.pack_start(self.category, False, False, 4)

        stats_a11y = None
        if stats is not None:
            self.stars = Star(size=StarSize.SMALL)
            self.stars.render_outline = True
            self.stars.set_rating(stats.ratings_average)
            self.rating_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, StockEms.SMALL)
            self.rating_box.pack_start(self.stars, False, False, 0)
            self.n_ratings = Gtk.Label.new(
                '<span font_desc="%i"> (%i)</span>' %  (
                    em(0.45), stats.ratings_total))
            self.n_ratings.set_use_markup(True)
            self.n_ratings.set_name("subtle-label")
            self.n_ratings.set_alignment(0.0, 0.5)
            self.rating_box.pack_start(self.n_ratings, False, False, 0)
            self.content_right.pack_start(self.rating_box, False, False, 0)
            # TRANSLATORS: this is an accessibility description for eg orca and
            # is not visible in the ui
            stats_a11y = _('%(stars)d stars - %(reviews)d reviews') % {
                'stars': stats.ratings_average, 'reviews': stats.ratings_total}
        
            #work out width tile needs to be to ensure ratings text is all visible
            req_width = (self.stars.size_request().width +
                         self.image.size_request().width +
                         self.n_ratings.size_request().width +
                         StockEms.MEDIUM * 3
                         )
            global _global_featured_tile_width
            _global_featured_tile_width = max(_global_featured_tile_width,
                                              req_width)

        details = AppDetails(db=helper.db, doc=doc)
        price = details.price or _("Free")
        if price == '0.00':
            price = _("Free")
        if price != _("Free"):
            price = 'US$ ' + price
        self.price = Gtk.Label.new(
            '<span font_desc="%i">%s</span>' % (em(0.6), price))
        self.price.set_use_markup(True)
        self.price.set_name("subtle-label")
        self.price.set_alignment(0.0, 0.5)
        self.content_right.pack_start(self.price, False, False, 0)

        self.set_name("featured-tile")

        a11y_name = '. '.join([t for t in [label, categories, stats_a11y, price] if t])    
        self.get_accessible().set_name(a11y_name)

        backend = get_install_backend()
        backend.connect("transaction-finished",
                        self.on_transaction_finished,
                        helper, doc)

        self.connect("enter-notify-event", self.on_enter)
        self.connect("leave-notify-event", self.on_leave)
        self.connect("button-press-event", self.on_press)
        self.connect("button-release-event", self.on_release)
        return
Exemplo n.º 14
0
        cr.restore()
        return

    def on_enter(self, widget, event):
        window = self.get_window()
        window.set_cursor(_HAND)
        return

    def on_leave(self, widget, event):
        window = self.get_window()
        window.set_cursor(None)
        return


_global_featured_tile_width = em(11)
class FeaturedTile(TileButton):

    INSTALLED_OVERLAY_SIZE = 22
    _MARKUP = '<b><small>%s</small></b>'

    def __init__(self, helper, doc, icon_size=48):
        TileButton.__init__(self)
        self._pressed = False

        label = helper.get_appname(doc)
        icon = helper.get_icon_at_size(doc, icon_size, icon_size)
        stats = helper.get_review_stats(doc)
        doc.installed = doc.available = None
        self.is_installed = helper.is_installed(doc)
        self._overlay = helper.icons.load_icon(Icons.INSTALLED_OVERLAY,
Exemplo n.º 15
0
class SectionSelector(TileToggleButton):

    MIN_WIDTH = em(5)
    _MARKUP = '<small>%s</small>'

    def __init__(self, label, icon, icon_size=Gtk.IconSize.DIALOG):
        TileToggleButton.__init__(self)
        markup = self._MARKUP % label
        self.build_default(markup, icon, icon_size)
        self.label.set_use_markup(True)
        self.label.set_justify(Gtk.Justification.CENTER)

        context = self.get_style_context()
        context.add_class("section-sel-bg")

        context = self.label.get_style_context()
        context.add_class("section-sel")

        self.draw_hint_has_channel_selector = False
        self._alloc = None
        self._bg_cache = {}

        self.connect('size-allocate', self.on_size_allocate)
        self.connect('style-updated', self.on_style_updated)

    def on_size_allocate(self, *args):
        alloc = self.get_allocation()

        if (self._alloc is None or self._alloc.width != alloc.width
                or self._alloc.height != alloc.height):
            self._alloc = alloc
            # reset the bg cache
            self._bg_cache = {}

    def on_style_updated(self, *args):
        # also reset the bg cache
        self._bg_cache = {}

    def _cache_bg_for_state(self, state):
        a = self.get_allocation()
        # tmp surface on which we render the button bg as per the gtk
        # theme engine
        _surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, a.width, a.height)
        cr = cairo.Context(_surf)

        context = self.get_style_context()
        context.save()
        context.set_state(state)

        Gtk.render_background(context, cr, -5, -5, a.width + 10, a.height + 10)
        Gtk.render_frame(context, cr, -5, -5, a.width + 10, a.height + 10)
        del cr

        # new surface which will be cached which
        surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, a.width, a.height)
        cr = cairo.Context(surf)

        # gradient for masking
        lin = cairo.LinearGradient(0, 0, 0, a.height)
        lin.add_color_stop_rgba(0.0, 1, 1, 1, 0.1)
        lin.add_color_stop_rgba(0.25, 1, 1, 1, 0.7)
        lin.add_color_stop_rgba(0.5, 1, 1, 1, 1.0)
        lin.add_color_stop_rgba(0.75, 1, 1, 1, 0.7)
        lin.add_color_stop_rgba(1.0, 1, 1, 1, 0.1)

        cr.set_source_surface(_surf, 0, 0)
        cr.mask(lin)
        del cr

        # cache the resulting surf...
        self._bg_cache[state] = surf

    def do_draw(self, cr):
        state = self.get_state_flags()
        if self.get_active():
            if state not in self._bg_cache:
                self._cache_bg_for_state(state)

            cr.set_source_surface(self._bg_cache[state], 0, 0)
            cr.paint()

        for child in self:
            self.propagate_draw(child, cr)
Exemplo n.º 16
0
    def __init__(self, helper, doc, icon_size=48):
        TileButton.__init__(self)
        self._pressed = False

        label = helper.get_appname(doc)
        icon = helper.get_icon_at_size(doc, icon_size, icon_size)
        stats = helper.get_review_stats(doc)
        helper.update_availability(doc)
        helper.connect("needs-refresh", self._on_needs_refresh, doc, icon_size)
        self.is_installed = helper.is_installed(doc)
        self._overlay = helper.icons.load_icon(Icons.INSTALLED_OVERLAY,
                                               self.INSTALLED_OVERLAY_SIZE,
                                               0)  # flags

        self.box.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.box.set_spacing(StockEms.SMALL)

        self.content_left = Gtk.Box.new(Gtk.Orientation.VERTICAL,
                                        StockEms.MEDIUM)
        self.content_right = Gtk.Box.new(Gtk.Orientation.VERTICAL, 1)
        self.box.pack_start(self.content_left, False, False, 0)
        self.box.pack_start(self.content_right, False, False, 0)
        self.image = Gtk.Image()
        _update_icon(self.image, icon, icon_size)
        self.content_left.pack_start(self.image, False, False, 0)

        self.title = Gtk.Label.new(self._MARKUP %
                                   GObject.markup_escape_text(label))
        self.title.set_alignment(0.0, 0.5)
        self.title.set_use_markup(True)
        self.title.set_tooltip_text(label)
        self.title.set_ellipsize(Pango.EllipsizeMode.END)
        self.content_right.pack_start(self.title, False, False, 0)

        categories = helper.get_categories(doc)
        if categories is not None:
            self.category = Gtk.Label.new(
                '<span font_desc="%i">%s</span>' %
                (em(0.6), GObject.markup_escape_text(categories)))
            self.category.set_use_markup(True)
            self.category.set_alignment(0.0, 0.5)
            self.category.set_ellipsize(Pango.EllipsizeMode.END)
            self.content_right.pack_start(self.category, False, False, 4)

        stats_a11y = None
        if stats is not None:
            self.stars = Star(size=StarSize.SMALL)
            self.stars.render_outline = True
            self.stars.set_rating(stats.ratings_average)
            self.rating_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL,
                                          StockEms.SMALL)
            self.rating_box.pack_start(self.stars, False, False, 0)
            self.n_ratings = Gtk.Label.new(
                '<span font_desc="%i"> (%i)</span>' %
                (em(0.45), stats.ratings_total))
            self.n_ratings.set_use_markup(True)
            self.n_ratings.set_name("subtle-label")
            self.n_ratings.set_alignment(0.0, 0.5)
            self.rating_box.pack_start(self.n_ratings, False, False, 0)
            self.content_right.pack_start(self.rating_box, False, False, 0)
            # TRANSLATORS: this is an accessibility description for eg orca and
            # is not visible in the ui
            stats_a11y = _('%(stars)d stars - %(reviews)d reviews') % {
                'stars': stats.ratings_average,
                'reviews': stats.ratings_total
            }

            # work out width tile needs to be to ensure ratings text is all
            # visible
            req_width = (self.stars.size_request().width +
                         self.image.size_request().width +
                         self.n_ratings.size_request().width +
                         StockEms.MEDIUM * 3)
            global _global_featured_tile_width
            _global_featured_tile_width = max(_global_featured_tile_width,
                                              req_width)

        details = AppDetails(db=helper.db, doc=doc)
        # TRANSLATORS: Free here means Gratis
        price = details.price or _("Free")
        if price == '0.00':
            # TRANSLATORS: Free here means Gratis
            price = _("Free")
        # TRANSLATORS: Free here means Gratis
        if price != _("Free"):
            price = 'US$ ' + price
        self.price = Gtk.Label.new('<span font_desc="%i">%s</span>' %
                                   (em(0.6), price))
        self.price.set_use_markup(True)
        self.price.set_name("subtle-label")
        self.price.set_alignment(0.0, 0.5)
        self.content_right.pack_start(self.price, False, False, 0)

        self.set_name("featured-tile")

        a11y_name = '. '.join(
            [t for t in [label, categories, stats_a11y, price] if t])
        self.get_accessible().set_name(a11y_name)

        backend = get_install_backend()
        backend.connect("transaction-finished", self.on_transaction_finished,
                        helper, doc)

        self.connect("enter-notify-event", self.on_enter)
        self.connect("leave-notify-event", self.on_leave)
        self.connect("button-press-event", self.on_press)
        self.connect("button-release-event", self.on_release)
Exemplo n.º 17
0
        for child in self:
            self.propagate_draw(child, cr)

        cr.restore()

    def on_enter(self, widget, event):
        window = self.get_window()
        window.set_cursor(_HAND)

    def on_leave(self, widget, event):
        window = self.get_window()
        window.set_cursor(None)


_global_featured_tile_width = em(11)


class FeaturedTile(TileButton):

    INSTALLED_OVERLAY_SIZE = 22
    _MARKUP = '<b><small>%s</small></b>'

    def __init__(self, helper, doc, icon_size=48):
        TileButton.__init__(self)
        self._pressed = False

        label = helper.get_appname(doc)
        icon = helper.get_icon_at_size(doc, icon_size, icon_size)
        stats = helper.get_review_stats(doc)
        helper.update_availability(doc)