示例#1
0
class FilemanagerView(PidaView):

    _columns = [
        Column("icon_stock_id", use_stock=True),
        Column("state_markup", use_markup=True),
        Column("markup", use_markup=True),
        Column("lower_name", visible=False, searchable=True),
    ]

    label_text = _('Files')
    icon_name = 'file-manager'
    key = 'filemanager.list'

    def create_ui(self):
        self._vbox = gtk.VBox()
        self._vbox.show()
        self.create_toolbar()
        self._file_hidden_check_actions = {}
        self._create_file_hidden_check_toolbar()
        self.create_file_list()
        self._clipboard_file = None
        self._fix_paste_sensitivity()
        self.add_main_widget(self._vbox)

    def create_file_list(self):
        self.file_list = ObjectList()
        self.file_list.set_headers_visible(False)

        def visible_func(item):
            return item is not None and item.visible

        self.file_list.set_visible_func(visible_func)
        self.file_list.set_columns(self._columns)
        self.file_list.connect('selection-changed', self.on_selection_changed)
        self.file_list.connect('item-activated', self.on_file_activated)
        self.file_list.connect('item-right-clicked', self.on_file_right_click)
        self.entries = {}
        self.update_to_path(self.svc.path)
        self.file_list.show()

        self._file_scroll = gtk.ScrolledWindow(
            hadjustment=self.file_list.props.hadjustment,
            vadjustment=self.file_list.props.vadjustment,
        )
        self._file_scroll.set_policy(gtk.POLICY_AUTOMATIC,
                                     gtk.POLICY_AUTOMATIC)
        self._file_scroll.add(self.file_list)
        self._file_scroll.show()

        self._vbox.pack_start(self._file_scroll)
        self._sort_combo = AttrSortCombo(self.file_list, [
            ('is_dir_sort', _('Directories First')),
            ('path', _('File Path')),
            ('lower_name', _('File Name')),
            ('name', _('File Name (Case Sensitive)')),
            ('extension_sort', _('Extension')),
            ('state', _('Version Control Status')),
        ], 'is_dir_sort')
        self._sort_combo.show()
        self._vbox.pack_start(self._sort_combo, expand=False)
        self.on_selection_changed(self.file_list)

    def create_toolbar(self):
        self._uim = gtk.UIManager()
        self._uim.insert_action_group(self.svc.get_action_group(), 0)
        self._uim.add_ui_from_string(
            pkgutil.get_data(__name__, 'uidef/filemanager-toolbar.xml'))
        self._uim.ensure_update()
        self._toolbar = self._uim.get_toplevels('toolbar')[0]
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_MENU)
        self._vbox.pack_start(self._toolbar, expand=False)
        self._toolbar.show_all()

    def add_or_update_file(self,
                           name,
                           basepath,
                           state,
                           select=False,
                           parent_link=False):
        if basepath != self.path and not parent_link:
            return
        entry = self.entries.setdefault(
            name, FileEntry(name, basepath, self, parent_link=parent_link))
        entry.state = state

        self.show_or_hide(entry, select=select)

    def show_or_hide(self, entry, select=False):
        def check(checker):
            if (checker.identifier in self._file_hidden_check_actions) and \
               (self._file_hidden_check_actions[checker.identifier].get_active()):
                return checker(
                    name=entry.name,
                    path=entry.parent_path,
                    state=entry.state,
                )
            else:
                return True

        if self.svc.opt('show_hidden') or entry.parent_link:
            show = True
        else:
            show = all(
                check(x) for x in self.svc.features['file_hidden_check'])

        entry.visible = show
        if entry not in self.file_list:
            self.file_list.append(entry)
        self.file_list.update(entry)

        if show and select:
            self.file_list.selected_item = entry

    def update_to_path(self, new_path=None, select=None):
        if new_path is None:
            new_path = self.path
        else:
            self.path = check_or_home(new_path)

        self.file_list.clear()
        self.entries.clear()

        if self.svc.opt('show_parent'):
            parent = os.path.normpath(os.path.join(new_path, os.path.pardir))
            # skip if we are already on the root
            if parent != new_path:
                self.add_or_update_file(os.pardir,
                                        parent,
                                        'normal',
                                        parent_link=True)

        def work(basepath):
            dir_content = listdir(basepath)
            # add all files from vcs and remove the corresponding items
            # from dir_content
            for item in self.svc.boss.cmd('versioncontrol',
                                          'list_file_states',
                                          path=self.path):
                if (item[1] == self.path):
                    try:
                        dir_content.remove(item[0])
                    except:
                        pass
                    yield item
            # handle remaining files
            for filename in dir_content:
                if (path.isdir(path.join(basepath, filename))):
                    state = 'normal'
                else:
                    state = 'unknown'
                yield filename, basepath, state

        # wrap add_or_update_file to set select accordingly
        def _add_or_update_file(name, basepath, state):
            self.add_or_update_file(name,
                                    basepath,
                                    state,
                                    select=(name == select))

        GeneratorTask(work, _add_or_update_file).start(self.path)

        self.create_ancest_tree()

    def update_single_file(self, name, basepath, select=False):
        if basepath != self.path:
            return
        if name not in self.entries:
            self.add_or_update_file(name, basepath, 'normal', select=select)

    def update_removed_file(self, filename):
        entry = self.entries.pop(filename, None)
        if entry is not None and entry.visible:
            self.file_list.remove(entry)

    def create_dir(self, name=None):
        if not name:
            #XXX: inputdialog or filechooser
            name = dialogs.input('Create New Directory',
                                 label=_("Directory name"))
        if name:
            npath = os.path.join(self.path, name)
            if not os.path.exists(npath):
                os.mkdir(npath)
            self.update_single_file(name, self.path, select=True)

    def on_file_activated(self, ol, fileentry):
        if os.path.exists(fileentry.path):
            if fileentry.is_dir:
                self.svc.browse(fileentry.path)
            else:
                self.svc.boss.cmd('buffer',
                                  'open_file',
                                  file_name=fileentry.path)
        else:
            self.update_removed_file(fileentry.name)

    def on_file_right_click(self, ol, item, event=None):
        if item.is_dir:
            self.svc.boss.cmd('contexts',
                              'popup_menu',
                              context='dir-menu',
                              dir_name=item.path,
                              event=event,
                              filemanager=True)
        else:
            self.svc.boss.cmd('contexts',
                              'popup_menu',
                              context='file-menu',
                              file_name=item.path,
                              event=event,
                              filemanager=True)

    def on_selection_changed(self, ol):
        for act_name in ['toolbar_copy', 'toolbar_delete']:
            self.svc.get_action(act_name).set_sensitive(
                ol.selected_item is not None)

    def rename_file(self, old, new, entry):
        print 'renaming', old, 'to', new

    def create_ancest_tree(self):
        task = AsyncTask(self._get_ancestors, self._show_ancestors)
        task.start(self.path)

    def _on_act_up_ancestor(self, action, directory):
        self.svc.browse(directory)

    def _show_ancestors(self, ancs):
        toolitem = self.svc.get_action('toolbar_up').get_proxies()[0]
        menu = gtk.Menu()
        for anc in ancs:
            action = gtk.Action(anc, anc, anc, 'directory')
            action.connect('activate', self._on_act_up_ancestor, anc)
            menuitem = action.create_menu_item()
            menu.add(menuitem)
        menu.show_all()
        toolitem.set_menu(menu)

    def _get_ancestors(self, directory):
        ancs = [directory]
        parent = None
        while True:
            parent = os.path.dirname(directory)
            if parent == directory:
                break
            ancs.append(parent)
            directory = parent
        return ancs

    def _on_act_file_hidden_check(self, action, check):
        if (check.scope == filehiddencheck.SCOPE_GLOBAL):
            # global
            active_checker = self.svc.opt('file_hidden_check')
            if (action.get_active()):
                active_checker.append(check.identifier)
            else:
                active_checker.remove(check.identifier)
            self.svc.set_opt('file_hidden_check', active_checker)
        else:
            # project
            if (self.svc.current_project is not None):
                section = self.svc.current_project.options.get(
                    'file_hidden_check', {})
                section[check.identifier] = action.get_active()
                self.svc.current_project.options['file_hidden_check'] = section
        self.update_to_path()

    def __file_hidden_check_scope_project_set_active(self, action):
        """sets active state of a file hidden check action with
           scope = project
           relies on action name = identifier of checker"""
        if (self.svc.current_project is not None):
            section = self.svc.current_project.options.get('file_hidden_check')
            action.set_active((section is not None)
                              and (action.get_name() in section)
                              and (section[action.get_name()] == 'True'))
        else:
            action.set_active(False)

    def refresh_file_hidden_check(self):
        """refreshes active status of actions of project scope checker"""
        for checker in self.svc.features['file_hidden_check']:
            if (checker.scope == filehiddencheck.SCOPE_PROJECT):
                action = self._file_hidden_check_actions[checker.identifier]
                self.__file_hidden_check_scope_project_set_active(action)

    def _create_file_hidden_check_toolbar(self):
        self._file_hidden_check_actions = {}
        menu = gtk.Menu()
        separator = gtk.SeparatorMenuItem()
        project_scope_count = 0
        menu.append(separator)
        for checker in self.svc.features['file_hidden_check']:
            action = gtk.ToggleAction(checker.identifier, checker.label,
                                      checker.label, None)
            # active?
            if (checker.scope == filehiddencheck.SCOPE_GLOBAL):
                action.set_active(
                    checker.identifier in self.svc.opt('file_hidden_check'))
            else:
                self.__file_hidden_check_scope_project_set_active(action)

            action.connect('activate', self._on_act_file_hidden_check, checker)
            self._file_hidden_check_actions[checker.identifier] = action
            menuitem = action.create_menu_item()
            if (checker.scope == filehiddencheck.SCOPE_GLOBAL):
                menu.prepend(menuitem)
            else:
                menu.append(menuitem)
                project_scope_count += 1
        menu.show_all()
        if (project_scope_count == 0):
            separator.hide()
        toolitem = None
        for proxy in self.svc.get_action('toolbar_hidden_menu').get_proxies():
            if (isinstance(proxy, DropDownMenuToolButton)):
                toolitem = proxy
                break
        if (toolitem is not None):
            toolitem.set_menu(menu)

    def get_selected_filename(self):
        fileentry = self.file_list.selected_item
        if fileentry is not None:
            return fileentry.path

    def copy_clipboard(self):
        current = self.get_selected_filename()
        if os.path.exists(current):
            self._clipboard_file = current
        else:
            self._clipboard_file = None
        self._fix_paste_sensitivity()

    def _fix_paste_sensitivity(self):
        self.svc.get_action('toolbar_paste').set_sensitive(
            self._clipboard_file is not None)

    def paste_clipboard(self):
        newname = os.path.join(self.path,
                               os.path.basename(self._clipboard_file))
        if newname == self._clipboard_file:
            self.svc.error_dlg(_('Cannot copy files to themselves.'))
            return
        if not os.path.exists(self._clipboard_file):
            self.svc.error_dlg(_('Source file has vanished.'))
            return
        if os.path.exists(newname):
            self.svc.error_dlg(_('Destination already exists.'))
            return

        task = AsyncTask(self._paste_clipboard, lambda: None)
        task.start()

    def _paste_clipboard(self):
        #XXX: in thread
        newname = os.path.join(self.path,
                               os.path.basename(self._clipboard_file))
        #XXX: GIO?
        if os.path.isdir(self._clipboard_file):
            shutil.copytree(self._clipboard_file, newname)
        else:
            shutil.copy2(self._clipboard_file, newname)

    def remove_path(self, path):
        task = AsyncTask(self._remove_path, lambda: None)
        task.start(path)

    def _remove_path(self, path):
        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)
        if path == self._clipboard_file:
            self._clipboard_file = None
            gcall(self._fix_paste_sensitivity)
示例#2
0
文件: pastebin.py 项目: xmonader/pida
class PasteHistoryView(PidaView):

    key = 'pastebin.history'

    label_text = _('Paste History')
    icon_name = gtk.STOCK_PASTE

    #glade_file_name = 'paste-history.glade'

    def create_ui(self):
        self.history_tree = ObjectList(
            [Column('markup', use_markup=True, expand=True)])
        self.history_tree.set_headers_visible(False)
        self.add_main_widget(self.history_tree)
        self.x11_clipboard = gtk.Clipboard(selection="PRIMARY")
        self.gnome_clipboard = gtk.Clipboard(selection="CLIPBOARD")
        self.history_tree.connect('item-right-clicked', self.on_paste_rclick)
        self.__pulse_bar = gtk.ProgressBar()
        self.add_main_widget(self.__pulse_bar, expand=False)
        # only show pulse bar if working
        self.__pulse_bar.hide()
        self.__pulse_bar.set_size_request(-1, 12)
        self.__pulse_bar.set_pulse_step(0.01)
        self.history_tree.show_all()

    @property
    def tree_selected(self):
        return self.history_tree.selected_item

    def set(self, pastes):
        '''Sets the paste list to the tree view.
           First reset it, then rebuild it.
        '''
        self.history_tree.clear()
        self.history_tree.expand(pastes)
        self.tree_selected = None

    def add_paste(self, item):
        self.history_tree.append(item)

    def copy_current_paste(self):
        '''Callback function bound to the toolbar button view that copies the
        selected paste'''
        if self.tree_selected != None:
            self.x11_clipboard.set_text(self.tree_selected.get_url())
            self.gnome_clipboard.set_text(self.tree_selected.get_url())

    def view_current_paste(self):
        '''Callback function bound to the toolbar button view that shows the
        selected paste'''
        if self.tree_selected != None:
            self.service.boss.call_command('pastemanager',
                                           'view_paste',
                                           paste=self.tree_selected)
        else:
            print _("ERROR: No paste selected")

    def remove_current_paste(self):
        '''Callback function bound to the toolbar button delete that removes the
        selected paste'''
        if self.tree_selected != None:
            self.service.boss.call_command('pastemanager',
                                           'delete_paste',
                                           paste=self.tree_selected)
        else:
            print _("ERROR: No paste selected")

    def cb_paste_db_clicked(self, ol, item):
        """
        Callback function called when an item is double clicked, and copy it
        to the gnome/gtk clipboard
        """
        if item is not None:
            self.svc.boss.cmd('browseweb', 'browse', url=item.url)
            # self.__gnome_clipboard.set_text(self.__tree_selected.get_url())
            # aa: view the paste

    def cb_paste_m_clicked(self, paste, tree_item):
        '''Callback function called when an item is middle clicked, and copy it
        to the mouse buffer clipboard'''
        if self.__tree_selected != None:
            self.__x11_clipboard.set_text(self.__tree_selected.get_url())

    def cb_paste_r_clicked(self, paste, tree_item, event):
        menu = gtk.Menu()
        sensitives = (tree_item is not None)
        for action in [
                'pastemanager+new_paste', None, 'pastemanager+remove_paste',
                'pastemanager+view_paste', None,
                'pastemanager+copy_url_to_clipboard'
        ]:
            if action is None:
                menu.append(gtk.SeparatorMenuItem())
            else:
                act = self.service.action_group.get_action(action)
                if 'new_paste' not in action:
                    act.set_sensitive(sensitives)
                mi = gtk.ImageMenuItem()
                act.connect_proxy(mi)
                mi.show()
                menu.append(mi)
        menu.show_all()
        menu.popup(None, None, None, event.button, event.time)

    def on_paste_rclick(self, ol, item, event):
        self.svc.boss.cmd('contexts',
                          'popup_menu',
                          context='url-menu',
                          url=item.url,
                          event=event)

    def start_pulse(self):
        '''Starts the pulse'''
        self._pulsing = True
        self.__pulse_bar.show()
        gobject.timeout_add(100, self._pulse)

    def stop_pulse(self):
        self.__pulse_bar.hide()
        self._pulsing = False

    def _pulse(self):
        self.__pulse_bar.pulse()
        return self._pulsing

    def can_be_closed(self):
        self.svc.get_action('show_pastes').set_active(False)
示例#3
0
class PreferencesDialog(BaseDialog):

    def __init__(self, parent):
        BaseDialog.__init__(self, 'preferences',
            parent, 'core.glade')
        ctx.logger.debug('initalizing preferences dialog')

        # init some data
        mapping = self.mail_cfg = {
            'smtp_host':            'text',
            'smtp_user':            '******',
            'smtp_password':        '******',
            'mail_encoding':        'text',
            'mail_default_from':    'text',
            'smtp_port':            'value',
            'smtp_use_tls':         'active',
            'smtp_raise_error':     'active',
            'debug':                'active',
            'log_timeformat':       'text',
        }
        cfg, w = ctx.settings, self.widgets
        # load values from the preferences module and visualize
        # them in the preferences dialog
        for widget, property in mapping.iteritems():
            w[widget].set_property(property, cfg[widget])
        ctx.logger.debug('loaded preferences from database')

        # the combo box to change the active project
        self._themes = ObjectList([
            Column('display_name', str, 'Name'),
            Column('author', str, 'Autor')
        ])
        self._themes.connect('item-activated', self.on_theme_choice_changed)
        self._themes.set_border_width(10)
        self.widgets.theme_vbox.pack_end(self._themes)
        # add all themes to the combo
        self._refresh_themes()

        # init the recipients ObjectList
        vbox = self.widgets.recipients_vbox
        self._recipients = ObjectList([
            Column('name', str, 'Name', editable=True),
            Column('mail', str, 'E-Mail', editable=True),
            Column('active', str, 'Mail senden', editable=True),
            Column('comment', str, 'Bemerkung', editable=True)
        ], sortable=True)
        self._recipients.connect('item-changed', self._on_recipient_edited)
        vbox.pack_start(self._recipients)
        self._update_recipients()
        self._recipients.show()
        ctx.logger.debug('inialized recipients preferences dialog-page')

    def on_add_recipient_button_clicked(self, sender, arg=None):
        ctx.logger.debug('add_recipient_button clicked')
        rdata = new_recipient_dialog(u'Neuer Empfänger',
            u'Trage hier die Daten für einen neuen Empfänger ein.')
        if rdata is not None:
            recipient = Recipient(*rdata)
            self._recipients.append(recipient)
            db.save(recipient)
            db.commit()

    def on_delete_recipient_button_clicked(self, sender, arg=None):
        ctx.logger.debug('delte_recipient_button clicked')
        obj = self._recipients.get_selected()
        if obj is not None:
            self._recipients.remove(obj)
            db.delete(obj)
            db.commit()

    def _update_recipients(self):
        rlist = set(self._recipients)
        rdb = set(db.query(Recipient).order_by(Recipient.name).all())
        rdiff = list(rdb - rlist)
        if rdiff:
            if len(rdiff) > 1:
                self._recipients.extend(rdiff)
            else:
                self._recipients.append(rdiff[0])

    def _on_recipient_edited(self, sender, object, attr, value):
        db.commit()
        ctx.logger.debug('recipient edited')

    @property
    def recipients(self):
        self._update_recipients()
        return self._recipients

    def _refresh_themes(self):
        self._themes.clear()
        a = None
        themes = list(find_themes())
        if not themes:
            self._themes.hide()
            self.widgets.no_themes_found.show()
        else:
            for theme in themes:
                self._themes.append(theme)
                if theme.name ==  ctx.theme_loader.current.name:
                    a = theme
            #if a: self._themes.select(a)
            self.widgets.no_themes_found.hide()
            self._themes.show()
        ctx.logger.debug('themes refreshed and repacked')

    def on_theme_choice_changed(self, sender, obj):
        # set the new theme in ctx.settings
        if obj is not None:
            ctx.settings['theme_choice'] = obj.name
            sender.emit_stop_by_name('item-changed')
        ctx.logger.debug('theme choice changed to %s'
            % ctx.settings['theme_choice'])

    def on_theme_path_selection_changed(self, sender):
        new_dir = self.widgets.theme_chooser.get_current_folder()
        ctx.settings['theme_path'] = new_dir
        sender.emit_stop_by_name('current-folder-changed')
        self._refresh_themes()
        ctx.logger.debug('theme path changed to %s' % new_dir)

    def get_response_data(self):
        cfg, w = ctx.settings, self.widgets
        return dict((x, w[x].get_property(y)) for x, y in \
                    self.mail_cfg.iteritems())
示例#4
0
class RfcView(PidaView):

    key = 'rfc.list'

    label_text = 'RFC'

    def create_ui(self):
        self._vbox = gtk.VBox(spacing=3)
        self._vbox.set_border_width(6)
        self.add_main_widget(self._vbox)
        self.create_toolbar()
        self.create_searchbar()
        self.create_list()
        self.create_progressbar()
        self._vbox.show_all()

    def create_searchbar(self):
        h = gtk.HBox()
        self._search_description = gtk.Entry()
        self._search_description.connect('changed', self._on_search_changed)
        l = gtk.Label()
        l.set_text(_('Filter : '))
        h.pack_start(l, expand=False)
        h.pack_start(self._search_description)
        self._vbox.pack_start(h, expand=False)
        self._search_description.show_all()

    def create_toolbar(self):
        self._uim = gtk.UIManager()
        self._uim.insert_action_group(self.svc.get_action_group(), 0)
        uidef_data = pkgutil.get_data(__name__, 'uidef/rfc-toolbar.xml')
        self._uim.add_ui_from_string(uidef_data)
        self._uim.ensure_update()
        self._toolbar = self._uim.get_toplevels('toolbar')[0]
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_SMALL_TOOLBAR)
        self._vbox.pack_start(self._toolbar, expand=False)
        self._toolbar.show_all()

    def create_list(self):
        self._list = ObjectList(
                [
                    Column('number', title=_('Number')),
                    Column('description', title=_('Description'))
                ]
        )
        self._scroll = gtk.ScrolledWindow()
        self._scroll.add(self._list)
        self._list.connect('item-activated', self._on_list_double_click)
        self._vbox.pack_start(self._scroll)
        self._list.show_all()

    def create_progressbar(self):
        self._progressbar = gtk.ProgressBar()
        self._progressbar.set_text(_('Download RFC Index'))
        self._vbox.pack_start(self._progressbar, expand=False)
        self._progressbar.set_no_show_all(True)
        self._progressbar.hide()

    def update_progressbar(self, current, max):
        if max > 1:
            self._progressbar.set_fraction(float(current) / float(max))

    def show_progressbar(self, show):
        self._progressbar.set_no_show_all(False)
        if show:
            self._progressbar.show()
        else:
            self._progressbar.hide()

    def set_items(self, items):
        self._list.extend(items)

    def clear(self):
        self._list.clear()

    def can_be_closed(self):
        self.svc.get_action('show_rfc').set_active(False)

    def _on_list_double_click(self, ot, item):
        self.svc.browse(id=item.number)

    def _on_search_changed(self, w):
        self.svc.filter(self._search_description.get_text())
示例#5
0
文件: gtags.py 项目: xmonader/pida
class GtagsView(PidaView):
    """
    Window wich shows the seach entry and update button for gtags
    """

    key = 'gtags.list'

    label_text = _('Gtags')

    def create_ui(self):
        self._hbox = gtk.HBox(spacing=3)
        self._hbox.set_border_width(2)
        self.add_main_widget(self._hbox)
        self._vbox = gtk.VBox(spacing=3)
        self._hbox.pack_start(self._vbox)
        self.create_searchbar()
        self.create_list()
        self.create_progressbar()
        self.create_toolbar()
        self._hbox.show_all()

    def create_searchbar(self):
        h = gtk.HBox(spacing=3)
        h.set_border_width(2)
        # label
        l = gtk.Label()
        l.set_text(_('Pattern : '))
        h.pack_start(l, expand=False)
        # pattern
        self._search = gtk.Entry()
        self._search.connect('changed', self._on_search_changed)
        self._search.set_sensitive(False)
        h.pack_start(self._search)
        # info
        self._info = gtk.Label()
        self._info.set_text('-')
        h.pack_start(self._info, expand=False)
        self._vbox.pack_start(h, expand=False)
        self._search.show_all()

    def create_toolbar(self):
        self._bar = gtk.VBox(spacing=1)
        self._refresh_button = create_mini_button(
            gtk.STOCK_REFRESH, _('Build TAGS database'),
            self._on_refresh_button_clicked)
        self._bar.pack_start(self._refresh_button, expand=False)
        self._hbox.pack_start(self._bar, expand=False)
        self._bar.show_all()

    def create_list(self):
        self._list = ObjectList([
            Column('symbol', title=_('Symbol'), use_markup=True),
            Column('filename', title=_('Location'), use_markup=True),
            Column('dataline', title=_('Data'), use_markup=True),
        ])
        self._scroll = gtk.ScrolledWindow()
        self._scroll.add(self._list)
        self._list.connect('item-double-clicked', self._on_list_double_click)
        self._vbox.pack_start(self._scroll)
        self._scroll.show_all()

    def create_progressbar(self):
        self._progressbar = gtk.ProgressBar()
        self._vbox.pack_start(self._progressbar, expand=False)
        self._progressbar.set_no_show_all(True)
        self._progressbar.hide()

    def update_progressbar(self, current, max):
        if max > 1:
            self._progressbar.set_fraction(float(current) / float(max))

    def show_progressbar(self, show):
        self._progressbar.set_no_show_all(False)
        if show:
            self._progressbar.show()
        else:
            self._progressbar.hide()

    def add_item(self, item):
        self._list.append(item)
        #XXX: ngettext
        self._info.set_text('%d matches' % len(self._list))

    def clear_items(self):
        self._list.clear()
        self._info.set_text('-')

    def activate(self, activate):
        self._search.set_sensitive(activate)
        self._list.set_sensitive(activate)

    def can_be_closed(self):
        self.svc.get_action('show_gtags').set_active(False)

    def _on_search_changed(self, w):
        self.svc.tag_search(self._search.get_text())

    def _on_refresh_button_clicked(self, w):
        self.svc.build_db()

    def _on_list_double_click(self, o, w):
        file_name = os.path.join(self.svc._project.source_directory, w.file)
        self.svc.boss.cmd('buffer',
                          'open_file',
                          file_name=file_name,
                          line=int(w.line))