Пример #1
0
 def search_text_changed(self, txt):
     searches = [_('Saved searches recognized in the expression:')]
     txt = unicode(txt)
     while txt:
         p = txt.partition('search:')
         if p[1]:  # found 'search:'
             possible_search = p[2]
             if possible_search:  # something follows the 'search:'
                 if possible_search[0] == '"':  # strip any quotes
                     possible_search = possible_search[1:].partition('"')
                 else:  # find end of the search name. Is EOL, space, rparen
                     sp = possible_search.find(' ')
                     pp = possible_search.find(')')
                     if pp < 0 or (sp > 0 and sp <= pp):
                         # space in string before rparen, or neither found
                         possible_search = possible_search.partition(' ')
                     else:
                         # rparen in string before space
                         possible_search = possible_search.partition(')')
                 txt = possible_search[2]  # grab remainder of the string
                 search_name = possible_search[0]
                 if search_name.startswith('='):
                     search_name = search_name[1:]
                 if search_name in saved_searches().names():
                     searches.append(search_name + '=' +
                                     saved_searches().lookup(search_name))
             else:
                 txt = ''
         else:
             txt = ''
     if len(searches) > 1:
         self.saved_searches_label.setText('\n'.join(searches))
     else:
         self.saved_searches_label.setText('')
Пример #2
0
 def link_activated(self, url):
     db = self.gui.current_db
     f, txt = unicode(url).partition('.')[0::2]
     if f == 'search':
         names = saved_searches().names()
     else:
         names = getattr(db, 'all_%s_names' % f)()
     d = SelectNames(names, txt, parent=self)
     if d.exec_() == d.Accepted:
         prefix = f + 's' if f in {'tag', 'author'} else f
         if f == 'search':
             search = [
                 '(%s)' % (saved_searches().lookup(x)) for x in d.names
             ]
         else:
             search = [
                 '%s:"=%s"' % (prefix, x.replace('"', '\\"'))
                 for x in d.names
             ]
         if search:
             if not self.editing:
                 self.vl_name.lineEdit().setText(d.names.next())
                 self.vl_name.lineEdit().setCursorPosition(0)
             self.vl_text.setText(d.match_type.join(search))
             self.vl_text.setCursorPosition(0)
Пример #3
0
 def search_text_changed(self, txt):
     searches = [_('Saved searches recognized in the expression:')]
     txt = unicode(txt)
     while txt:
         p = txt.partition('search:')
         if p[1]:  # found 'search:'
             possible_search = p[2]
             if possible_search:  # something follows the 'search:'
                 if possible_search[0] == '"':  # strip any quotes
                     possible_search = possible_search[1:].partition('"')
                 else:  # find end of the search name. Is EOL, space, rparen
                     sp = possible_search.find(' ')
                     pp = possible_search.find(')')
                     if pp < 0 or (sp > 0 and sp <= pp):
                         # space in string before rparen, or neither found
                         possible_search = possible_search.partition(' ')
                     else:
                         # rparen in string before space
                         possible_search = possible_search.partition(')')
                 txt = possible_search[2]  # grab remainder of the string
                 search_name = possible_search[0]
                 if search_name.startswith('='):
                     search_name = search_name[1:]
                 if search_name in saved_searches().names():
                     searches.append(search_name + '=' +
                                     saved_searches().lookup(search_name))
             else:
                 txt = ''
         else:
             txt = ''
     if len(searches) > 1:
         self.saved_searches_label.setText('\n'.join(searches))
     else:
         self.saved_searches_label.setText('')
Пример #4
0
 def accept(self):
     if self.current_search_name:
         self.searches[self.current_search_name] = unicode(self.search_text.toPlainText())
     for name in saved_searches().names():
         saved_searches().delete(name)
     for name in self.searches:
         saved_searches().add(name, self.searches[name])
     QDialog.accept(self)
 def accept(self):
     if self.current_search_name:
         self.searches[self.current_search_name] = unicode(
             self.search_text.toPlainText())
     for name in saved_searches().names():
         saved_searches().delete(name)
     for name in self.searches:
         saved_searches().add(name, self.searches[name])
     QDialog.accept(self)
Пример #6
0
 def saved_search_selected(self, qname):
     qname = unicode(qname)
     if qname is None or not qname.strip():
         self.search_box.clear()
         return
     if not saved_searches().lookup(qname):
         self.search_box.clear()
         self.setEditText(qname)
         return
     self.search_box.set_search_string(u'search:"%s"' % qname, emit_changed=False)
     self.setEditText(qname)
     self.setToolTip(saved_searches().lookup(qname))
Пример #7
0
 def save_search_button_clicked(self):
     name = unicode(self.currentText())
     if not name.strip():
         name = unicode(self.search_box.text()).replace('"', '')
     saved_searches().delete(name)
     saved_searches().add(name, unicode(self.search_box.text()))
     # now go through an initialization cycle to ensure that the combobox has
     # the new search in it, that it is selected, and that the search box
     # references the new search instead of the text in the search.
     self.clear()
     self.setCurrentIndex(self.findText(name))
     self.saved_search_selected (name)
     self.changed.emit()
Пример #8
0
 def saved_search_selected(self, qname):
     qname = unicode(qname)
     if qname is None or not qname.strip():
         self.search_box.clear()
         return
     if not saved_searches().lookup(qname):
         self.search_box.clear()
         self.setEditText(qname)
         return
     self.search_box.set_search_string(u'search:"%s"' % qname,
                                       emit_changed=False)
     self.setEditText(qname)
     self.setToolTip(saved_searches().lookup(qname))
Пример #9
0
    def build_search_restriction_list(self):
        m = self.ar_menu
        m.clear()

        current_restriction_text = None

        if self.search_restriction.count() > 1:
            txt = unicode(self.search_restriction.itemText(2))
            if txt.startswith('*'):
                current_restriction_text = txt
        self.search_restriction.clear()

        current_restriction = self.library_view.model().db.data.get_search_restriction_name()
        m.setIcon(self.checked if current_restriction else self.empty)

        def add_action(txt, index):
            self.search_restriction.addItem(txt)
            txt = self._trim_restriction_name(txt)
            if txt == current_restriction:
                a = m.addAction(self.checked, txt if txt else self.no_restriction)
            else:
                a = m.addAction(self.empty, txt if txt else self.no_restriction)
            a.triggered.connect(partial(self.search_restriction_triggered,
                                        action=a, index=index))

        add_action('', 0)
        add_action(_('*current search'), 1)
        dex = 2
        if current_restriction_text:
            add_action(current_restriction_text, 2)
            dex += 1

        for n in sorted(saved_searches().names(), key=sort_key):
            add_action(n, dex)
            dex += 1
Пример #10
0
    def build_search_restriction_list(self):
        m = self.ar_menu
        m.clear()

        current_restriction_text = None

        if self.search_restriction.count() > 1:
            txt = unicode(self.search_restriction.itemText(2))
            if txt.startswith('*'):
                current_restriction_text = txt
        self.search_restriction.clear()

        current_restriction = self.library_view.model().db.data.get_search_restriction_name()
        m.setIcon(self.checked if current_restriction else self.empty)

        def add_action(txt, index):
            self.search_restriction.addItem(txt)
            txt = self._trim_restriction_name(txt)
            if txt == current_restriction:
                a = m.addAction(self.checked, txt if txt else self.no_restriction)
            else:
                a = m.addAction(self.empty, txt if txt else self.no_restriction)
            a.triggered.connect(partial(self.search_restriction_triggered,
                                        action=a, index=index))

        add_action('', 0)
        add_action(_('*current search'), 1)
        dex = 2
        if current_restriction_text:
            add_action(current_restriction_text, 2)
            dex += 1

        for n in sorted(saved_searches().names(), key=sort_key):
            add_action(n, dex)
            dex += 1
Пример #11
0
 def delete_current_search(self):
     idx = self.currentIndex()
     if idx <= 0:
         error_dialog(self, _('Delete current search'),
                      _('No search is selected'), show=True)
         return
     if not confirm('<p>'+_('The selected search will be '
                    '<b>permanently deleted</b>. Are you sure?')
                 +'</p>', 'saved_search_delete', self):
         return
     ss = saved_searches().lookup(unicode(self.currentText()))
     if ss is None:
         return
     saved_searches().delete(unicode(self.currentText()))
     self.clear()
     self.search_box.clear()
     self.changed.emit()
Пример #12
0
 def link_activated(self, url):
     db = self.gui.current_db
     f, txt = unicode(url).partition('.')[0::2]
     if f == 'search':
         names = saved_searches().names()
     else:
         names = getattr(db, 'all_%s_names'%f)()
     d = SelectNames(names, txt, parent=self)
     if d.exec_() == d.Accepted:
         prefix = f+'s' if f in {'tag', 'author'} else f
         if f == 'search':
             search = ['(%s)'%(saved_searches().lookup(x)) for x in d.names]
         else:
             search = ['%s:"=%s"'%(prefix, x.replace('"', '\\"')) for x in d.names]
         if search:
             if not self.editing:
                 self.vl_name.lineEdit().setText(d.names.next())
                 self.vl_name.lineEdit().setCursorPosition(0)
             self.vl_text.setText(d.match_type.join(search))
             self.vl_text.setCursorPosition(0)
Пример #13
0
 def delete_current_search(self):
     idx = self.currentIndex()
     if idx <= 0:
         error_dialog(self,
                      _('Delete current search'),
                      _('No search is selected'),
                      show=True)
         return
     if not confirm(
             '<p>' + _('The selected search will be '
                       '<b>permanently deleted</b>. Are you sure?') +
             '</p>', 'saved_search_delete', self):
         return
     ss = saved_searches().lookup(unicode(self.currentText()))
     if ss is None:
         return
     saved_searches().delete(unicode(self.currentText()))
     self.clear()
     self.search_box.clear()
     self.changed.emit()
Пример #14
0
    def __init__(self, parent, initial_search=None):
        QDialog.__init__(self, parent)
        Ui_SavedSearchEditor.__init__(self)
        self.setupUi(self)

        self.connect(self.add_search_button, SIGNAL('clicked()'), self.add_search)
        self.connect(self.search_name_box, SIGNAL('currentIndexChanged(int)'),
                                    self.current_index_changed)
        self.connect(self.delete_search_button, SIGNAL('clicked()'), self.del_search)
        self.rename_button.clicked.connect(self.rename_search)

        self.current_search_name = None
        self.searches = {}
        for name in saved_searches().names():
            self.searches[name] = saved_searches().lookup(name)
        self.search_names = set([icu_lower(n) for n in saved_searches().names()])

        self.populate_search_list()
        if initial_search is not None and initial_search in self.searches:
            self.select_search(initial_search)
Пример #15
0
 def set_search_restriction(self, restriction):
     self.search_restriction_name = restriction
     if restriction:
         if restriction not in saved_searches().names():
             prints('WARNING: Content server: search restriction ',
                    restriction, ' does not exist')
             self.search_restriction = ''
         else:
             self.search_restriction = 'search:"%s"'%restriction
     else:
         self.search_restriction = ''
     self.reset_caches()
Пример #16
0
 def set_search_restriction(self, restriction):
     self.search_restriction_name = restriction
     if restriction:
         if restriction not in saved_searches().names():
             prints('WARNING: Content server: search restriction ',
                    restriction, ' does not exist')
             self.search_restriction = ''
         else:
             self.search_restriction = 'search:"%s"' % restriction
     else:
         self.search_restriction = ''
     self.reset_caches()
Пример #17
0
 def saved_searches_changed(self, set_restriction=None, recount=True):
     p = sorted(saved_searches().names(), key=sort_key)
     if set_restriction is None:
         set_restriction = unicode(self.search_restriction.currentText())
     # rebuild the restrictions combobox using current saved searches
     self.search_restriction.clear()
     self.search_restriction.addItem('')
     self.search_restriction.addItem(_('*Current search'))
     if recount:
         self.tags_view.recount()
     for s in p:
         self.search_restriction.addItem(s)
     if set_restriction:  # redo the search restriction if there was one
         self.apply_named_search_restriction(set_restriction)
    def __init__(self, parent, initial_search=None):
        QDialog.__init__(self, parent)
        Ui_SavedSearchEditor.__init__(self)
        self.setupUi(self)

        self.connect(self.add_search_button, SIGNAL('clicked()'),
                     self.add_search)
        self.connect(self.search_name_box, SIGNAL('currentIndexChanged(int)'),
                     self.current_index_changed)
        self.connect(self.delete_search_button, SIGNAL('clicked()'),
                     self.del_search)
        self.rename_button.clicked.connect(self.rename_search)

        self.current_search_name = None
        self.searches = {}
        for name in saved_searches().names():
            self.searches[name] = saved_searches().lookup(name)
        self.search_names = set(
            [icu_lower(n) for n in saved_searches().names()])

        self.populate_search_list()
        if initial_search is not None and initial_search in self.searches:
            self.select_search(initial_search)
Пример #19
0
 def saved_searches_changed(self, set_restriction=None, recount=True):
     p = sorted(saved_searches().names(), key=sort_key)
     if set_restriction is None:
         set_restriction = unicode(self.search_restriction.currentText())
     # rebuild the restrictions combobox using current saved searches
     self.search_restriction.clear()
     self.search_restriction.addItem('')
     self.search_restriction.addItem(_('*Current search'))
     if recount:
         self.tags_view.recount()
     for s in p:
         self.search_restriction.addItem(s)
     if set_restriction: # redo the search restriction if there was one
         self.apply_named_search_restriction(set_restriction)
Пример #20
0
def command_saved_searches(args, dbpath):
    parser = saved_searches_option_parser()
    opts, args = parser.parse_args(args)
    if len(args) < 1:
        parser.print_help()
        print
        prints(_('Error: You must specify an action (add|remove|list)'), file=sys.stderr)
        return 1
    from calibre.utils.search_query_parser import saved_searches
    db = get_db(dbpath, opts)
    db
    ss = saved_searches()
    if args[0] == 'list':
        for name in ss.names():
            prints(_('Name:'), name)
            prints(_('Search string:'), ss.lookup(name))
            print
    elif args[0] == 'add':
        if len(args) < 3:
            parser.print_help()
            print
            prints(_('Error: You must specify a name and a search string'), file=sys.stderr)
            return 1
        ss.add(args[1], args[2])
        prints(args[1], _('added'))
    elif args[0] == 'remove':
        if len(args) < 2:
            parser.print_help()
            print
            prints(_('Error: You must specify a name'), file=sys.stderr)
            return 1
        ss.delete(args[1])
        prints(args[1], _('removed'))
    else:
        parser.print_help()
        print
        prints(_('Error: Action %s not recognized, must be one '
            'of: (add|remove|list)') % args[1], file=sys.stderr)
        return 1

    return 0
Пример #21
0
def command_saved_searches(args, dbpath):
    parser = saved_searches_option_parser()
    opts, args = parser.parse_args(args)
    if len(args) < 1:
        parser.print_help()
        print
        prints(_('Error: You must specify an action (add|remove|list)'), file=sys.stderr)
        return 1
    from calibre.utils.search_query_parser import saved_searches
    db = get_db(dbpath, opts)
    db
    ss = saved_searches()
    if args[0] == 'list':
        for name in ss.names():
            prints(_('Name:'), name)
            prints(_('Search string:'), ss.lookup(name))
            print
    elif args[0] == 'add':
        if len(args) < 3:
            parser.print_help()
            print
            prints(_('Error: You must specify a name and a search string'), file=sys.stderr)
            return 1
        ss.add(args[1], args[2])
        prints(args[1], _('added'))
    elif args[0] == 'remove':
        if len(args) < 2:
            parser.print_help()
            print
            prints(_('Error: You must specify a name'), file=sys.stderr)
            return 1
        ss.delete(args[1])
        prints(args[1], _('removed'))
    else:
        parser.print_help()
        print
        prints(_('Error: Action %s not recognized, must be one '
            'of: (add|remove|list)') % args[1], file=sys.stderr)
        return 1

    return 0
Пример #22
0
    def genesis(self, gui):
        self.gui = gui
        self.proxy = ConfigProxy(server_config())
        db = self.db = gui.library_view.model().db
        self.server = self.gui.content_server

        r = self.register

        r('port', self.proxy)
        r('username', self.proxy)
        r('password', self.proxy)
        r('max_cover', self.proxy)
        r('max_opds_items', self.proxy)
        r('max_opds_ungrouped_items', self.proxy)
        r('url_prefix', self.proxy)

        self.show_server_password.stateChanged[int].connect(
            lambda s: self.opt_password.setEchoMode(
                self.opt_password.Normal
                if s == Qt.Checked else self.opt_password.Password))
        self.opt_password.setEchoMode(self.opt_password.Password)

        restrictions = sorted(saved_searches().names(), key=sort_key)
        # verify that the current restriction still exists. If not, clear it.
        csr = db.prefs.get('cs_restriction', None)
        if csr and csr not in restrictions:
            db.prefs.set('cs_restriction', '')
        choices = [('', '')] + [(x, x) for x in restrictions]
        r('cs_restriction', db.prefs, choices=choices)

        self.start_button.setEnabled(
            not getattr(self.server, 'is_running', False))
        self.test_button.setEnabled(not self.start_button.isEnabled())
        self.stop_button.setDisabled(self.start_button.isEnabled())
        self.start_button.clicked.connect(self.start_server)
        self.stop_button.clicked.connect(self.stop_server)
        self.test_button.clicked.connect(self.test_server)
        self.view_logs.clicked.connect(self.view_server_logs)

        r('autolaunch_server', config)
Пример #23
0
    def genesis(self, gui):
        self.gui = gui
        self.proxy = ConfigProxy(server_config())
        db = self.db = gui.library_view.model().db
        self.server = self.gui.content_server

        r = self.register

        r('port', self.proxy)
        r('username', self.proxy)
        r('password', self.proxy)
        r('max_cover', self.proxy)
        r('max_opds_items', self.proxy)
        r('max_opds_ungrouped_items', self.proxy)
        r('url_prefix', self.proxy)

        self.show_server_password.stateChanged[int].connect(
                     lambda s: self.opt_password.setEchoMode(
                         self.opt_password.Normal if s == Qt.Checked
                         else self.opt_password.Password))
        self.opt_password.setEchoMode(self.opt_password.Password)

        restrictions = sorted(saved_searches().names(), key=sort_key)
        # verify that the current restriction still exists. If not, clear it.
        csr = db.prefs.get('cs_restriction', None)
        if csr and csr not in restrictions:
            db.prefs.set('cs_restriction', '')
        choices = [('', '')] + [(x, x) for x in restrictions]
        r('cs_restriction', db.prefs, choices=choices)

        self.start_button.setEnabled(not getattr(self.server, 'is_running', False))
        self.test_button.setEnabled(not self.start_button.isEnabled())
        self.stop_button.setDisabled(self.start_button.isEnabled())
        self.start_button.clicked.connect(self.start_server)
        self.stop_button.clicked.connect(self.stop_server)
        self.test_button.clicked.connect(self.test_server)
        self.view_logs.clicked.connect(self.view_server_logs)

        r('autolaunch_server', config)
Пример #24
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register
        choices = [(_('Low'), 'low'), (_('Normal'), 'normal'), (_('High'),
            'high')] if iswindows else \
                    [(_('Normal'), 'normal'), (_('Low'), 'low'), (_('Very low'),
                        'high')]
        r('worker_process_priority', prefs, choices=choices)

        r('network_timeout', prefs)

        r('new_version_notification', config)
        r('upload_news_to_device', config)
        r('delete_news_from_library_on_upload', config)

        output_formats = list(sorted(available_output_formats()))
        output_formats.remove('oeb')
        choices = [(x.upper(), x) for x in output_formats]
        r('output_format', prefs, choices=choices, setting=OutputFormatSetting)

        restrictions = sorted(saved_searches().names(), key=sort_key)
        choices = [('', '')] + [(x, x) for x in restrictions]
        r('gui_restriction', db.prefs, choices=choices)
        self.reset_confirmation_button.clicked.connect(self.reset_confirmation_dialogs)

        self.input_up_button.clicked.connect(self.up_input)
        self.input_down_button.clicked.connect(self.down_input)
        for signal in ('Activated', 'Changed', 'DoubleClicked', 'Clicked'):
            signal = getattr(self.opt_internally_viewed_formats, 'item'+signal)
            signal.connect(self.internally_viewed_formats_changed)

        r('bools_are_tristate', db.prefs, restart_required=True)
        r = self.register
        choices = [(_('Default'), 'default'), (_('Compact Metadata'), 'alt1'),
                   (_('All on 1 tab'), 'alt2')]
        r('edit_metadata_single_layout', gprefs, choices=choices)
Пример #25
0
 def set_database(self, db):
     self.db = db
     virt_libs = db.prefs.get('virtual_libraries', {})
     sr = getattr(self.opts, 'restriction', None)
     if sr:
         if sr in virt_libs:
             sr = virt_libs[sr]
         elif sr not in saved_searches().names():
             prints('WARNING: Content server: search restriction ',
                    sr, ' does not exist')
             sr = ''
         else:
             sr = 'search:"%s"'%sr
     else:
         sr = db.prefs.get('cs_virtual_lib_on_startup', '')
         if sr:
             if sr not in virt_libs:
                 prints('WARNING: Content server: virtual library ',
                        sr, ' does not exist')
                 sr = ''
             else:
                 sr = virt_libs[sr]
     self.search_restriction = sr
     self.reset_caches()
Пример #26
0
 def set_database(self, db):
     self.db = db
     virt_libs = db.prefs.get('virtual_libraries', {})
     sr = getattr(self.opts, 'restriction', None)
     if sr:
         if sr in virt_libs:
             sr = virt_libs[sr]
         elif sr not in saved_searches().names():
             prints('WARNING: Content server: search restriction ', sr,
                    ' does not exist')
             sr = ''
         else:
             sr = 'search:"%s"' % sr
     else:
         sr = db.prefs.get('cs_virtual_lib_on_startup', '')
         if sr:
             if sr not in virt_libs:
                 prints('WARNING: Content server: virtual library ', sr,
                        ' does not exist')
                 sr = ''
             else:
                 sr = virt_libs[sr]
     self.search_restriction = sr
     self.reset_caches()
Пример #27
0
    def context_menu_handler(self,
                             action=None,
                             category=None,
                             key=None,
                             index=None,
                             search_state=None):
        if not action:
            return
        try:
            if action == 'set_icon':
                try:
                    path = choose_files(self,
                                        'choose_category_icon',
                                        _('Change Icon for: %s') % key,
                                        filters=[
                                            ('Images',
                                             ['png', 'gif', 'jpg', 'jpeg'])
                                        ],
                                        all_files=False,
                                        select_only_single_file=True)
                    if path:
                        path = path[0]
                        p = QIcon(path).pixmap(QSize(128, 128))
                        d = os.path.join(config_dir, 'tb_icons')
                        if not os.path.exists(d):
                            os.makedirs(d)
                        with open(
                                os.path.join(
                                    d, 'icon_' +
                                    sanitize_file_name_unicode(key) + '.png'),
                                'wb') as f:
                            f.write(pixmap_to_data(p, format='PNG'))
                            path = os.path.basename(f.name)
                        self._model.set_custom_category_icon(
                            key, unicode(path))
                        self.recount()
                except:
                    import traceback
                    traceback.print_exc()
                return
            if action == 'clear_icon':
                self._model.set_custom_category_icon(key, None)
                self.recount()
                return

            if action == 'edit_item':
                self.edit(index)
                return
            if action == 'delete_item':
                self.tag_item_delete.emit(key, index.id, index.original_name)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key)
                return
            if action == 'manage_categories':
                self.edit_user_category.emit(category)
                return
            if action == 'search':
                self._toggle(index, set_to=search_state)
                return
            if action == 'add_to_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.all_children():
                        self.add_item_to_user_cat.emit(category,
                                                       c.tag.original_name,
                                                       c.tag.category)
                self.add_item_to_user_cat.emit(category, tag.original_name,
                                               tag.category)
                return
            if action == 'add_subcategory':
                self.add_subcategory.emit(key)
                return
            if action == 'search_category':
                self._toggle(index, set_to=search_state)
                return
            if action == 'delete_user_category':
                self.delete_user_category.emit(key)
                return
            if action == 'delete_search':
                saved_searches().delete(key)
                self.rebuild_saved_searches.emit()
                return
            if action == 'delete_item_from_user_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.children:
                        self.del_item_from_user_cat.emit(
                            key, c.tag.original_name, c.tag.category)
                self.del_item_from_user_cat.emit(key, tag.original_name,
                                                 tag.category)
                return
            if action == 'manage_searches':
                self.saved_search_edit.emit(category)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True)
                return

            reset_filter_categories = True
            if action == 'hide':
                self.hidden_categories.add(category)
            elif action == 'show':
                self.hidden_categories.discard(category)
            elif action == 'categorization':
                changed = self.collapse_model != category
                self._model.collapse_model = category
                if changed:
                    reset_filter_categories = False
                    gprefs['tags_browser_partition_method'] = category
            elif action == 'defaults':
                self.hidden_categories.clear()
            self.db.prefs.set('tag_browser_hidden_categories',
                              list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except:
            return
Пример #28
0
def get_categories(dbcache, sort='name', book_ids=None, icon_map=None):
    if icon_map is not None and type(icon_map) != TagsIcons:
        raise TypeError(
            'icon_map passed to get_categories must be of type TagIcons')
    if sort not in CATEGORY_SORTS:
        raise ValueError('sort ' + sort + ' not a valid value')

    fm = dbcache.field_metadata
    book_rating_map = dbcache.fields['rating'].book_value_map
    lang_map = dbcache.fields['languages'].book_value_map

    categories = {}
    book_ids = frozenset(book_ids) if book_ids else book_ids
    get_metadata = partial(dbcache._get_metadata, get_user_categories=False)
    bids = None

    for category, is_multiple, is_composite in find_categories(fm):
        tag_class = create_tag_class(category, fm, icon_map)
        if is_composite:
            if bids is None:
                bids = dbcache._all_book_ids(
                ) if book_ids is None else book_ids
            cats = dbcache.fields[category].get_composite_categories(
                tag_class, book_rating_map, bids, is_multiple, get_metadata)
        elif category == 'news':
            cats = dbcache.fields['tags'].get_news_category(
                tag_class, book_ids)
        else:
            cat = fm[category]
            brm = book_rating_map
            if cat['datatype'] == 'rating' and category != 'rating':
                brm = dbcache.fields[category].book_value_map
            cats = dbcache.fields[category].get_categories(
                tag_class, brm, lang_map, book_ids)
            if (category != 'authors' and cat['datatype'] == 'text'
                    and cat['is_multiple']
                    and cat['display'].get('is_names', False)):
                for item in cats:
                    item.sort = author_to_author_sort(item.sort)
        sort_categories(cats, sort)
        categories[category] = cats

    # Needed for legacy databases that have multiple ratings that
    # map to n stars
    for r in categories['rating']:
        for x in tuple(categories['rating']):
            if r.name == x.name and r.id != x.id:
                r.id_set |= x.id_set
                r.count = r.count + x.count
                categories['rating'].remove(x)
                break

    # User categories
    user_categories = clean_user_categories(dbcache).copy()
    if user_categories:
        # We want to use same node in the user category as in the source
        # category. To do that, we need to find the original Tag node. There is
        # a time/space tradeoff here. By converting the tags into a map, we can
        # do the verification in the category loop much faster, at the cost of
        # temporarily duplicating the categories lists.
        taglist = {}
        for c, items in categories.iteritems():
            taglist[c] = dict(map(lambda t: (icu_lower(t.name), t), items))

        muc = dbcache.pref('grouped_search_make_user_categories', [])
        gst = dbcache.pref('grouped_search_terms', {})
        for c in gst:
            if c not in muc:
                continue
            user_categories[c] = []
            for sc in gst[c]:
                if sc in categories.keys():
                    for t in categories[sc]:
                        user_categories[c].append([t.name, sc, 0])

        gst_icon = icon_map['gst'] if icon_map else None
        for user_cat in sorted(user_categories.iterkeys(), key=sort_key):
            items = []
            names_seen = {}
            for name, label, ign in user_categories[user_cat]:
                n = icu_lower(name)
                if label in taglist and n in taglist[label]:
                    if user_cat in gst:
                        # for gst items, make copy and consolidate the tags by name.
                        if n in names_seen:
                            t = names_seen[n]
                            t.id_set |= taglist[label][n].id_set
                            t.count += taglist[label][n].count
                            t.tooltip = t.tooltip.replace(
                                ')', ', ' + label + ')')
                        else:
                            t = copy.copy(taglist[label][n])
                            t.icon = gst_icon
                            names_seen[t.name] = t
                            items.append(t)
                    else:
                        items.append(taglist[label][n])
                # else: do nothing, to not include nodes w zero counts
            cat_name = '@' + user_cat  # add the '@' to avoid name collision
            # Not a problem if we accumulate entries in the icon map
            if icon_map is not None:
                icon_map[cat_name] = icon_map['user:'******'search' in icon_map:
        icon = icon_map['search']
    ss = saved_searches()
    for srch in ss.names():
        items.append(
            Tag(srch,
                tooltip=ss.lookup(srch),
                sort=srch,
                icon=icon,
                category='search',
                is_editable=False))
    if len(items):
        categories['search'] = items

    return categories
Пример #29
0
def get_categories(dbcache, sort="name", book_ids=None, icon_map=None):
    if icon_map is not None and type(icon_map) != TagsIcons:
        raise TypeError("icon_map passed to get_categories must be of type TagIcons")
    if sort not in CATEGORY_SORTS:
        raise ValueError("sort " + sort + " not a valid value")

    fm = dbcache.field_metadata
    book_rating_map = dbcache.fields["rating"].book_value_map
    lang_map = dbcache.fields["languages"].book_value_map

    categories = {}
    book_ids = frozenset(book_ids) if book_ids else book_ids
    get_metadata = partial(dbcache._get_metadata, get_user_categories=False)
    bids = None

    for category, is_multiple, is_composite in find_categories(fm):
        tag_class = create_tag_class(category, fm, icon_map)
        if is_composite:
            if bids is None:
                bids = dbcache._all_book_ids() if book_ids is None else book_ids
            cats = dbcache.fields[category].get_composite_categories(
                tag_class, book_rating_map, bids, is_multiple, get_metadata
            )
        elif category == "news":
            cats = dbcache.fields["tags"].get_news_category(tag_class, book_ids)
        else:
            cats = dbcache.fields[category].get_categories(tag_class, book_rating_map, lang_map, book_ids)
        sort_categories(cats, sort)
        categories[category] = cats

    # Needed for legacy databases that have multiple ratings that
    # map to n stars
    for r in categories["rating"]:
        for x in tuple(categories["rating"]):
            if r.name == x.name and r.id != x.id:
                r.id_set |= x.id_set
                r.count = r.count + x.count
                categories["rating"].remove(x)
                break

    # User categories
    user_categories = clean_user_categories(dbcache).copy()
    if user_categories:
        # We want to use same node in the user category as in the source
        # category. To do that, we need to find the original Tag node. There is
        # a time/space tradeoff here. By converting the tags into a map, we can
        # do the verification in the category loop much faster, at the cost of
        # temporarily duplicating the categories lists.
        taglist = {}
        for c, items in categories.iteritems():
            taglist[c] = dict(map(lambda t: (icu_lower(t.name), t), items))

        muc = dbcache.pref("grouped_search_make_user_categories", [])
        gst = dbcache.pref("grouped_search_terms", {})
        for c in gst:
            if c not in muc:
                continue
            user_categories[c] = []
            for sc in gst[c]:
                if sc in categories.keys():
                    for t in categories[sc]:
                        user_categories[c].append([t.name, sc, 0])

        gst_icon = icon_map["gst"] if icon_map else None
        for user_cat in sorted(user_categories.iterkeys(), key=sort_key):
            items = []
            names_seen = {}
            for name, label, ign in user_categories[user_cat]:
                n = icu_lower(name)
                if label in taglist and n in taglist[label]:
                    if user_cat in gst:
                        # for gst items, make copy and consolidate the tags by name.
                        if n in names_seen:
                            t = names_seen[n]
                            t.id_set |= taglist[label][n].id_set
                            t.count += taglist[label][n].count
                            t.tooltip = t.tooltip.replace(")", ", " + label + ")")
                        else:
                            t = copy.copy(taglist[label][n])
                            t.icon = gst_icon
                            names_seen[t.name] = t
                            items.append(t)
                    else:
                        items.append(taglist[label][n])
                # else: do nothing, to not include nodes w zero counts
            cat_name = "@" + user_cat  # add the '@' to avoid name collision
            # Not a problem if we accumulate entries in the icon map
            if icon_map is not None:
                icon_map[cat_name] = icon_map["user:"******"search" in icon_map:
        icon = icon_map["search"]
    ss = saved_searches()
    for srch in ss.names():
        items.append(Tag(srch, tooltip=ss.lookup(srch), sort=srch, icon=icon, category="search", is_editable=False))
    if len(items):
        categories["search"] = items

    return categories
Пример #30
0
 def copy_search_button_clicked (self):
     idx = self.currentIndex();
     if idx < 0:
         return
     self.search_box.set_search_string(saved_searches().lookup(unicode(self.currentText())))
Пример #31
0
 def initialize_saved_search_names(self):
     qnames = saved_searches().names()
     self.addItems(qnames)
     self.setCurrentIndex(-1)
Пример #32
0
    def context_menu_handler(self, action=None, category=None,
                             key=None, index=None, search_state=None):
        if not action:
            return
        try:
            if action == 'edit_item':
                self.edit(index)
                return
            if action == 'delete_item':
                self.tag_item_delete.emit(key, index.id, index.original_name)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key)
                return
            if action == 'manage_categories':
                self.edit_user_category.emit(category)
                return
            if action == 'search':
                self._toggle(index, set_to=search_state)
                return
            if action == 'add_to_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.all_children():
                        self.add_item_to_user_cat.emit(category, c.tag.original_name,
                                               c.tag.category)
                self.add_item_to_user_cat.emit(category, tag.original_name,
                                               tag.category)
                return
            if action == 'add_subcategory':
                self.add_subcategory.emit(key)
                return
            if action == 'search_category':
                self._toggle(index, set_to=search_state)
                return
            if action == 'delete_user_category':
                self.delete_user_category.emit(key)
                return
            if action == 'delete_search':
                saved_searches().delete(key)
                self.rebuild_saved_searches.emit()
                return
            if action == 'delete_item_from_user_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.children:
                        self.del_item_from_user_cat.emit(key, c.tag.original_name,
                                               c.tag.category)
                self.del_item_from_user_cat.emit(key, tag.original_name, tag.category)
                return
            if action == 'manage_searches':
                self.saved_search_edit.emit(category)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True)
                return

            reset_filter_categories = True
            if action == 'hide':
                self.hidden_categories.add(category)
            elif action == 'show':
                self.hidden_categories.discard(category)
            elif action == 'categorization':
                changed = self.collapse_model != category
                self._model.collapse_model = category
                if changed:
                    reset_filter_categories = False
                    gprefs['tags_browser_partition_method'] = category
            elif action == 'defaults':
                self.hidden_categories.clear()
            self.db.prefs.set('tag_browser_hidden_categories', list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except:
            return
Пример #33
0
    def context_menu_handler(self,
                             action=None,
                             category=None,
                             key=None,
                             index=None,
                             search_state=None):
        if not action:
            return
        try:
            if action == 'edit_item':
                self.edit(index)
                return
            if action == 'delete_item':
                self.tag_item_delete.emit(key, index.id, index.original_name)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key)
                return
            if action == 'manage_categories':
                self.edit_user_category.emit(category)
                return
            if action == 'search':
                self._toggle(index, set_to=search_state)
                return
            if action == 'add_to_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.all_children():
                        self.add_item_to_user_cat.emit(category,
                                                       c.tag.original_name,
                                                       c.tag.category)
                self.add_item_to_user_cat.emit(category, tag.original_name,
                                               tag.category)
                return
            if action == 'add_subcategory':
                self.add_subcategory.emit(key)
                return
            if action == 'search_category':
                self._toggle(index, set_to=search_state)
                return
            if action == 'delete_user_category':
                self.delete_user_category.emit(key)
                return
            if action == 'delete_search':
                saved_searches().delete(key)
                self.rebuild_saved_searches.emit()
                return
            if action == 'delete_item_from_user_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.children:
                        self.del_item_from_user_cat.emit(
                            key, c.tag.original_name, c.tag.category)
                self.del_item_from_user_cat.emit(key, tag.original_name,
                                                 tag.category)
                return
            if action == 'manage_searches':
                self.saved_search_edit.emit(category)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True)
                return

            reset_filter_categories = True
            if action == 'hide':
                self.hidden_categories.add(category)
            elif action == 'show':
                self.hidden_categories.discard(category)
            elif action == 'categorization':
                changed = self.collapse_model != category
                self._model.collapse_model = category
                if changed:
                    reset_filter_categories = False
                    gprefs['tags_browser_partition_method'] = category
            elif action == 'defaults':
                self.hidden_categories.clear()
            self.db.prefs.set('tag_browser_hidden_categories',
                              list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except:
            return
Пример #34
0
    def context_menu_handler(self, action=None, category=None,
                             key=None, index=None, search_state=None):
        if not action:
            return
        try:
            if action == 'set_icon':
                try:
                    path = choose_files(self, 'choose_category_icon',
                                _('Change Icon for: %s')%key, filters=[
                                ('Images', ['png', 'gif', 'jpg', 'jpeg'])],
                            all_files=False, select_only_single_file=True)
                    if path:
                        path = path[0]
                        p = QIcon(path).pixmap(QSize(128, 128))
                        d = os.path.join(config_dir, 'tb_icons')
                        if not os.path.exists(d):
                            os.makedirs(d)
                        with open(os.path.join(d, 'icon_'+
                            sanitize_file_name_unicode(key)+'.png'), 'wb') as f:
                            f.write(pixmap_to_data(p, format='PNG'))
                            path = os.path.basename(f.name)
                        self._model.set_custom_category_icon(key, unicode(path))
                        self.recount()
                except:
                    import traceback
                    traceback.print_exc()
                return
            if action == 'clear_icon':
                self._model.set_custom_category_icon(key, None)
                self.recount()
                return

            if action == 'edit_item':
                self.edit(index)
                return
            if action == 'delete_item':
                self.tag_item_delete.emit(key, index.id, index.original_name)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key)
                return
            if action == 'manage_categories':
                self.edit_user_category.emit(category)
                return
            if action == 'search':
                self._toggle(index, set_to=search_state)
                return
            if action == 'add_to_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.all_children():
                        self.add_item_to_user_cat.emit(category, c.tag.original_name,
                                               c.tag.category)
                self.add_item_to_user_cat.emit(category, tag.original_name,
                                               tag.category)
                return
            if action == 'add_subcategory':
                self.add_subcategory.emit(key)
                return
            if action == 'search_category':
                self._toggle(index, set_to=search_state)
                return
            if action == 'delete_user_category':
                self.delete_user_category.emit(key)
                return
            if action == 'delete_search':
                saved_searches().delete(key)
                self.rebuild_saved_searches.emit()
                return
            if action == 'delete_item_from_user_category':
                tag = index.tag
                if len(index.children) > 0:
                    for c in index.children:
                        self.del_item_from_user_cat.emit(key, c.tag.original_name,
                                               c.tag.category)
                self.del_item_from_user_cat.emit(key, tag.original_name, tag.category)
                return
            if action == 'manage_searches':
                self.saved_search_edit.emit(category)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True)
                return

            reset_filter_categories = True
            if action == 'hide':
                self.hidden_categories.add(category)
            elif action == 'show':
                self.hidden_categories.discard(category)
            elif action == 'categorization':
                changed = self.collapse_model != category
                self._model.collapse_model = category
                if changed:
                    reset_filter_categories = False
                    gprefs['tags_browser_partition_method'] = category
            elif action == 'defaults':
                self.hidden_categories.clear()
            self.db.prefs.set('tag_browser_hidden_categories', list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except:
            return