This commit is contained in:
Kovid Goyal 2011-04-10 21:15:20 -06:00
parent 385986fe4b
commit f628964592
3 changed files with 99 additions and 8 deletions

View File

@ -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:

View File

@ -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'])

View File

@ -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)