mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
parent
385986fe4b
commit
f628964592
@ -131,7 +131,22 @@ def fixcase(x):
|
|||||||
x = titlecase(x)
|
x = titlecase(x)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
class Option(object):
|
||||||
|
__slots__ = ['type', 'default', 'label', 'desc', 'name', 'choices']
|
||||||
|
|
||||||
|
def __init__(self, name, type_, default, label, desc, choices=None):
|
||||||
|
'''
|
||||||
|
:param name: The name of this option. Must be a valid python identifier
|
||||||
|
:param type_: The type of this option, one of ('number', 'string',
|
||||||
|
'bool', 'choices')
|
||||||
|
:param default: The default value for this option
|
||||||
|
:param label: A short (few words) description of this option
|
||||||
|
:param desc: A longer description of this option
|
||||||
|
:param choices: A list of possible values, used only if type='choices'
|
||||||
|
'''
|
||||||
|
self.name, self.type, self.default, self.label, self.desc = (name,
|
||||||
|
type_, default, label, desc)
|
||||||
|
self.choices = choices
|
||||||
|
|
||||||
class Source(Plugin):
|
class Source(Plugin):
|
||||||
|
|
||||||
@ -158,10 +173,14 @@ class Source(Plugin):
|
|||||||
supports_gzip_transfer_encoding = False
|
supports_gzip_transfer_encoding = False
|
||||||
|
|
||||||
#: Cached cover URLs can sometimes be unreliable (i.e. the download could
|
#: Cached cover URLs can sometimes be unreliable (i.e. the download could
|
||||||
#: fail or the returned image could be bogus. If that is the case set this to
|
#: fail or the returned image could be bogus. If that is often the case
|
||||||
#: False
|
#: with this source set to False
|
||||||
cached_cover_url_is_reliable = True
|
cached_cover_url_is_reliable = True
|
||||||
|
|
||||||
|
#: A list of :class:`Option` objects. They will be used to automatically
|
||||||
|
#: construct the configuration widget for this plugin
|
||||||
|
options = ()
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
Plugin.__init__(self, *args, **kwargs)
|
Plugin.__init__(self, *args, **kwargs)
|
||||||
@ -170,6 +189,9 @@ class Source(Plugin):
|
|||||||
self.cache_lock = threading.RLock()
|
self.cache_lock = threading.RLock()
|
||||||
self._config_obj = None
|
self._config_obj = None
|
||||||
self._browser = None
|
self._browser = None
|
||||||
|
self.prefs.defaults['ignore_fields'] = []
|
||||||
|
for opt in self.options:
|
||||||
|
self.prefs.defaults[opt.name] = opt.default
|
||||||
|
|
||||||
# Configuration {{{
|
# Configuration {{{
|
||||||
|
|
||||||
@ -180,6 +202,16 @@ class Source(Plugin):
|
|||||||
'''
|
'''
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def is_customizable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def config_widget(self):
|
||||||
|
from calibre.gui2.metadata.config import ConfigWidget
|
||||||
|
return ConfigWidget(self)
|
||||||
|
|
||||||
|
def save_settings(self, config_widget):
|
||||||
|
config_widget.commit()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def prefs(self):
|
def prefs(self):
|
||||||
if self._config_obj is None:
|
if self._config_obj is None:
|
||||||
|
@ -12,7 +12,7 @@ from calibre.ebooks.metadata.sources.base import Source
|
|||||||
class OpenLibrary(Source):
|
class OpenLibrary(Source):
|
||||||
|
|
||||||
name = 'Open Library'
|
name = 'Open Library'
|
||||||
description = _('Downloads metadata from The Open Library')
|
description = _('Downloads covers from The Open Library')
|
||||||
|
|
||||||
capabilities = frozenset(['cover'])
|
capabilities = frozenset(['cover'])
|
||||||
|
|
||||||
|
@ -9,14 +9,15 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
from PyQt4.Qt import (QAbstractTableModel, Qt, QAbstractListModel)
|
from PyQt4.Qt import (QAbstractTableModel, Qt, QAbstractListModel, QWidget,
|
||||||
|
pyqtSignal, QVBoxLayout, QDialogButtonBox, QFrame, QLabel)
|
||||||
|
|
||||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
||||||
from calibre.gui2.preferences.metadata_sources_ui import Ui_Form
|
from calibre.gui2.preferences.metadata_sources_ui import Ui_Form
|
||||||
from calibre.ebooks.metadata.sources.base import msprefs
|
from calibre.ebooks.metadata.sources.base import msprefs
|
||||||
from calibre.customize.ui import (all_metadata_plugins, is_disabled,
|
from calibre.customize.ui import (all_metadata_plugins, is_disabled,
|
||||||
enable_plugin, disable_plugin, default_disabled_plugins)
|
enable_plugin, disable_plugin, default_disabled_plugins)
|
||||||
from calibre.gui2 import NONE
|
from calibre.gui2 import NONE, error_dialog
|
||||||
|
|
||||||
class SourcesModel(QAbstractTableModel): # {{{
|
class SourcesModel(QAbstractTableModel): # {{{
|
||||||
|
|
||||||
@ -64,7 +65,8 @@ class SourcesModel(QAbstractTableModel): # {{{
|
|||||||
elif role == Qt.CheckStateRole and col == 0:
|
elif role == Qt.CheckStateRole and col == 0:
|
||||||
orig = Qt.Unchecked if is_disabled(plugin) else Qt.Checked
|
orig = Qt.Unchecked if is_disabled(plugin) else Qt.Checked
|
||||||
return self.enabled_overrides.get(plugin, orig)
|
return self.enabled_overrides.get(plugin, orig)
|
||||||
|
elif role == Qt.UserRole:
|
||||||
|
return plugin
|
||||||
return NONE
|
return NONE
|
||||||
|
|
||||||
def setData(self, index, val, role):
|
def setData(self, index, val, role):
|
||||||
@ -127,6 +129,7 @@ class SourcesModel(QAbstractTableModel): # {{{
|
|||||||
|
|
||||||
class FieldsModel(QAbstractListModel): # {{{
|
class FieldsModel(QAbstractListModel): # {{{
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QAbstractTableModel.__init__(self, parent)
|
QAbstractTableModel.__init__(self, parent)
|
||||||
|
|
||||||
@ -143,6 +146,7 @@ class FieldsModel(QAbstractListModel): # {{{
|
|||||||
'language': _('Language'),
|
'language': _('Language'),
|
||||||
}
|
}
|
||||||
self.overrides = {}
|
self.overrides = {}
|
||||||
|
self.exclude = frozenset(['series_index'])
|
||||||
|
|
||||||
def rowCount(self, parent=None):
|
def rowCount(self, parent=None):
|
||||||
return len(self.fields)
|
return len(self.fields)
|
||||||
@ -153,7 +157,7 @@ class FieldsModel(QAbstractListModel): # {{{
|
|||||||
fields |= p.touched_fields
|
fields |= p.touched_fields
|
||||||
self.fields = []
|
self.fields = []
|
||||||
for x in fields:
|
for x in fields:
|
||||||
if not x.startswith('identifier:') and x not in ('series_index',):
|
if not x.startswith('identifier:') and x not in self.exclude:
|
||||||
self.fields.append(x)
|
self.fields.append(x)
|
||||||
self.fields.sort(key=lambda x:self.descs.get(x, x))
|
self.fields.sort(key=lambda x:self.descs.get(x, x))
|
||||||
self.reset()
|
self.reset()
|
||||||
@ -204,6 +208,41 @@ class FieldsModel(QAbstractListModel): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
class PluginConfig(QWidget): # {{{
|
||||||
|
|
||||||
|
finished = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, plugin, parent):
|
||||||
|
QWidget.__init__(self, parent)
|
||||||
|
|
||||||
|
self.plugin = plugin
|
||||||
|
|
||||||
|
self.l = l = QVBoxLayout()
|
||||||
|
self.setLayout(l)
|
||||||
|
self.c = c = QLabel(_('<b>Configure %s</b><br>%s') % (plugin.name,
|
||||||
|
plugin.description))
|
||||||
|
c.setAlignment(Qt.AlignHCenter)
|
||||||
|
l.addWidget(c)
|
||||||
|
|
||||||
|
self.config_widget = plugin.config_widget()
|
||||||
|
self.l.addWidget(self.config_widget)
|
||||||
|
|
||||||
|
self.bb = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.Save|QDialogButtonBox.Cancel,
|
||||||
|
parent=self)
|
||||||
|
self.bb.accepted.connect(self.finished)
|
||||||
|
self.bb.rejected.connect(self.finished)
|
||||||
|
self.bb.accepted.connect(self.commit)
|
||||||
|
l.addWidget(self.bb)
|
||||||
|
|
||||||
|
self.f = QFrame(self)
|
||||||
|
self.f.setFrameShape(QFrame.HLine)
|
||||||
|
l.addWidget(self.f)
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
self.plugin.save_settings(self.config_widget)
|
||||||
|
# }}}
|
||||||
|
|
||||||
class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||||
|
|
||||||
def genesis(self, gui):
|
def genesis(self, gui):
|
||||||
@ -223,7 +262,27 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.fields_model.dataChanged.connect(self.changed_signal)
|
self.fields_model.dataChanged.connect(self.changed_signal)
|
||||||
|
|
||||||
def configure_plugin(self):
|
def configure_plugin(self):
|
||||||
pass
|
for index in self.sources_view.selectionModel().selectedRows():
|
||||||
|
plugin = self.sources_model.data(index, Qt.UserRole)
|
||||||
|
if plugin is not NONE:
|
||||||
|
return self.do_config(plugin)
|
||||||
|
error_dialog(self, _('No source selected'),
|
||||||
|
_('No source selected, cannot configure.'), show=True)
|
||||||
|
|
||||||
|
def do_config(self, plugin):
|
||||||
|
self.pc = PluginConfig(plugin, self)
|
||||||
|
self.stack.insertWidget(1, self.pc)
|
||||||
|
self.stack.setCurrentIndex(1)
|
||||||
|
self.pc.finished.connect(self.pc_finished)
|
||||||
|
|
||||||
|
def pc_finished(self):
|
||||||
|
try:
|
||||||
|
self.pc.finished.diconnect()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.stack.setCurrentIndex(0)
|
||||||
|
self.stack.removeWidget(self.pc)
|
||||||
|
self.pc = None
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
ConfigWidgetBase.initialize(self)
|
ConfigWidgetBase.initialize(self)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user