Example #1
0
    def __init__(self, on_filter_changed=lambda has_episodes: None):
        gtk.GenericTreeModel.__init__(self)

        # Callback for when the filter / list changes, gets one parameter
        # (has_episodes) that is True if the list has any episodes
        self._on_filter_changed = on_filter_changed

        self._downloading = lambda x: False
        self._include_description = False
        self._generate_thumbnails = False

        self._episodes = []

        # Filter to allow hiding some episodes
        self._filter = self.filter_new()
        self._view_mode = self.VIEW_ALL
        self._search_term = None
        self._filter.set_visible_func(self._filter_visible_func)

        # Are we currently showing the "all episodes" view?
        self._all_episodes_view = False

        # "ICON" is used to mark icon names in source files
        ICON = lambda x: x

        self._icon_cache = {}
        self.ICON_AUDIO_FILE = ICON('gpodder-audio')
        self.ICON_VIDEO_FILE = ICON('gpodder-video')
        self.ICON_IMAGE_FILE = ICON('general_image')
        self.ICON_GENERIC_FILE = ICON('filemanager_unknown_file')
        self.ICON_DOWNLOADING = ICON('gpodder-download')
        self.ICON_DELETED = ICON('camera_delete')
        self.ICON_UNPLAYED = ICON('emblem-new')
        self.ICON_LOCKED = ICON('emblem-readonly')
        self.ICON_MISSING = ICON('emblem-unreadable')
        self.ICON_NEW = gtk.STOCK_ABOUT

        normal_font = style.get_font_desc('SystemFont')
        normal_color = style.get_color('DefaultTextColor')
        normal = (normal_font.to_string(), normal_color.to_string())
        self._normal_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % normal

        active_font = style.get_font_desc('SystemFont')
        active_color = style.get_color('ActiveTextColor')
        active = (active_font.to_string(), active_color.to_string())
        self._active_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % active

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '\n<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self._unplayed_markup = self._normal_markup + sub
        self._active_markup += sub
Example #2
0
 def __init__(self):
     download.DownloadStatusModel.__init__(self)
     head_font = style.get_font_desc('SystemFont')
     head_color = style.get_color('ButtonTextColor')
     head = (head_font.to_string(), head_color.to_string())
     head = '<span font_desc="%s" foreground="%s">%%s</span>' % head
     sub_font = style.get_font_desc('SmallSystemFont')
     sub_color = style.get_color('SecondaryTextColor')
     sub = (sub_font.to_string(), sub_color.to_string())
     sub = '<span font_desc="%s" foreground="%s">%%s - %%s</span>' % sub
     self._markup_template = '\n'.join((head, sub))
Example #3
0
 def __init__(self):
     download.DownloadStatusModel.__init__(self)
     head_font = style.get_font_desc('SystemFont')
     head_color = style.get_color('ButtonTextColor')
     head = (head_font.to_string(), head_color.to_string())
     head = '<span font_desc="%s" foreground="%s">%%s</span>' % head
     sub_font = style.get_font_desc('SmallSystemFont')
     sub_color = style.get_color('SecondaryTextColor')
     sub = (sub_font.to_string(), sub_color.to_string())
     sub = '<span font_desc="%s" foreground="%s">%%s - %%s</span>' % sub
     self._markup_template = '\n'.join((head, sub))
Example #4
0
    def __init__(self, on_filter_changed=lambda has_episodes: None):
        gtk.GenericTreeModel.__init__(self)

        # Callback for when the filter / list changes, gets one parameter
        # (has_episodes) that is True if the list has any episodes
        self._on_filter_changed = on_filter_changed

        self._downloading = lambda x: False
        self._include_description = False
        self._generate_thumbnails = False

        self._episodes = []

        # Filter to allow hiding some episodes
        self._filter = self.filter_new()
        self._view_mode = self.VIEW_ALL
        self._search_term = None
        self._filter.set_visible_func(self._filter_visible_func)

        # Are we currently showing the "all episodes" view?
        self._all_episodes_view = False

        # "ICON" is used to mark icon names in source files
        ICON = lambda x: x

        self._icon_cache = {}
        self.ICON_AUDIO_FILE = ICON('gpodder-audio')
        self.ICON_VIDEO_FILE = ICON('gpodder-video')
        self.ICON_IMAGE_FILE = ICON('general_image')
        self.ICON_GENERIC_FILE = ICON('filemanager_unknown_file')
        self.ICON_DOWNLOADING = ICON('gpodder-download')
        self.ICON_DELETED = ICON('camera_delete')
        self.ICON_UNPLAYED = ICON('emblem-new')
        self.ICON_LOCKED = ICON('emblem-readonly')
        self.ICON_MISSING = ICON('emblem-unreadable')
        self.ICON_NEW = gtk.STOCK_ABOUT

        normal_font = style.get_font_desc('SystemFont')
        normal_color = style.get_color('DefaultTextColor')
        normal = (normal_font.to_string(), normal_color.to_string())
        self._normal_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % normal

        active_font = style.get_font_desc('SystemFont')
        active_color = style.get_color('ActiveTextColor')
        active = (active_font.to_string(), active_color.to_string())
        self._active_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % active

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '\n<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self._unplayed_markup = self._normal_markup + sub
        self._active_markup += sub
Example #5
0
    def __init__(self, importer):
        gtk.ListStore.__init__(self, bool, str, str)

        head_font = style.get_font_desc('SystemFont')
        head_color = style.get_color('ButtonTextColor')
        head = (head_font.to_string(), head_color.to_string())
        head = '<span font_desc="%s" foreground="%s">%%s</span>' % head

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '<span font_desc="%s" foreground="%s">%%s</span>' % sub
        self._markup_template = '\n'.join((head, sub))

        for channel in importer.items:
            self.append([False, self._format_channel(channel), channel['url']])
Example #6
0
    def __init__(self, importer):
        gtk.ListStore.__init__(self, bool, str, str)

        head_font = style.get_font_desc('SystemFont')
        head_color = style.get_color('ButtonTextColor')
        head = (head_font.to_string(), head_color.to_string())
        head = '<span font_desc="%s" foreground="%s">%%s</span>' % head

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '<span font_desc="%s" foreground="%s">%%s</span>' % sub
        self._markup_template = '\n'.join((head, sub))

        for channel in importer.items:
            self.append([False, self._format_channel(channel), channel['url']])
Example #7
0
    def __init__(self, *args):
        model.PodcastListModel.__init__(self, *args)

        normal_font = style.get_font_desc('SystemFont')
        normal_color = style.get_color('DefaultTextColor')
        normal = (normal_font.to_string(), normal_color.to_string())
        self._normal_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % normal

        active_font = style.get_font_desc('SystemFont')
        active_color = style.get_color('ActiveTextColor')
        active = (active_font.to_string(), active_color.to_string())
        self._active_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % active

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '\n<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self._unplayed_markup = self._normal_markup + sub
        self._active_markup += sub
Example #8
0
    def __init__(self, *args):
        model.PodcastListModel.__init__(self, *args)

        normal_font = style.get_font_desc('SystemFont')
        normal_color = style.get_color('DefaultTextColor')
        normal = (normal_font.to_string(), normal_color.to_string())
        self._normal_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % normal

        active_font = style.get_font_desc('SystemFont')
        active_color = style.get_color('ActiveTextColor')
        active = (active_font.to_string(), active_color.to_string())
        self._active_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % active

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '\n<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self._unplayed_markup = self._normal_markup + sub
        self._active_markup += sub
Example #9
0
    def new(self):
        self.current_mode = -1
        self.pause_resume_mode = -1
        self.episode = None
        self.download_task_monitor = None
        self.action_table = None
        self.should_set_new_value = False
        self.new_keep_value = False

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        self._sub_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self.label_description = gtk.Label()
        self.label_description.set_ellipsize(pango.ELLIPSIZE_END)
        self.label_description.set_alignment(0., 0.)
    def new(self):
        self.current_mode = -1
        self.pause_resume_mode = -1
        self.episode = None
        self.download_task_monitor = None
        self.action_table = None
        self.should_set_new_value = False
        self.new_keep_value = False

        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        self._sub_markup = '<span font_desc="%s" foreground="%s">%%s</span>' % sub

        self.label_description = gtk.Label()
        self.label_description.set_ellipsize(pango.ELLIPSIZE_END)
        self.label_description.set_alignment(0., 0.)
    def on_treeview_expose_event(self, treeview, event):
        if event.window == treeview.get_bin_window():
            model = treeview.get_model()
            if (model is not None and model.get_iter_first() is not None):
                return False

            ctx = event.window.cairo_create()
            ctx.rectangle(event.area.x, event.area.y,
                    event.area.width, event.area.height)
            ctx.clip()
            x, y, width, height, depth = event.window.get_geometry()

            if self._is_updating:
                text = _('Loading podcast list')
            else:
                text = _('No podcasts')

            from gpodder.gtkui.frmntl import style
            font_desc = style.get_font_desc('LargeSystemFont')
            draw_text_box_centered(ctx, treeview, width, height, text, font_desc)

        return False
Example #12
0
    def on_treeview_expose_event(self, treeview, event):
        if event.window == treeview.get_bin_window():
            model = treeview.get_model()
            if (model is not None and model.get_iter_first() is not None):
                return False

            ctx = event.window.cairo_create()
            ctx.rectangle(event.area.x, event.area.y, event.area.width,
                          event.area.height)
            ctx.clip()
            x, y, width, height, depth = event.window.get_geometry()

            if self._is_updating:
                text = _('Loading podcast list')
            else:
                text = _('No podcasts')

            from gpodder.gtkui.frmntl import style
            font_desc = style.get_font_desc('LargeSystemFont')
            draw_text_box_centered(ctx, treeview, width, height, text,
                                   font_desc)

        return False
    def new( self):
        self._config.connect_gtk_window(self.gPodderEpisodeSelector, 'episode_selector', True)
        if not hasattr( self, 'callback'):
            self.callback = None

        if not hasattr(self, 'remove_callback'):
            self.remove_callback = None

        if not hasattr(self, 'remove_action'):
            self.remove_action = _('Remove')

        if not hasattr(self, 'remove_finished'):
            self.remove_finished = None

        if not hasattr( self, 'episodes'):
            self.episodes = []

        if not hasattr( self, 'size_attribute'):
            self.size_attribute = 'length'

        if not hasattr(self, 'tooltip_attribute'):
            self.tooltip_attribute = 'description'

        if not hasattr( self, 'selection_buttons'):
            self.selection_buttons = {}

        if not hasattr( self, 'selected_default'):
            self.selected_default = False

        if not hasattr( self, 'selected'):
            self.selected = [self.selected_default]*len(self.episodes)

        if len(self.selected) < len(self.episodes):
            self.selected += [self.selected_default]*(len(self.episodes)-len(self.selected))

        if not hasattr( self, 'columns'):
            self.columns = (('title_markup', None, None, _('Episode')),)

        if hasattr( self, 'title'):
            self.gPodderEpisodeSelector.set_title( self.title)

        if hasattr(self, 'instructions'):
            #self.show_message(self.instructions)
            pass

        if self.remove_callback is not None:
            self.btnRemoveAction.show()
            self.btnRemoveAction.set_label(self.remove_action)

        if hasattr(self, 'stock_ok_button'):
            if self.stock_ok_button == 'gpodder-download':
                self.btnOK.set_image(gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON))
                self.btnOK.set_label(_('Download'))
            else:
                self.btnOK.set_label(self.stock_ok_button)
                self.btnOK.set_use_stock(True)

        # Work around Maemo bug #4718
        self.btnOK.set_name('HildonButton-finger')
        self.btnRemoveAction.set_name('HildonButton-finger')

        # Make sure the window comes up quick
        self.main_window.show()
        self.main_window.present()
        while gtk.events_pending():
            gtk.main_iteration(False)

        # Determine the styling for the list items
        head_font = style.get_font_desc('SystemFont')
        head_color = style.get_color('ButtonTextColor')
        head = (head_font.to_string(), head_color.to_string())
        head = '<span font_desc="%s" foreground="%s">%%s</span>' % head
        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '<span font_desc="%s" foreground="%s">%%s</span>' % sub
        self._markup_template = '\n'.join((head, sub))

        # Context menu stuff for the treeview (shownotes)
        self.touched_episode = None
        if hasattr(self, 'show_episode_shownotes'):
            self.context_menu = gtk.Menu()
            # "Emulate" hildon_gtk_menu_new
            self.context_menu.set_name('hildon-context-sensitive-menu')
            self.context_menu.append(self.action_shownotes.create_menu_item())
            self.context_menu.show_all()
            self.treeviewEpisodes.connect('button-press-event', self.on_treeview_button_press)
            self.treeviewEpisodes.tap_and_hold_setup(self.context_menu)

        # This regex gets the two lines of the normal Maemo markup,
        # as used on Maemo 4 (see maemo_markup() in gpodder.model)
        markup_re = re.compile(r'<b>(.*)</b>\n<small>(.*)</small>')

        next_column = self.COLUMN_ADDITIONAL
        for name, sort_name, sort_type, caption in self.columns:
            renderer = gtk.CellRendererText()
            if next_column < self.COLUMN_ADDITIONAL + 2:
                renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
            column = gtk.TreeViewColumn(caption, renderer, markup=next_column)
            column.set_resizable( True)
            # Only set "expand" on the first column
            if next_column < self.COLUMN_ADDITIONAL + 1:
                column.set_expand(True)
            if sort_name is not None:
                column.set_sort_column_id(next_column+1)
            else:
                column.set_sort_column_id(next_column)
            self.treeviewEpisodes.append_column( column)
            next_column += 1
            
            if sort_name is not None:
                # add the sort column
                column = gtk.TreeViewColumn()
                column.set_visible(False)
                self.treeviewEpisodes.append_column( column)
                next_column += 1

        column_types = [ int, str, bool ]
        # add string column type plus sort column type if it exists
        for name, sort_name, sort_type, caption in self.columns:
            column_types.append(str)
            if sort_name is not None:
                column_types.append(sort_type)
        self.model = gtk.ListStore( *column_types)

        tooltip = None
        for index, episode in enumerate( self.episodes):
            if self.tooltip_attribute is not None:
                try:
                    tooltip = getattr(episode, self.tooltip_attribute)
                except:
                    log('Episode object %s does not have tooltip attribute: "%s"', episode, self.tooltip_attribute, sender=self)
                    tooltip = None
            row = [ index, tooltip, self.selected[index] ]
            for name, sort_name, sort_type, caption in self.columns:
                if name.startswith('maemo_') and name.endswith('markup'):
                    # This will fetch the Maemo 4 markup from the object
                    # and then filter the two lines (using markup_re.match)
                    # and use the markup template to create Maemo 5 markup
                    markup = getattr(episode, name)
                    args = markup_re.match(markup).groups()
                    row.append(self._markup_template % args)
                elif not hasattr(episode, name):
                    log('Warning: Missing attribute "%s"', name, sender=self)
                    row.append(None)
                else:
                    row.append(getattr( episode, name))
                    
                if sort_name is not None:
                    if not hasattr(episode, sort_name):
                        log('Warning: Missing attribute "%s"', sort_name, sender=self)
                        row.append(None)
                    else:
                        row.append(getattr( episode, sort_name))
            self.model.append( row)

        self.treeviewEpisodes.set_rules_hint( True)
        self.treeviewEpisodes.set_model( self.model)
        self.treeviewEpisodes.columns_autosize()
        self.calculate_total_size()

        selection = self.treeviewEpisodes.get_selection()
        selection.connect('changed', self.on_selection_changed)
        selection.set_mode(gtk.SELECTION_MULTIPLE)
        selection.unselect_all()

        appmenu = hildon.AppMenu()
        for action in (self.action_select_all, \
                       self.action_select_none):
            button = gtk.Button()
            action.connect_proxy(button)
            appmenu.append(button)

        if self.selection_buttons:
            for label in self.selection_buttons:
                button = gtk.Button(label)
                button.connect('clicked', self.custom_selection_button_clicked, label)
                appmenu.append(button)

        appmenu.show_all()
        self.main_window.set_app_menu(appmenu)
Example #14
0
    def new( self):
        self._config.connect_gtk_window(self.gPodderEpisodeSelector, 'episode_selector', True)
        if not hasattr( self, 'callback'):
            self.callback = None

        if not hasattr(self, 'remove_callback'):
            self.remove_callback = None

        if not hasattr(self, 'remove_action'):
            self.remove_action = _('Remove')

        if not hasattr(self, 'remove_finished'):
            self.remove_finished = None

        if not hasattr( self, 'episodes'):
            self.episodes = []

        if not hasattr( self, 'size_attribute'):
            self.size_attribute = 'length'

        if not hasattr(self, 'tooltip_attribute'):
            self.tooltip_attribute = 'description'

        if not hasattr( self, 'selection_buttons'):
            self.selection_buttons = {}

        if not hasattr( self, 'selected_default'):
            self.selected_default = False

        if not hasattr( self, 'selected'):
            self.selected = [self.selected_default]*len(self.episodes)

        if len(self.selected) < len(self.episodes):
            self.selected += [self.selected_default]*(len(self.episodes)-len(self.selected))

        if not hasattr( self, 'columns'):
            self.columns = (('title_markup', None, None, _('Episode')),)

        if hasattr( self, 'title'):
            self.gPodderEpisodeSelector.set_title( self.title)

        if hasattr(self, 'instructions'):
            #self.show_message(self.instructions)
            pass

        if self.remove_callback is not None:
            self.btnRemoveAction.show()
            self.btnRemoveAction.set_label(self.remove_action)

        if hasattr(self, 'stock_ok_button'):
            if self.stock_ok_button == 'gpodder-download':
                self.btnOK.set_image(gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON))
                self.btnOK.set_label(_('Download'))
            else:
                self.btnOK.set_label(self.stock_ok_button)
                self.btnOK.set_use_stock(True)

        # Work around Maemo bug #4718
        self.btnOK.set_name('HildonButton-finger')
        self.btnRemoveAction.set_name('HildonButton-finger')

        # Make sure the window comes up quick
        self.main_window.show()
        self.main_window.present()
        while gtk.events_pending():
            gtk.main_iteration(False)

        # Determine the styling for the list items
        head_font = style.get_font_desc('SystemFont')
        head_color = style.get_color('ButtonTextColor')
        head = (head_font.to_string(), head_color.to_string())
        head = '<span font_desc="%s" foreground="%s">%%s</span>' % head
        sub_font = style.get_font_desc('SmallSystemFont')
        sub_color = style.get_color('SecondaryTextColor')
        sub = (sub_font.to_string(), sub_color.to_string())
        sub = '<span font_desc="%s" foreground="%s">%%s</span>' % sub
        self._markup_template = '\n'.join((head, sub))

        # Context menu stuff for the treeview (shownotes)
        self.touched_episode = None
        if hasattr(self, 'show_episode_shownotes'):
            self.context_menu = gtk.Menu()
            # "Emulate" hildon_gtk_menu_new
            self.context_menu.set_name('hildon-context-sensitive-menu')
            self.context_menu.append(self.action_shownotes.create_menu_item())
            self.context_menu.show_all()
            self.treeviewEpisodes.connect('button-press-event', self.on_treeview_button_press)
            self.treeviewEpisodes.tap_and_hold_setup(self.context_menu)

        # This regex gets the two lines of the normal Maemo markup,
        # as used on Maemo 4 (see maemo_markup() in gpodder.model)
        markup_re = re.compile(r'<b>(.*)</b>\n<small>(.*)</small>')

        next_column = self.COLUMN_ADDITIONAL
        for name, sort_name, sort_type, caption in self.columns:
            renderer = gtk.CellRendererText()
            if next_column < self.COLUMN_ADDITIONAL + 2:
                renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
            column = gtk.TreeViewColumn(caption, renderer, markup=next_column)
            column.set_resizable( True)
            # Only set "expand" on the first column
            if next_column < self.COLUMN_ADDITIONAL + 1:
                column.set_expand(True)
            if sort_name is not None:
                column.set_sort_column_id(next_column+1)
            else:
                column.set_sort_column_id(next_column)
            self.treeviewEpisodes.append_column( column)
            next_column += 1
            
            if sort_name is not None:
                # add the sort column
                column = gtk.TreeViewColumn()
                column.set_visible(False)
                self.treeviewEpisodes.append_column( column)
                next_column += 1

        column_types = [ int, str, bool ]
        # add string column type plus sort column type if it exists
        for name, sort_name, sort_type, caption in self.columns:
            column_types.append(str)
            if sort_name is not None:
                column_types.append(sort_type)
        self.model = gtk.ListStore( *column_types)

        tooltip = None
        for index, episode in enumerate( self.episodes):
            if self.tooltip_attribute is not None:
                try:
                    tooltip = getattr(episode, self.tooltip_attribute)
                except:
                    log('Episode object %s does not have tooltip attribute: "%s"', episode, self.tooltip_attribute, sender=self)
                    tooltip = None
            row = [ index, tooltip, self.selected[index] ]
            for name, sort_name, sort_type, caption in self.columns:
                if name.startswith('maemo_') and name.endswith('markup'):
                    # This will fetch the Maemo 4 markup from the object
                    # and then filter the two lines (using markup_re.match)
                    # and use the markup template to create Maemo 5 markup
                    markup = getattr(episode, name)
                    args = markup_re.match(markup).groups()
                    row.append(self._markup_template % args)
                elif not hasattr(episode, name):
                    log('Warning: Missing attribute "%s"', name, sender=self)
                    row.append(None)
                else:
                    row.append(getattr( episode, name))
                    
                if sort_name is not None:
                    if not hasattr(episode, sort_name):
                        log('Warning: Missing attribute "%s"', sort_name, sender=self)
                        row.append(None)
                    else:
                        row.append(getattr( episode, sort_name))
            self.model.append( row)

        self.treeviewEpisodes.set_rules_hint( True)
        self.treeviewEpisodes.set_model( self.model)
        self.treeviewEpisodes.columns_autosize()
        self.calculate_total_size()

        selection = self.treeviewEpisodes.get_selection()
        selection.connect('changed', self.on_selection_changed)
        selection.set_mode(gtk.SELECTION_MULTIPLE)
        selection.unselect_all()

        appmenu = hildon.AppMenu()
        for action in (self.action_select_all, \
                       self.action_select_none):
            button = gtk.Button()
            action.connect_proxy(button)
            appmenu.append(button)

        if self.selection_buttons:
            for label in self.selection_buttons:
                button = gtk.Button(label)
                button.connect('clicked', self.custom_selection_button_clicked, label)
                appmenu.append(button)

        appmenu.show_all()
        self.main_window.set_app_menu(appmenu)