Beispiel #1
0
 def update_ip_info(self):
     from calibre.gui2.ui import get_gui
     gui = get_gui()
     if gui is not None:
         t = get_gui().iactions['Connect Share'].share_conn_menu.ip_text
         t = t.strip().strip('[]')
         self.ip_info.setText(_('Content server listening at: %s') % t)
Beispiel #2
0
	def download_author(self, id, limit_ids=None):
		''' Downloads all of an authors metadata to a path '''
		uri = '/maker/%s/calibre' % id
		print('Downloading metadata for author: ' + uri )
		# first get the zipfile
		tdir = self.download_and_extract(uri)
		get_gui().current_db.recursive_import(tdir)
Beispiel #3
0
 def __init__(self, parent=None):
     QWidget.__init__(self, parent)
     self.l = l = QVBoxLayout(self)
     self.la = la = QLabel(
         _(
             'calibre contains an internet server that allows you to'
             ' access your book collection using a browser from anywhere'
             ' in the world. Any changes to the settings will only take'
             ' effect after a server restart.'
         )
     )
     la.setWordWrap(True)
     l.addWidget(la)
     l.addSpacing(10)
     self.fl = fl = QFormLayout()
     l.addLayout(fl)
     self.opt_port = sb = QSpinBox(self)
     if options['port'].longdoc:
         sb.setToolTip(options['port'].longdoc)
     sb.setRange(1, 65535)
     sb.valueChanged.connect(self.changed_signal.emit)
     fl.addRow(options['port'].shortdoc + ':', sb)
     l.addSpacing(25)
     self.opt_auth = cb = QCheckBox(
         _('Require &username and password to access the content server')
     )
     l.addWidget(cb)
     self.auth_desc = la = QLabel(self)
     la.setStyleSheet('QLabel { font-size: small; font-style: italic }')
     la.setWordWrap(True)
     l.addWidget(la)
     l.addSpacing(25)
     self.opt_autolaunch_server = al = QCheckBox(
         _('Run server &automatically when calibre starts')
     )
     l.addWidget(al)
     l.addSpacing(25)
     self.h = h = QHBoxLayout()
     l.addLayout(h)
     for text, name in [(_('&Start server'),
                         'start_server'), (_('St&op server'), 'stop_server'),
                        (_('&Test server'),
                         'test_server'), (_('Show server &logs'), 'show_logs')]:
         b = QPushButton(text)
         b.clicked.connect(getattr(self, name).emit)
         setattr(self, name + '_button', b)
         if name == 'show_logs':
             h.addStretch(10)
         h.addWidget(b)
     self.ip_info = QLabel(self)
     self.update_ip_info()
     from calibre.gui2.ui import get_gui
     get_gui().iactions['Connect Share'].share_conn_menu.server_state_changed_signal.connect(self.update_ip_info)
     l.addSpacing(10)
     l.addWidget(self.ip_info)
     l.addStretch(10)
Beispiel #4
0
 def configure(self):
     d = Configure(get_gui().current_db, self)
     if d.exec_() == d.Accepted:
         if self.current_row is not None:
             mi = self.view.model().get_book_display_info(self.current_row)
             if mi is not None:
                 self.refresh(self.current_row, mi=mi)
Beispiel #5
0
 def get_saved_search_text(self):
     db = self.current_db
     try:
         current_search = self.search.currentText()
         if not current_search.startswith('search:'):
             raise ValueError()
         # This strange expression accounts for the four ways a search can be written:
         # search:fff, search:"fff", search:"=fff". and search:="fff"
         current_search = current_search[7:].lstrip('=').strip('"').lstrip('=')
         current_search = db.saved_search_lookup(current_search)
         if not current_search:
             raise ValueError()
         self.search.set_search_string(current_search)
     except:
         from calibre.gui2.ui import get_gui
         get_gui().status_bar.show_message(_('Current search is not a saved search'), 3000)
Beispiel #6
0
    def initialize(self, catalog_name, db):
        self.name = catalog_name
        from calibre.library.catalogs import FIELDS

        db = get_gui().current_db
        self.all_fields = {x for x in FIELDS if x != "all"} | set(db.custom_field_keys())
        sort_order = gprefs.get(self.name + "_db_fields_sort_order", {})
        fm = db.field_metadata

        def name(x):
            if x == "isbn":
                return "ISBN"
            if x == "library_name":
                return _("Library Name")
            if x.endswith("_index"):
                return name(x[: -len("_index")]) + " " + _("Number")
            return fm[x].get("name") or x

        def key(x):
            return (sort_order.get(x, 10000), name(x))

        self.db_fields.clear()
        for x in sorted(self.all_fields, key=key):
            QListWidgetItem(name(x) + " (%s)" % x, self.db_fields).setData(Qt.UserRole, x)
            if x.startswith("#") and fm[x]["datatype"] == "series":
                x += "_index"
                QListWidgetItem(name(x) + " (%s)" % x, self.db_fields).setData(Qt.UserRole, x)

        # Restore the activated fields from last use
        fields = frozenset(gprefs.get(self.name + "_db_fields", self.all_fields))
        for x in range(self.db_fields.count()):
            item = self.db_fields.item(x)
            item.setCheckState(Qt.Checked if unicode(item.data(Qt.UserRole)) in fields else Qt.Unchecked)
Beispiel #7
0
def register_keyboard_shortcuts(gui=None, finalize=False):
    if gui is None:
        from calibre.gui2.ui import get_gui
        gui = get_gui()
    if gui is None:
        return
    for unique_name, action in registered_shortcuts.iteritems():
        gui.keyboard.unregister_shortcut(unique_name)
        gui.removeAction(action)
    registered_shortcuts.clear()

    for filetype, applications in oprefs['entries'].iteritems():
        for application in applications:
            text = entry_to_icon_text(application, only_text=True)
            t = _('cover image') if filetype.upper() == 'COVER_IMAGE' else filetype.upper()
            name = _('Open {0} files with {1}').format(t, text)
            ac = QAction(gui)
            unique_name = application['uuid']
            func = partial(gui.open_with_action_triggerred, filetype, application)
            ac.triggered.connect(func)
            gui.keyboard.register_shortcut(unique_name, name, action=ac, group=_('Open With'))
            gui.addAction(ac)
            registered_shortcuts[unique_name] = ac
    if finalize:
        gui.keyboard.finalize()
Beispiel #8
0
 def _get_prefs(self):
     libraryid = get_library_uuid(get_gui().current_db)
     if self.current_prefs == None or self.libraryid != libraryid:
         #logger.debug("self.current_prefs == None(%s) or self.libraryid != libraryid(%s)"%(self.current_prefs == None,self.libraryid != libraryid))
         self.libraryid = libraryid
         self.current_prefs = get_library_config()
     return self.current_prefs
Beispiel #9
0
    def initialize(self, catalog_name, db):
        self.name = catalog_name
        from calibre.library.catalogs import FIELDS
        db = get_gui().current_db
        self.all_fields = {x for x in FIELDS if x != 'all'} | set(db.custom_field_keys())
        sort_order, fields = get_saved_field_data(self.name, self.all_fields)
        fm = db.field_metadata

        def name(x):
            if x == 'isbn':
                return 'ISBN'
            if x == 'library_name':
                return _('Library name')
            if x.endswith('_index'):
                return name(x[:-len('_index')]) + ' ' + _('Number')
            return fm[x].get('name') or x

        def key(x):
            return (sort_order.get(x, 10000), name(x))

        self.db_fields.clear()
        for x in sorted(self.all_fields, key=key):
            QListWidgetItem(name(x) + ' (%s)' % x, self.db_fields).setData(Qt.UserRole, x)
            if x.startswith('#') and fm[x]['datatype'] == 'series':
                x += '_index'
                QListWidgetItem(name(x) + ' (%s)' % x, self.db_fields).setData(Qt.UserRole, x)

        # Restore the activated fields from last use
        for x in range(self.db_fields.count()):
            item = self.db_fields.item(x)
            item.setCheckState(Qt.Checked if unicode_type(item.data(Qt.UserRole)) in fields else Qt.Unchecked)
Beispiel #10
0
 def save_search_button_clicked(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     name = unicode(self.currentText())
     if not name.strip():
         name = unicode(self.search_box.text()).replace('"', '')
     name = name.replace('\\', '')
     if not name:
         error_dialog(self, _('Create saved search'),
                      _('Invalid saved search name. '
                        'It must contain at least one letter or number'), show=True)
         return
     if not self.search_box.text():
         error_dialog(self, _('Create saved search'),
                      _('There is no search to save'), show=True)
         return
     db.saved_search_delete(name)
     db.saved_search_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()
Beispiel #11
0
 def accept(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     self.save_current_search()
     ss = {name:self.searches[name] for name in self.searches}
     db.saved_search_set_all(ss)
     QDialog.accept(self)
Beispiel #12
0
 def copy_search_button_clicked(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     idx = self.currentIndex()
     if idx < 0:
         return
     self.search_box.set_search_string(db.saved_search_lookup(unicode(self.currentText())))
Beispiel #13
0
 def update_button_state(self):
     from calibre.gui2.ui import get_gui
     gui = get_gui()
     is_running = gui.content_server is not None and gui.content_server.is_running
     self.start_server_button.setEnabled(not is_running)
     self.stop_server_button.setEnabled(is_running)
     self.test_server_button.setEnabled(is_running)
Beispiel #14
0
 def _get_db(self):
     if self.passed_db:
         return self.passed_db
     else:
         # In the GUI plugin we want current db so we detect when
         # it's changed.  CLI plugin calls need to pass db in.
         return get_gui().current_db
Beispiel #15
0
    def contextMenuEvent(self, ev):
        p = self.page()
        mf = p.mainFrame()
        r = mf.hitTestContent(ev.pos())
        url = unicode(r.linkUrl().toString()).strip()
        menu = p.createStandardContextMenu()
        ca = self.pageAction(p.Copy)
        for action in list(menu.actions()):
            if action is not ca:
                menu.removeAction(action)
        if not r.isNull():
            if url.startswith('http') or url.startswith('file:'):
                el = r.linkElement()
                author = el.toPlainText() if unicode(el.attribute('calibre-data')) == u'authors' else None
                for a, t in [('copy', _('&Copy Link')),
                ]:
                    ac = getattr(self, '%s_link_action'%a)
                    ac.current_url = url
                    ac.setText(t)
                    menu.addAction(ac)
                if author is not None:
                    ac = self.manage_author_action
                    ac.current_fmt = author
                    ac.setText(_('Manage %s') % author)
                    menu.addAction(ac)

            if url.startswith('format:'):
                parts = url.split(':')
                try:
                    book_id, fmt = int(parts[1]), parts[2].upper()
                except:
                    import traceback
                    traceback.print_exc()
                else:
                    from calibre.gui2.ui import get_gui
                    from calibre.ebooks.oeb.polish.main import SUPPORTED
                    db = get_gui().current_db.new_api
                    ofmt = fmt.upper() if fmt.startswith('ORIGINAL_') else 'ORIGINAL_' + fmt
                    nfmt = ofmt[len('ORIGINAL_'):]
                    fmts = {x.upper() for x in db.formats(book_id)}
                    for a, t in [('remove', _('Delete the %s format')),
                        ('save', _('Save the %s format to disk')),
                        ('restore', _('Restore the %s format')),
                        ('compare', ''),
                    ]:
                        if a == 'restore' and not fmt.startswith('ORIGINAL_'):
                            continue
                        if a == 'compare':
                            if ofmt not in fmts or nfmt not in SUPPORTED:
                                continue
                            t = _('Compare to the %s format') % (fmt[9:] if fmt.startswith('ORIGINAL_') else ofmt)
                        else:
                            t = t % fmt
                        ac = getattr(self, '%s_format_action'%a)
                        ac.current_fmt = (book_id, fmt)
                        ac.setText(t)
                        menu.addAction(ac)
        if len(menu.actions()) > 0:
            menu.exec_(ev.globalPos())
Beispiel #16
0
    def end(self):
        if gprefs["manual_add_auto_convert"] and self.auto_convert_books:
            from calibre.gui2.ui import get_gui

            gui = get_gui()
            gui.iactions["Convert Books"].auto_convert_auto_add(self.auto_convert_books)

        self.input_queue.put((None, None, None))
 def accept(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     if self.current_search_name:
         self.searches[self.current_search_name] = unicode(self.search_text.toPlainText())
     ss = {name:self.searches[name] for name in self.searches}
     db.saved_search_set_all(ss)
     QDialog.accept(self)
Beispiel #18
0
 def generate_cover(self, *args):
     book_id = self.data.get('id')
     if book_id is not None:
         from calibre.ebooks.covers import generate_cover
         from calibre.gui2.ui import get_gui
         mi = get_gui().current_db.new_api.get_metadata(book_id)
         cdata = generate_cover(mi)
         self.update_cover(cdata=cdata)
 def __init__(self, parent=None, search=None):
     self.initial_search = search
     Dialog.__init__(
         self, _('Add a new Saved search'), 'add-saved-search', parent)
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     self.searches = {}
     for name in db.saved_search_names():
         self.searches[name] = db.saved_search_lookup(name)
     self.search_names = {icu_lower(n) for n in db.saved_search_names()}
Beispiel #20
0
 def doit(self):
     from calibre.gui2.ui import get_gui
     library_broker = get_gui().library_broker
     newdb = library_broker.get_library(self.loc)
     try:
         if self.check_for_duplicates:
             self.find_identical_books_data = newdb.new_api.data_for_find_identical_books()
         self._doit(newdb)
     finally:
         library_broker.prune_loaded_dbs()
Beispiel #21
0
def get_saved_field_data(name, all_fields):
    db = get_gui().current_db
    val = db.new_api.pref('catalog-field-data-for-' + name)
    if val is None:
        sort_order = gprefs.get(name + '_db_fields_sort_order', {})
        fields = frozenset(gprefs.get(name+'_db_fields', all_fields))
    else:
        sort_order = val['sort_order']
        fields = frozenset(val['fields'])
    return sort_order, fields
Beispiel #22
0
 def initialize_saved_search_names(self):
     from calibre.gui2.ui import get_gui
     gui = get_gui()
     try:
         names = gui.current_db.saved_search_names()
     except AttributeError:
         # Happens during gui initialization
         names = []
     self.addItems(names)
     self.setCurrentIndex(-1)
Beispiel #23
0
def set_html(mi, html, web_view):
    from calibre.gui2.ui import get_gui
    gui = get_gui()
    book_id = getattr(mi, 'id', None)
    if gui and book_id is not None:
        path = gui.current_db.abspath(book_id, index_is_id=True)
        if path:
            web_view.setHtml(html, QUrl.fromLocalFile(os.path.join(path, 'metadata.html')))
            return
    web_view.setHtml(html)
Beispiel #24
0
 def run_export_action(self):
     from calibre.gui2.ui import get_gui
     library_paths = {i.data(Qt.UserRole):i.data(Qt.UserRole+1) for i in self.lib_list.selectedItems()}
     dbmap = {}
     gui = get_gui()
     if gui is not None:
         db = gui.current_db
         dbmap[db.library_path] = db.new_api
     return RunAction(_('Exporting all calibre data...'), _(
         'Failed to export data.'), partial(export, self.export_dir, library_paths=library_paths, dbmap=dbmap),
                   parent=self).exec_() == Dialog.Accepted
Beispiel #25
0
	def arg_library_status(self):
		''' Uses curren library type to sync '''
		db = get_gui().current_db.new_api
		type = db.pref('arg_library_type')
		id = db.pref('arg_id')
		if type and id:
			if type=='author':
				return self.arg_author_status(id)
			if type=='collection':
				return self.arg_collection_status(id)
		return {}
Beispiel #26
0
 def save_cover(self):
     from calibre.gui2.ui import get_gui
     book_id = self.data.get('id')
     db = get_gui().current_db.new_api
     path = choose_save_file(
         self, 'save-cover-from-book-details', _('Choose cover save location'),
         filters=[(_('JPEG images'), ['jpg', 'jpeg'])], all_files=False,
         initial_filename='{}.jpeg'.format(db.field_for('title', book_id, default_value='cover'))
     )
     if path:
         db.copy_cover_to(book_id, path)
Beispiel #27
0
 def mouseReleaseEvent(self, ev):
     if ev.button() == Qt.RightButton:
         tab_name = {'book':'book_details', 'grid':'cover_grid', 'cover_flow':'cover_browser', 'tags':'tag_browser'}.get(self.icname)
         if tab_name:
             from calibre.gui2.ui import get_gui
             gui = get_gui()
             if gui is not None:
                 gui.iactions['Preferences'].do_config(initial_plugin=('Interface', 'Look & Feel', tab_name+'_tab'), close_after_initial=True)
                 ev.accept()
                 return
     return QToolButton.mouseReleaseEvent(self, ev)
Beispiel #28
0
	def commit(self, book_id):
		''' Commits any local changes to the metadata for this book up to the server '''
		ids = self.get_arg_ids()
		if book_id not in ids:
			print('There is no a*rg identifier for this book')
			return
		arg_id, timestamp, version = ids[book_id]
		repo_version = self.arg_book_status(arg_id)
		if version!=repo_version:
			print('This library\'s version is out of date.')
			return
		# recompute the id
		mi = get_gui().current_db.get_metadata(book_id, index_is_id=True, get_cover=True)
		mi.identifiers['arg'] = "%s.%s" % (mi.identifiers['arg'].split('.')[0], version+1)
		get_gui().current_db.set_metadata(book_id, mi)
		mi = get_gui().current_db.get_metadata(book_id, index_is_id=True, get_cover=True)
		# get the opf that will be posted
		opf = metadata_to_opf(mi)
		# now post the metadata
		return self._post_metadata(arg_id, version, opf, mi.cover)
Beispiel #29
0
 def do_proceed(self, result):
     from calibre.gui2.ui import get_gui
     func = (self.callback if result == self.Accepted else
             self.cancel_callback)
     gui = get_gui()
     gui.proceed_requested.emit(func, self.payload)
     # Ensure this notification is garbage collected
     self.vlb.clicked.disconnect()
     self.callback = self.cancel_callback = self.payload = None
     self.setParent(None)
     _proceed_memory.remove(self)
Beispiel #30
0
def get_current_db():
    '''
    This method will try to return the current database in use by the user as
    efficiently as possible, i.e. without constructing duplicate
    LibraryDatabase objects.
    '''
    from calibre.gui2.ui import get_gui
    gui = get_gui()
    if gui is not None and gui.current_db is not None:
        return gui.current_db
    from calibre.library import db
    return db()
Beispiel #31
0
 def save_cover(self):
     from calibre.gui2.ui import get_gui
     book_id = self.data.get('id')
     db = get_gui().current_db.new_api
     path = choose_save_file(self,
                             'save-cover-from-book-details',
                             _('Choose cover save location'),
                             filters=[(_('JPEG images'), ['jpg', 'jpeg'])],
                             all_files=False,
                             initial_filename='{}.jpeg'.format(
                                 sanitize_file_name(
                                     db.field_for('title',
                                                  book_id,
                                                  default_value='cover'))))
     if path:
         db.copy_cover_to(book_id, path)
Beispiel #32
0
 def mouseReleaseEvent(self, ev):
     if ev.button() == Qt.RightButton:
         from calibre.gui2.ui import get_gui
         gui = get_gui()
         if self.icname == 'search':
             gui.iactions['Preferences'].do_config(initial_plugin=('Interface', 'Search'), close_after_initial=True)
             ev.accept()
             return
         tab_name = {'book':'book_details', 'grid':'cover_grid', 'cover_flow':'cover_browser',
                     'tags':'tag_browser', 'quickview':'quickview'}.get(self.icname)
         if tab_name:
             if gui is not None:
                 gui.iactions['Preferences'].do_config(initial_plugin=('Interface', 'Look & Feel', tab_name+'_tab'), close_after_initial=True)
                 ev.accept()
                 return
     return QToolButton.mouseReleaseEvent(self, ev)
Beispiel #33
0
def handle_changes(changes, gui=None):
    if not changes:
        return
    if gui is None:
        from calibre.gui2.ui import get_gui
        gui = get_gui()
    if gui is None:
        return
    refresh_ids = set()
    added, removed = set(), set()
    ss_changed = False
    for change in changes:
        if isinstance(change, (FormatsAdded, FormatsRemoved, MetadataChanged)):
            refresh_ids |= change.book_ids
        elif isinstance(change, BooksAdded):
            added |= change.book_ids
        elif isinstance(change, BooksDeleted):
            removed |= change.book_ids
        elif isinstance(change, SavedSearchesChanged):
            ss_changed = True

    if added and removed:
        gui.refresh_all()
        return
    refresh_ids -= added | removed
    orig = gui.tags_view.disable_recounting, gui.disable_cover_browser_refresh
    gui.tags_view.disable_recounting = gui.disable_cover_browser_refresh = True
    try:
        if added:
            gui.current_db.data.books_added(added)
            gui.iactions['Add Books'].refresh_gui(len(added), recount=False)
        if removed:
            next_id = gui.current_view().next_id
            m = gui.library_view.model()
            m.ids_deleted(removed)
            gui.iactions['Remove Books'].library_ids_deleted2(removed,
                                                              next_id=next_id)
        if refresh_ids:
            gui.iactions['Edit Metadata'].refresh_books_after_metadata_edit(
                refresh_ids)
        if ss_changed:
            gui.saved_searches_changed(recount=False)
        gui.tags_view.disable_recounting = gui.disable_cover_browser_refresh = False
        gui.tags_view.recount(), gui.refresh_cover_browser()
    finally:
        gui.tags_view.disable_recounting, gui.disable_cover_browser_refresh = orig
Beispiel #34
0
def get_field_list(fm, use_defaults=False, pref_name='book_display_fields'):
    from calibre.gui2.ui import get_gui
    db = get_gui().current_db
    if use_defaults:
        src = db.prefs.defaults
    else:
        old_val = gprefs.get(pref_name, None)
        if old_val is not None and not db.prefs.has_setting(pref_name):
            src = gprefs
        else:
            src = db.prefs
    fieldlist = list(src[pref_name])
    names = frozenset(x[0] for x in fieldlist)
    available = frozenset(fm.displayable_field_keys())
    for field in available - names:
        fieldlist.append((field, True))
    return [(f, d) for f, d in fieldlist if f in available]
Beispiel #35
0
def get_library_config():
    db = get_gui().current_db
    library_id = get_library_uuid(db)
    library_config = None
    # Check whether this is a configuration needing to be migrated
    # from json into database.  If so: get it, set it, wipe it from json.
    if library_id in old_prefs:
        #print("get prefs from old_prefs")
        library_config = old_prefs[library_id]
        set_library_config(library_config)
        del old_prefs[library_id]

    if library_config is None:
        #print("get prefs from db")
        library_config = db.prefs.get_namespaced(PREFS_NAMESPACE, PREFS_KEY_SETTINGS,
                                                 copy.deepcopy(default_prefs))
    return library_config
Beispiel #36
0
def add_item_specific_entries(menu, data, book_info):
    search_internet_added = False
    dt = data['type']
    if dt == 'format':
        add_format_entries(menu, data, book_info)
    elif dt == 'author':
        author = data['name']
        menu.addAction(
            init_manage_action(book_info.manage_action, 'authors', author))
        if hasattr(book_info, 'search_internet'):
            menu.sia = sia = create_search_internet_menu(
                book_info.search_internet, author)
            menu.addMenu(sia)
            search_internet_added = True
        if hasattr(book_info, 'search_requested'):
            menu.addAction(
                _('Search calibre for %s') % author,
                lambda: book_info.search_requested('authors:"={}"'.format(
                    author.replace('"', r'\"'))))
    elif dt in ('path', 'devpath'):
        from calibre.gui2.ui import get_gui
        path = data['loc']
        ac = book_info.copy_link_action
        if isinstance(path, int):
            path = get_gui().library_view.model().db.abspath(path,
                                                             index_is_id=True)
        ac.current_url = path
        ac.setText(_('Copy path'))
        menu.addAction(ac)
    else:
        field = data.get('field')
        if field is not None:
            book_id = int(data['book_id'])
            value = data['value']
            if field == 'identifiers':
                menu.addAction(book_info.edit_identifiers_action)
            elif field in ('tags', 'series',
                           'publisher') or is_category(field):
                menu.addAction(
                    init_manage_action(book_info.manage_action, field, value))
            ac = book_info.remove_item_action
            ac.data = (field, value, book_id)
            ac.setText(_('Remove %s from this book') % value)
            menu.addAction(ac)
    return search_internet_added
Beispiel #37
0
 def run_export_action(self):
     from calibre.gui2.ui import get_gui
     library_paths = {
         i.data(Qt.UserRole): i.data(Qt.UserRole + 1)
         for i in self.lib_list.selectedItems()
     }
     dbmap = {}
     gui = get_gui()
     if gui is not None:
         db = gui.current_db
         dbmap[db.library_path] = db.new_api
     return RunAction(_('Exporting all calibre data...'),
                      _('Failed to export data.'),
                      partial(export,
                              self.export_dir,
                              library_paths=library_paths,
                              dbmap=dbmap),
                      parent=self).exec_() == Dialog.Accepted
Beispiel #38
0
 def __init__(self,
              parent=None,
              search=None,
              commit_changes=True,
              label=None,
              validate=None):
     self.initial_search = search
     self.validate = validate
     self.label = label
     self.commit_changes = commit_changes
     Dialog.__init__(self, _('Add a new Saved search'), 'add-saved-search',
                     parent)
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     self.searches = {}
     for name in db.saved_search_names():
         self.searches[name] = db.saved_search_lookup(name)
     self.search_names = {icu_lower(n): n for n in db.saved_search_names()}
Beispiel #39
0
    def get_custom_columns_date(self):
        try:
            from calibre.gui2.ui import get_gui
            db = get_gui().current_db
        except:
            return None

        column_types = ['date', 'datetime']
        custom_fields = set(db.custom_field_keys())
        available_columns = {}

        for field in list(custom_fields):
            column = db.field_metadata[field]
            typ = column['datatype']
            if typ in column_types:
                available_columns[field] = column

        return available_columns
Beispiel #40
0
def details_context_menu_event(view, ev, book_info, add_popup_action=False):
    url = view.anchorAt(ev.pos())
    menu = QMenu(view)
    menu.addAction(QIcon(I('edit-copy.png')), _('Copy all book details'),
                   partial(copy_all, view))
    cm = QMenu(_('Copy link to book'), menu)
    cm.setIcon(QIcon(I('edit-copy.png')))
    copy_links_added = False
    search_internet_added = False
    if url and url.startswith('action:'):
        data = json_loads(from_hex_bytes(url.split(':', 1)[1]))
        create_copy_links(cm, data)
        copy_links_added = True
        search_internet_added = add_item_specific_entries(
            menu, data, book_info)
    elif url and not url.startswith('#'):
        ac = book_info.copy_link_action
        ac.current_url = url
        ac.setText(_('Copy link location'))
        menu.addAction(ac)
    if not copy_links_added:
        create_copy_links(cm)
    if list(cm.actions()):
        menu.addMenu(cm)

    if not search_internet_added and hasattr(book_info, 'search_internet'):
        menu.addSeparator()
        menu.si = create_search_internet_menu(book_info.search_internet)
        menu.addMenu(menu.si)
    for ac in tuple(menu.actions()):
        if not ac.isEnabled():
            menu.removeAction(ac)
    menu.addSeparator()
    if add_popup_action:
        ac = menu.addAction(_('Open the Book details window'))
        ac.triggered.connect(book_info.show_book_info)
    else:
        from calibre.gui2.ui import get_gui
        ema = get_gui().iactions['Edit Metadata'].menuless_qaction
        menu.addAction(
            _('Open the Edit metadata window') + '\t' +
            ema.shortcut().toString(QKeySequence.NativeText), ema.trigger)
    if len(menu.actions()) > 0:
        menu.exec_(ev.globalPos())
Beispiel #41
0
    def setup_ui(self):
        from calibre.gui2.ui import get_gui
        db = get_gui().current_db
        self.l = l = QVBoxLayout(self)
        b = self.bb.addButton(_('&Add search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('plus.png')))
        b.clicked.connect(self.add_search)

        b = self.bb.addButton(_('&Remove search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('minus.png')))
        b.clicked.connect(self.del_search)

        b = self.bb.addButton(_('&Edit search'),
                              QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('modified.png')))
        b.clicked.connect(self.edit_search)

        self.slist = QListWidget(self)
        self.slist.setStyleSheet('QListView::item { padding: 3px }')
        self.slist.activated.connect(self.edit_search)
        self.slist.setAlternatingRowColors(True)
        self.searches = {
            name: db.saved_search_lookup(name)
            for name in db.saved_search_names()
        }
        self.populate_search_list()
        if self.initial_search is not None and self.initial_search in self.searches:
            self.select_search(self.initial_search)
        elif self.searches:
            self.slist.setCurrentRow(0)
        self.slist.currentItemChanged.connect(self.current_index_changed)
        l.addWidget(self.slist)

        self.desc = la = QLabel('\xa0')
        la.setWordWrap(True)
        l.addWidget(la)

        l.addWidget(self.bb)
        self.current_index_changed(self.slist.currentItem())
        self.setMinimumHeight(500)
        self.setMinimumWidth(600)
Beispiel #42
0
    def build_search_restriction_list(self):
        self.search_restriction_list_built = True
        from calibre.gui2.ui import get_gui
        m = self.ar_menu
        m.clear()

        current_restriction_text = None

        if self.search_restriction.count() > 1:
            txt = unicode_type(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(get_gui().current_db.saved_search_names(),
                        key=sort_key):
            add_action(n, dex)
            dex += 1
Beispiel #43
0
 def delete_current_search(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     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 = db.saved_search_lookup(unicode(self.currentText()))
     if ss is None:
         return
     db.saved_search_delete(unicode(self.currentText()))
     self.clear()
     self.search_box.clear()
     self.changed.emit()
Beispiel #44
0
 def save_search_button_clicked(self):
     from calibre.gui2.ui import get_gui
     db = get_gui().current_db
     name = unicode(self.currentText())
     if not name.strip():
         name = unicode(self.search_box.text()).replace('"', '')
     if not (name and self.search_box.text()):
         error_dialog(self, _('Create saved search'),
                      _('There is no search to save'), show=True)
         return
     db.saved_search_delete(name)
     db.saved_search_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()
Beispiel #45
0
    def __init__(self, parent, initial_search=None):
        from calibre.gui2.ui import get_gui
        db = get_gui().current_db
        QDialog.__init__(self, parent)
        Ui_SavedSearchEditor.__init__(self)
        self.setupUi(self)

        self.add_search_button.clicked.connect(self.add_search)
        self.search_name_box.currentIndexChanged[(int)].connect(self.current_index_changed)
        self.delete_search_button.clicked.connect(self.del_search)
        self.rename_button.clicked.connect(self.rename_search)

        self.current_search_name = None
        self.searches = {}
        for name in db.saved_search_names():
            self.searches[name] = db.saved_search_lookup(name)
        self.search_names = set([icu_lower(n) for n in db.saved_search_names()])

        self.populate_search_list()
        if initial_search is not None and initial_search in self.searches:
            self.select_search(initial_search)
Beispiel #46
0
 def validate_import(self):
     from calibre.gui2.ui import get_gui
     g = get_gui()
     if g is not None:
         if g.iactions['Connect Share'].content_server_is_running:
             error_dialog(self, _('Content server running'), _(
                 'Cannot import while the Content server is running, shut it down first by clicking the'
                 ' "Connect/share" button on the calibre toolbar'), show=True)
             return False
     if self.import_panel.stack.currentIndex() == 0:
         error_dialog(self, _('No folder selected'), _(
             'You must select a folder containing the previously exported data that you wish to import'), show=True)
         return False
     else:
         blanks = []
         for w in self.imported_lib_widgets:
             newloc = w.path
             if not newloc:
                 blanks.append(w.lpath)
                 continue
             if iswindows and len(newloc) > LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT:
                 error_dialog(self, _('Too long'),
                     _('Path to library ({0}) too long. Must be less than'
                     ' {1} characters.').format(newloc, LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT), show=True)
                 return False
             if not os.path.isdir(newloc):
                 error_dialog(self, _('Not a folder'), _('%s is not a folder')%newloc, show=True)
                 return False
             if os.listdir(newloc):
                 error_dialog(self, _('Folder not empty'), _('%s is not an empty folder')%newloc, show=True)
                 return False
         if blanks:
             if len(blanks) == len(self.imported_lib_widgets):
                 error_dialog(self, _('No libraries selected'), _(
                     'You must specify the location for at least one library'), show=True)
                 return False
             if not question_dialog(self, _('Some libraries ignored'), _(
                     'You have chosen not to import some libraries. Proceed anyway?')):
                 return False
     return True
Beispiel #47
0
    def refresh(self, idx):
        '''
        Given a cell in the library view, display the information. This method
        converts the index into the lookup ken
        '''
        if self.lock_qv.isChecked():
            return

        try:
            bv_row = idx.row()
            from calibre.gui2.ui import get_gui
            view = get_gui().library_view.alternate_views.current_view.__class__.__name__
            self.current_column = (
                self.view.column_map.index('authors') if view == 'GridView'
                                                      else idx.column())
            key = self.view.column_map[self.current_column]
            book_id = self.view.model().id(bv_row)
            if self.current_book_id == book_id and self.current_key == key:
                return
            self._refresh(book_id, key)
        except:
            self.indicate_no_items()
Beispiel #48
0
def init_find_in_grouped_search(menu, field, value, book_info):
    from calibre.gui2.ui import get_gui
    db = get_gui().current_db
    fm = db.field_metadata
    field_name = fm.get(field, {}).get('name', None)
    if field_name is None:
        # I don't think this can ever happen, but ...
        return
    gsts = db.prefs.get('grouped_search_terms', {})
    gsts_to_show = []
    for v in gsts:
        fk = fm.search_term_to_field_key(v)
        if field in fk:
            gsts_to_show.append(v)

    if gsts_to_show:
        m = QMenu(
            (_('Search calibre for %s') + '...') % escape_for_menu(value),
            menu)
        m.setIcon(QIcon(I('search.png')))
        menu.addMenu(m)
        m.addAction(QIcon(get_icon_path(field, '')),
                    _('in category %s') % escape_for_menu(field_name),
                    lambda g=field: book_info.search_requested(
                        '{}:"={}"'.format(g, value.replace('"', r'\"')), ''))
        for gst in gsts_to_show:
            icon_path = get_icon_path(gst, '@')
            m.addAction(
                QIcon(icon_path),
                _('in grouped search %s') % gst,
                lambda g=gst: book_info.search_requested(
                    '{}:"={}"'.format(g, value.replace('"', r'\"')), ''))
    else:
        menu.addAction(
            QIcon(I('search.png')),
            _('Search calibre for {val} in category {name}').format(
                val=escape_for_menu(value), name=escape_for_menu(field_name)),
            lambda g=field: book_info.search_requested(
                '{}:"={}"'.format(g, value.replace('"', r'\"')), ''))
Beispiel #49
0
    def initialize(self, catalog_name, db):
        self.name = catalog_name
        from calibre.library.catalogs import FIELDS
        db = get_gui().current_db
        self.all_fields = {x
                           for x in FIELDS
                           if x != 'all'} | set(db.custom_field_keys())
        sort_order, fields = get_saved_field_data(self.name, self.all_fields)
        fm = db.field_metadata

        def name(x):
            if x == 'isbn':
                return 'ISBN'
            if x == 'library_name':
                return _('Library name')
            if x.endswith('_index'):
                return name(x[:-len('_index')]) + ' ' + _('Number')
            return fm[x].get('name') or x

        def key(x):
            return (sort_order.get(x, 10000), name(x))

        self.db_fields.clear()
        for x in sorted(self.all_fields, key=key):
            QListWidgetItem(name(x) + ' (%s)' % x,
                            self.db_fields).setData(Qt.ItemDataRole.UserRole,
                                                    x)
            if x.startswith('#') and fm[x]['datatype'] == 'series':
                x += '_index'
                QListWidgetItem(name(x) + ' (%s)' % x, self.db_fields).setData(
                    Qt.ItemDataRole.UserRole, x)

        # Restore the activated fields from last use
        for x in range(self.db_fields.count()):
            item = self.db_fields.item(x)
            item.setCheckState(Qt.CheckState.Checked if str(
                item.data(Qt.ItemDataRole.UserRole)) in
                               fields else Qt.CheckState.Unchecked)
Beispiel #50
0
def handle_enter_press(self, ev, special_action=None, has_edit_cell=True):
    if ev.key() in (Qt.Key_Enter, Qt.Key_Return):
        mods = ev.modifiers()
        if mods & Qt.CTRL or mods & Qt.ALT or mods & Qt.SHIFT or mods & Qt.META:
            return
        if self.state() != self.EditingState and self.hasFocus() and self.currentIndex().isValid():
            from calibre.gui2.ui import get_gui
            ev.ignore()
            tweak = tweaks['enter_key_behavior']
            gui = get_gui()
            if tweak == 'edit_cell':
                if has_edit_cell:
                    self.edit(self.currentIndex(), self.EditKeyPressed, ev)
                else:
                    gui.iactions['Edit Metadata'].edit_metadata(False)
            elif tweak == 'edit_metadata':
                gui.iactions['Edit Metadata'].edit_metadata(False)
            elif tweak == 'do_nothing':
                pass
            else:
                if special_action is not None:
                    special_action(self.currentIndex())
                gui.iactions['View'].view_triggered(self.currentIndex())
            return True
Beispiel #51
0
def register_keyboard_shortcuts(gui=None, finalize=False):
    if gui is None:
        from calibre.gui2.ui import get_gui
        gui = get_gui()
    if gui is None:
        return
    for unique_name, action in registered_shortcuts.iteritems():
        gui.keyboard.unregister_shortcut(unique_name)
        gui.removeAction(action)
    registered_shortcuts.clear()

    for filetype, applications in oprefs['entries'].iteritems():
        for application in applications:
            text = entry_to_icon_text(application, only_text=True)
            t = _('cover image') if filetype.upper() == 'COVER_IMAGE' else filetype.upper()
            name = _('Open {0} files with {1}').format(t, text)
            ac = QAction(gui)
            unique_name = application['uuid']
            ac.triggered.connect(partial(gui.open_with_action_triggerred, filetype, application))
            gui.keyboard.register_shortcut(unique_name, name, action=ac, group=_('Open With'))
            gui.addAction(ac)
            registered_shortcuts[unique_name] = ac
    if finalize:
        gui.keyboard.finalize()
Beispiel #52
0
def is_category(field):
    from calibre.db.categories import find_categories
    from calibre.gui2.ui import get_gui
    gui = get_gui()
    fm = gui.current_db.field_metadata
    return field in {x[0] for x in find_categories(fm) if fm.is_custom_field(x[0])}
Beispiel #53
0
    def __init__(self, parent, text, mi=None, fm=None, color_field=None,
                 icon_field_key=None, icon_rule_kind=None):
        QDialog.__init__(self, parent)
        Ui_TemplateDialog.__init__(self)
        self.setupUi(self)

        self.coloring = color_field is not None
        self.iconing = icon_field_key is not None

        cols = []
        if fm is not None:
            for key in sorted(displayable_columns(fm),
                              key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0):
                if key == color_row_key and not self.coloring:
                    continue
                from calibre.gui2.preferences.coloring import all_columns_string
                name = all_columns_string if key == color_row_key else fm[key]['name']
                if name:
                    cols.append((name, key))

        self.color_layout.setVisible(False)
        self.icon_layout.setVisible(False)

        if self.coloring:
            self.color_layout.setVisible(True)
            for n1, k1 in cols:
                self.colored_field.addItem(n1, k1)
            self.colored_field.setCurrentIndex(self.colored_field.findData(color_field))
        elif self.iconing:
            self.icon_layout.setVisible(True)
            for n1, k1 in cols:
                self.icon_field.addItem(n1, k1)
            self.icon_file_names = []
            d = os.path.join(config_dir, 'cc_icons')
            if os.path.exists(d):
                for icon_file in os.listdir(d):
                    icon_file = icu_lower(icon_file)
                    if os.path.exists(os.path.join(d, icon_file)):
                        if icon_file.endswith('.png'):
                            self.icon_file_names.append(icon_file)
            self.icon_file_names.sort(key=sort_key)
            self.update_filename_box()

            dex = 0
            from calibre.gui2.preferences.coloring import icon_rule_kinds
            for i,tup in enumerate(icon_rule_kinds):
                txt,val = tup
                self.icon_kind.addItem(txt, userData=QVariant(val))
                if val == icon_rule_kind:
                    dex = i
            self.icon_kind.setCurrentIndex(dex)
            self.icon_field.setCurrentIndex(self.icon_field.findData(icon_field_key))

        if mi:
            self.mi = mi
        else:
            self.mi = Metadata(_('Title'), [_('Author')])
            self.mi.author_sort = _('Author Sort')
            self.mi.series = _('Series')
            self.mi.series_index = 3
            self.mi.rating = 4.0
            self.mi.tags = [_('Tag 1'), _('Tag 2')]
            self.mi.languages = ['eng']
            if fm is not None:
                self.mi.set_all_user_metadata(fm.custom_field_metadata())
            else:
                # No field metadata. Grab a copy from the current library so
                # that we can validate any custom column names. The values for
                # the columns will all be empty, which in some very unusual
                # cases might cause formatter errors. We can live with that.
                from calibre.gui2.ui import get_gui
                self.mi.set_all_user_metadata(
                      get_gui().current_db.new_api.field_metadata.custom_field_metadata())

        # Remove help icon on title bar
        icon = self.windowIcon()
        self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
        self.setWindowIcon(icon)

        self.last_text = ''
        self.highlighter = TemplateHighlighter(self.textbox.document())
        self.textbox.cursorPositionChanged.connect(self.text_cursor_changed)
        self.textbox.textChanged.connect(self.textbox_changed)

        self.textbox.setTabStopWidth(10)
        self.source_code.setTabStopWidth(10)
        self.documentation.setReadOnly(True)
        self.source_code.setReadOnly(True)

        if text is not None:
            self.textbox.setPlainText(text)
        self.buttonBox.button(QDialogButtonBox.Ok).setText(_('&OK'))
        self.buttonBox.button(QDialogButtonBox.Cancel).setText(_('&Cancel'))
        self.color_copy_button.clicked.connect(self.color_to_clipboard)
        self.filename_button.clicked.connect(self.filename_button_clicked)
        self.icon_copy_button.clicked.connect(self.icon_to_clipboard)

        try:
            with open(P('template-functions.json'), 'rb') as f:
                self.builtin_source_dict = json.load(f, encoding='utf-8')
        except:
            self.builtin_source_dict = {}

        self.funcs = formatter_functions().get_functions()
        self.builtins = formatter_functions().get_builtins()

        func_names = sorted(self.funcs)
        self.function.clear()
        self.function.addItem('')
        self.function.addItems(func_names)
        self.function.setCurrentIndex(0)
        self.function.currentIndexChanged[str].connect(self.function_changed)
        self.textbox_changed()
        self.rule = (None, '')

        tt = _('Template language tutorial')
        self.template_tutorial.setText(
                '<a href="http://manual.calibre-ebook.com/template_lang.html">'
                '%s</a>'%tt)
        tt = _('Template function reference')
        self.template_func_reference.setText(
                '<a href="http://manual.calibre-ebook.com/template_ref.html">'
                '%s</a>'%tt)
Beispiel #54
0
def set_library_config(library_config):
    get_gui().current_db.prefs.set_namespaced(PREFS_NAMESPACE,
                                              PREFS_KEY_SETTINGS,
                                              library_config)
Beispiel #55
0
def current_db():
    from calibre.gui2.ui import get_gui
    return (getattr(current_db, 'ans', None) or get_gui().current_db).new_api
Beispiel #56
0
 def edit_tags(self):
     from calibre.gui2.dialogs.tag_editor import TagEditor
     d = TagEditor(self, get_gui().current_db, current_tags=list(filter(None, [x.strip() for x in self.query.text().split(',')])))
     if d.exec_() == d.Accepted:
         self.query.setText(', '.join(d.tags))
Beispiel #57
0
 def can_use_tag_editor(self):
     return self.SUBJECT is RuleEdit.SUBJECT and 'matches' not in self.match_type.currentData() and get_gui() is not None
Beispiel #58
0
    def __init__(
        self, title=_('Choose Files'),
        filters=[],
        add_all_files_filter=True,
        parent=None,
        modal=True,
        name='',
        mode=QFileDialog.ExistingFiles,
        default_dir=u'~',
        no_save_dir=False,
        combine_file_and_saved_dir=False
    ):
        from calibre.gui2 import dynamic, sanitize_env_vars
        from calibre.gui2.ui import get_gui
        gui = get_gui()
        adapt_menubar = gui.bars_manager.adapt_menu_bar_for_dialog if gui is not None else Dummy()
        QObject.__init__(self)
        ftext = ''
        if filters:
            for filter in filters:
                text, extensions = filter
                extensions = ['*'+(i if i.startswith('.') else '.'+i) for i in
                        extensions]
                ftext += '%s (%s);;'%(text, ' '.join(extensions))
        if add_all_files_filter or not ftext:
            ftext += 'All files (*)'
        if ftext.endswith(';;'):
            ftext = ftext[:-2]

        self.dialog_name = dialog_name(name, title)
        self.selected_files = None
        self.fd = None

        if combine_file_and_saved_dir:
            bn = os.path.basename(default_dir)
            prev = dynamic.get(self.dialog_name,
                    os.path.expanduser(u'~'))
            if os.path.exists(prev):
                if os.path.isfile(prev):
                    prev = os.path.dirname(prev)
            else:
                prev = os.path.expanduser(u'~')
            initial_dir = os.path.join(prev, bn)
        elif no_save_dir:
            initial_dir = os.path.expanduser(default_dir)
        else:
            initial_dir = dynamic.get(self.dialog_name,
                    os.path.expanduser(default_dir))
        if not isinstance(initial_dir, string_or_bytes):
            initial_dir = os.path.expanduser(default_dir)
        if not initial_dir or (not os.path.exists(initial_dir) and not (
                mode == QFileDialog.AnyFile and (no_save_dir or combine_file_and_saved_dir))):
            initial_dir = select_initial_dir(initial_dir)
        self.selected_files = []
        use_native_dialog = 'CALIBRE_NO_NATIVE_FILEDIALOGS' not in os.environ
        with sanitize_env_vars():
            opts = QFileDialog.Option()
            if not use_native_dialog:
                opts |= QFileDialog.DontUseNativeDialog
            if mode == QFileDialog.AnyFile:
                with adapt_menubar:
                    f = QFileDialog.getSaveFileName(parent, title,
                        initial_dir, ftext, "", opts)
                if f and f[0]:
                    self.selected_files.append(f[0])
            elif mode == QFileDialog.ExistingFile:
                with adapt_menubar:
                    f = QFileDialog.getOpenFileName(parent, title,
                        initial_dir, ftext, "", opts)
                if f and f[0] and os.path.exists(f[0]):
                    self.selected_files.append(f[0])
            elif mode == QFileDialog.ExistingFiles:
                with adapt_menubar:
                    fs = QFileDialog.getOpenFileNames(parent, title, initial_dir,
                            ftext, "", opts)
                if fs and fs[0]:
                    for f in fs[0]:
                        f = unicode_type(f)
                        if not f:
                            continue
                        if not os.path.exists(f):
                            # QFileDialog for some reason quotes spaces
                            # on linux if there is more than one space in a row
                            f = unquote(f)
                        if f and os.path.exists(f):
                            self.selected_files.append(f)
            else:
                if mode == QFileDialog.Directory:
                    opts |= QFileDialog.ShowDirsOnly
                with adapt_menubar:
                    f = unicode_type(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts))
                if os.path.exists(f):
                    self.selected_files.append(f)
        if self.selected_files:
            self.selected_files = [unicode_type(q) for q in self.selected_files]
            saved_loc = self.selected_files[0]
            if os.path.isfile(saved_loc):
                saved_loc = os.path.dirname(saved_loc)
            if not no_save_dir:
                dynamic[self.dialog_name] = saved_loc
        self.accepted = bool(self.selected_files)
Beispiel #59
0
    def context_menu_handler(self, action=None, category=None,
                             key=None, index=None, search_state=None,
                             use_vl=None, is_first_letter=False):
        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(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_type(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

            def set_completion_data(category):
                try:
                    completion_data = self.db.new_api.all_field_names(category)
                except:
                    completion_data = None
                self.itemDelegate().set_completion_data(completion_data)

            if action == 'edit_item_no_vl':
                item = self.model().get_node(index)
                item.use_vl = False
                set_completion_data(category)
                self.edit(index)
                return
            if action == 'edit_item_in_vl':
                item = self.model().get_node(index)
                item.use_vl = True
                set_completion_data(category)
                self.edit(index)
                return
            if action == 'delete_item_in_vl':
                tag = index.tag
                children = index.child_tags()
                self.tag_item_delete.emit(key, tag.id, tag.original_name,
                                          self.model().get_book_ids_to_use(),
                                          children)
                return
            if action == 'delete_item_no_vl':
                tag = index.tag
                children = index.child_tags()
                self.tag_item_delete.emit(key, tag.id, tag.original_name,
                                          None, children)
                return
            if action == 'open_editor':
                self.tags_list_edit.emit(category, key, is_first_letter)
                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 == "raw_search":
                from calibre.gui2.ui import get_gui
                get_gui().get_saved_search_text(search_name='search:' + key)
                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':
                self.model().db.saved_search_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_authors':
                self.author_sort_edit.emit(self, index, False, False, is_first_letter)
                return
            if action == 'edit_author_sort':
                self.author_sort_edit.emit(self, index, True, False, is_first_letter)
                return
            if action == 'edit_author_link':
                self.author_sort_edit.emit(self, index, False, True, False)
                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()
            elif action == 'add_tag':
                item = self.model().get_node(index)
                if item is not None:
                    self.apply_to_selected_books(item)
                return
            elif action == 'remove_tag':
                item = self.model().get_node(index)
                if item is not None:
                    self.apply_to_selected_books(item, True)
                return
            self.db.new_api.set_pref('tag_browser_hidden_categories', list(self.hidden_categories))
            if reset_filter_categories:
                self._model.set_categories_filter(None)
            self._model.rebuild_node_tree()
        except Exception:
            import traceback
            traceback.print_exc()
            return
Beispiel #60
0
def add_item_specific_entries(menu, data, book_info, copy_menu, search_menu):
    from calibre.gui2.ui import get_gui
    search_internet_added = False
    find_action = book_info.find_in_tag_browser_action
    dt = data['type']

    def add_copy_action(name):
        copy_menu.addAction(QIcon(I('edit-copy.png')), _('The text: {}').format(name), lambda: QApplication.instance().clipboard().setText(name))

    if dt == 'format':
        add_format_entries(menu, data, book_info, copy_menu, search_menu)
    elif dt == 'author':
        author = data['name']
        if data['url'] != 'calibre':
            ac = book_info.copy_link_action
            ac.current_url = data['url']
            ac.setText(_('&Author link'))
            copy_menu.addAction(ac)
        add_copy_action(author)
        init_find_in_tag_browser(search_menu, find_action, 'authors', author)
        init_find_in_grouped_search(search_menu, 'authors', author, book_info)
        menu.addAction(init_manage_action(book_info.manage_action, 'authors', author))
        if hasattr(book_info, 'search_internet'):
            search_menu.addSeparator()
            search_menu.sim = create_search_internet_menu(book_info.search_internet, author)
            for ac in search_menu.sim.actions():
                search_menu.addAction(ac)
                ac.setText(_('Search {0} for {1}').format(ac.text(), author))
            search_internet_added = True
        if hasattr(book_info, 'remove_item_action'):
            ac = book_info.remove_item_action
            book_id = get_gui().library_view.current_id
            ac.data = ('authors', author, book_id)
            ac.setText(_('Remove %s from this book') % escape_for_menu(author))
            menu.addAction(ac)
    elif dt in ('path', 'devpath'):
        path = data['loc']
        ac = book_info.copy_link_action
        if isinstance(path, int):
            path = get_gui().library_view.model().db.abspath(path, index_is_id=True)
        ac.current_url = path
        ac.setText(_('The location of the book'))
        copy_menu.addAction(ac)
    else:
        field = data.get('field')
        if field is not None:
            book_id = int(data['book_id'])
            value = remove_value = data['value']
            if field == 'identifiers':
                ac = book_info.copy_link_action
                ac.current_url = value
                ac.setText(_('&Identifier'))
                copy_menu.addAction(ac)
                if data.get('url'):
                    book_info.copy_identifiers_url_action.current_url = data['url']
                    copy_menu.addAction(book_info.copy_identifiers_url_action)
                remove_value = data['id_type']
                init_find_in_tag_browser(search_menu, find_action, field, remove_value)
                init_find_in_grouped_search(search_menu, field, remove_value, book_info)
                menu.addAction(book_info.edit_identifiers_action)
            elif field in ('tags', 'series', 'publisher') or is_category(field):
                add_copy_action(value)
                init_find_in_tag_browser(search_menu, find_action, field, value)
                init_find_in_grouped_search(search_menu, field, value, book_info)
                menu.addAction(init_manage_action(book_info.manage_action, field, value))
            elif field == 'languages':
                remove_value = langnames_to_langcodes((value,)).get(value, 'Unknown')
                init_find_in_tag_browser(search_menu, find_action, field, value)
                init_find_in_grouped_search(search_menu, field, value, book_info)
            ac = book_info.remove_item_action
            ac.data = (field, remove_value, book_id)
            ac.setText(_('Remove %s from this book') % escape_for_menu(value))
            menu.addAction(ac)
    return search_internet_added