mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-12-20 12:05:03 -05:00
318 lines
10 KiB
Python
318 lines
10 KiB
Python
#!/usr/bin/env python
|
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
|
from __future__ import (unicode_literals, division, absolute_import,
|
|
print_function)
|
|
|
|
__license__ = 'GPL v3'
|
|
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
|
__docformat__ = 'restructuredtext en'
|
|
|
|
from operator import attrgetter
|
|
|
|
from PyQt4.Qt import (QAbstractTableModel, Qt, QAbstractListModel, QWidget,
|
|
pyqtSignal, QVBoxLayout, QDialogButtonBox, QFrame, QLabel, QIcon)
|
|
|
|
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
|
from calibre.gui2.preferences.metadata_sources_ui import Ui_Form
|
|
from calibre.ebooks.metadata.sources.base import msprefs
|
|
from calibre.customize.ui import (all_metadata_plugins, is_disabled,
|
|
enable_plugin, disable_plugin, default_disabled_plugins)
|
|
from calibre.gui2 import NONE, error_dialog
|
|
|
|
class SourcesModel(QAbstractTableModel): # {{{
|
|
|
|
def __init__(self, parent=None):
|
|
QAbstractTableModel.__init__(self, parent)
|
|
|
|
self.plugins = []
|
|
self.enabled_overrides = {}
|
|
self.cover_overrides = {}
|
|
|
|
def initialize(self):
|
|
self.plugins = list(all_metadata_plugins())
|
|
self.plugins.sort(key=attrgetter('name'))
|
|
self.enabled_overrides = {}
|
|
self.cover_overrides = {}
|
|
self.reset()
|
|
|
|
def rowCount(self, parent=None):
|
|
return len(self.plugins)
|
|
|
|
def columnCount(self, parent=None):
|
|
return 2
|
|
|
|
def headerData(self, section, orientation, role):
|
|
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
|
if section == 0:
|
|
return _('Source')
|
|
if section == 1:
|
|
return _('Cover priority')
|
|
return NONE
|
|
|
|
def data(self, index, role):
|
|
try:
|
|
plugin = self.plugins[index.row()]
|
|
except:
|
|
return NONE
|
|
col = index.column()
|
|
|
|
if role == Qt.DisplayRole:
|
|
if col == 0:
|
|
return plugin.name
|
|
elif col == 1:
|
|
orig = msprefs['cover_priorities'].get(plugin.name, 1)
|
|
return self.cover_overrides.get(plugin, orig)
|
|
elif role == Qt.CheckStateRole and col == 0:
|
|
orig = Qt.Unchecked if is_disabled(plugin) else Qt.Checked
|
|
return self.enabled_overrides.get(plugin, orig)
|
|
elif role == Qt.UserRole:
|
|
return plugin
|
|
elif (role == Qt.DecorationRole and col == 0 and not
|
|
plugin.is_configured()):
|
|
return QIcon(I('list_remove.png'))
|
|
elif role == Qt.ToolTipRole:
|
|
if plugin.is_configured():
|
|
return _('This source is configured and ready to go')
|
|
return _('This source needs configuration')
|
|
return NONE
|
|
|
|
def setData(self, index, val, role):
|
|
try:
|
|
plugin = self.plugins[index.row()]
|
|
except:
|
|
return False
|
|
col = index.column()
|
|
ret = False
|
|
if col == 0 and role == Qt.CheckStateRole:
|
|
val, ok = val.toInt()
|
|
if ok:
|
|
self.enabled_overrides[plugin] = val
|
|
ret = True
|
|
if col == 1 and role == Qt.EditRole:
|
|
val, ok = val.toInt()
|
|
if ok:
|
|
self.cover_overrides[plugin] = val
|
|
ret = True
|
|
if ret:
|
|
self.dataChanged.emit(index, index)
|
|
return ret
|
|
|
|
|
|
def flags(self, index):
|
|
col = index.column()
|
|
ans = QAbstractTableModel.flags(self, index)
|
|
if col == 0:
|
|
return ans | Qt.ItemIsUserCheckable
|
|
return Qt.ItemIsEditable | ans
|
|
|
|
def commit(self):
|
|
for plugin, val in self.enabled_overrides.iteritems():
|
|
if val == Qt.Checked:
|
|
enable_plugin(plugin)
|
|
elif val == Qt.Unchecked:
|
|
disable_plugin(plugin)
|
|
|
|
if self.cover_overrides:
|
|
cp = msprefs['cover_priorities']
|
|
for plugin, val in self.cover_overrides.iteritems():
|
|
if val == 1:
|
|
cp.pop(plugin.name, None)
|
|
else:
|
|
cp[plugin.name] = val
|
|
msprefs['cover_priorities'] = cp
|
|
|
|
self.enabled_overrides = {}
|
|
self.cover_overrides = {}
|
|
|
|
def restore_defaults(self):
|
|
self.enabled_overrides = dict([(p, (Qt.Unchecked if p.name in
|
|
default_disabled_plugins else Qt.Checked)) for p in self.plugins])
|
|
self.cover_overrides = dict([(p,
|
|
msprefs.defaults['cover_priorities'].get(p.name, 1))
|
|
for p in self.plugins])
|
|
self.reset()
|
|
|
|
# }}}
|
|
|
|
class FieldsModel(QAbstractListModel): # {{{
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
QAbstractTableModel.__init__(self, parent)
|
|
|
|
self.fields = []
|
|
self.descs = {
|
|
'authors': _('Authors'),
|
|
'comments': _('Comments'),
|
|
'pubdate': _('Published date'),
|
|
'publisher': _('Publisher'),
|
|
'rating' : _('Rating'),
|
|
'tags' : _('Tags'),
|
|
'title': _('Title'),
|
|
'series': _('Series'),
|
|
'language': _('Language'),
|
|
}
|
|
self.overrides = {}
|
|
self.exclude = frozenset(['series_index'])
|
|
|
|
def rowCount(self, parent=None):
|
|
return len(self.fields)
|
|
|
|
def initialize(self):
|
|
fields = set()
|
|
for p in all_metadata_plugins():
|
|
fields |= p.touched_fields
|
|
self.fields = []
|
|
for x in fields:
|
|
if not x.startswith('identifier:') and x not in self.exclude:
|
|
self.fields.append(x)
|
|
self.fields.sort(key=lambda x:self.descs.get(x, x))
|
|
self.reset()
|
|
|
|
def state(self, field, defaults=False):
|
|
src = msprefs.defaults if defaults else msprefs
|
|
return (Qt.Unchecked if field in src['ignore_fields']
|
|
else Qt.Checked)
|
|
|
|
def data(self, index, role):
|
|
try:
|
|
field = self.fields[index.row()]
|
|
except:
|
|
return None
|
|
if role == Qt.DisplayRole:
|
|
return self.descs.get(field, field)
|
|
if role == Qt.CheckStateRole:
|
|
return self.overrides.get(field, self.state(field))
|
|
return NONE
|
|
|
|
def flags(self, index):
|
|
ans = QAbstractTableModel.flags(self, index)
|
|
return ans | Qt.ItemIsUserCheckable
|
|
|
|
def restore_defaults(self):
|
|
self.overrides = dict([(f, self.state(f, True)) for f in self.fields])
|
|
self.reset()
|
|
|
|
def setData(self, index, val, role):
|
|
try:
|
|
field = self.fields[index.row()]
|
|
except:
|
|
return False
|
|
ret = False
|
|
if role == Qt.CheckStateRole:
|
|
val, ok = val.toInt()
|
|
if ok:
|
|
self.overrides[field] = val
|
|
ret = True
|
|
if ret:
|
|
self.dataChanged.emit(index, index)
|
|
return ret
|
|
|
|
def commit(self):
|
|
val = [k for k, v in self.overrides.iteritems() if v == Qt.Unchecked]
|
|
msprefs['ignore_fields'] = val
|
|
|
|
|
|
# }}}
|
|
|
|
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):
|
|
|
|
def genesis(self, gui):
|
|
r = self.register
|
|
r('txt_comments', msprefs)
|
|
r('max_tags', msprefs)
|
|
r('wait_after_first_identify_result', msprefs)
|
|
r('wait_after_first_cover_result', msprefs)
|
|
r('swap_author_names', msprefs)
|
|
r('fewer_tags', msprefs)
|
|
|
|
self.configure_plugin_button.clicked.connect(self.configure_plugin)
|
|
self.sources_model = SourcesModel(self)
|
|
self.sources_view.setModel(self.sources_model)
|
|
self.sources_model.dataChanged.connect(self.changed_signal)
|
|
|
|
self.fields_model = FieldsModel(self)
|
|
self.fields_view.setModel(self.fields_model)
|
|
self.fields_model.dataChanged.connect(self.changed_signal)
|
|
|
|
def configure_plugin(self):
|
|
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):
|
|
ConfigWidgetBase.initialize(self)
|
|
self.sources_model.initialize()
|
|
self.sources_view.resizeColumnsToContents()
|
|
self.fields_model.initialize()
|
|
|
|
def restore_defaults(self):
|
|
ConfigWidgetBase.restore_defaults(self)
|
|
self.sources_model.restore_defaults()
|
|
self.fields_model.restore_defaults()
|
|
self.changed_signal.emit()
|
|
|
|
def commit(self):
|
|
self.sources_model.commit()
|
|
self.fields_model.commit()
|
|
return ConfigWidgetBase.commit(self)
|
|
|
|
if __name__ == '__main__':
|
|
from PyQt4.Qt import QApplication
|
|
app = QApplication([])
|
|
test_widget('Sharing', 'Metadata download')
|
|
|