mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Framework for plugin based preferences dialog
This commit is contained in:
parent
81f081527d
commit
19bcbb713f
@ -8,7 +8,7 @@ from calibre.constants import numeric_version
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class Plugin(object):
|
||||
class Plugin(object): # {{{
|
||||
'''
|
||||
A calibre plugin. Useful members include:
|
||||
|
||||
@ -147,9 +147,9 @@ class Plugin(object):
|
||||
if hasattr(it, '__exit__'):
|
||||
it.__exit__(*args)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
class FileTypePlugin(Plugin):
|
||||
class FileTypePlugin(Plugin): # {{{
|
||||
'''
|
||||
A plugin that is associated with a particular set of file types.
|
||||
'''
|
||||
@ -191,7 +191,9 @@ class FileTypePlugin(Plugin):
|
||||
# Default implementation does nothing
|
||||
return path_to_ebook
|
||||
|
||||
class MetadataReaderPlugin(Plugin):
|
||||
# }}}
|
||||
|
||||
class MetadataReaderPlugin(Plugin): # {{{
|
||||
'''
|
||||
A plugin that implements reading metadata from a set of file types.
|
||||
'''
|
||||
@ -219,8 +221,9 @@ class MetadataReaderPlugin(Plugin):
|
||||
:return: A :class:`calibre.ebooks.metadata.MetaInformation` object
|
||||
'''
|
||||
return None
|
||||
# }}}
|
||||
|
||||
class MetadataWriterPlugin(Plugin):
|
||||
class MetadataWriterPlugin(Plugin): # {{{
|
||||
'''
|
||||
A plugin that implements reading metadata from a set of file types.
|
||||
'''
|
||||
@ -249,7 +252,9 @@ class MetadataWriterPlugin(Plugin):
|
||||
'''
|
||||
pass
|
||||
|
||||
class CatalogPlugin(Plugin):
|
||||
# }}}
|
||||
|
||||
class CatalogPlugin(Plugin): # {{{
|
||||
'''
|
||||
A plugin that implements a catalog generator.
|
||||
'''
|
||||
@ -352,7 +357,9 @@ class CatalogPlugin(Plugin):
|
||||
raise NotImplementedError('CatalogPlugin.generate_catalog() default '
|
||||
'method, should be overridden in subclass')
|
||||
|
||||
class InterfaceActionBase(Plugin):
|
||||
# }}}
|
||||
|
||||
class InterfaceActionBase(Plugin): # {{{
|
||||
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
author = 'Kovid Goyal'
|
||||
@ -360,3 +367,44 @@ class InterfaceActionBase(Plugin):
|
||||
can_be_disabled = False
|
||||
|
||||
actual_plugin = None
|
||||
# }}}
|
||||
|
||||
class PreferencesPlugin(Plugin): # {{{
|
||||
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
author = 'Kovid Goyal'
|
||||
type = _('Preferences')
|
||||
can_be_disabled = False
|
||||
|
||||
#: Import path to module that contains a class named ConfigWidget
|
||||
#: which implements the ConfigWidgetInterface. Used by
|
||||
#: :meth:`create_widget`.
|
||||
config_widget = None
|
||||
|
||||
#: Where in the list of categories the :attr:`category` of this plugin should be.
|
||||
category_order = 100
|
||||
|
||||
#: Where in the list of names in a category, the :attr:`gui_name` of this
|
||||
#: plugin should be
|
||||
name_order = 100
|
||||
|
||||
#: The category this plugin should be in
|
||||
category = None
|
||||
|
||||
#: The name displayed to the user for this plugin
|
||||
gui_name = None
|
||||
|
||||
def create_widget(self, parent=None):
|
||||
'''
|
||||
Create and return the actual Qt widget used for setting this group of
|
||||
preferences. The widget must implement the ConfigWidgetInterface.
|
||||
|
||||
The default implementation uses :attr:`config_widget` to instantiate
|
||||
the widget.
|
||||
'''
|
||||
base = __import__(self.config_widget, fromlist=[1])
|
||||
widget = base.ConfigWidget(parent)
|
||||
return widget
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -7,7 +7,8 @@ from contextlib import closing
|
||||
|
||||
from calibre.customize import Plugin, CatalogPlugin, FileTypePlugin, \
|
||||
MetadataReaderPlugin, MetadataWriterPlugin, \
|
||||
InterfaceActionBase as InterfaceAction
|
||||
InterfaceActionBase as InterfaceAction, \
|
||||
PreferencesPlugin
|
||||
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||
from calibre.customize.builtins import plugins as builtin_plugins
|
||||
@ -257,6 +258,17 @@ def interface_actions():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Preferences Plugins # {{{
|
||||
|
||||
def preferences_plugins():
|
||||
customization = config['plugin_customization']
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, PreferencesPlugin):
|
||||
if not is_disabled(plugin):
|
||||
plugin.site_customization = customization.get(plugin.name, '')
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Metadata read/write {{{
|
||||
_metadata_readers = {}
|
||||
_metadata_writers = {}
|
||||
|
@ -7,28 +7,67 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
from PyQt4.Qt import QWidget, pyqtSignal
|
||||
|
||||
class PreferenceWidget(QWidget):
|
||||
from calibre.customize.ui import preferences_plugins
|
||||
|
||||
category = None
|
||||
name = None
|
||||
class ConfigWidgetInterface(object):
|
||||
|
||||
changed_signal = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
|
||||
self.has_changed = False
|
||||
self.changed.connect(lambda : setattr(self, 'has_changed', True))
|
||||
self.setupUi(self)
|
||||
changed_signal = None
|
||||
|
||||
def genesis(self, gui):
|
||||
raise NotImplementedError()
|
||||
|
||||
def reset_to_defaults(self):
|
||||
def restore_defaults(self):
|
||||
pass
|
||||
|
||||
def commit(self):
|
||||
pass
|
||||
|
||||
def add_boolean(self, widget_name, preference_interface, pref_name):
|
||||
pass
|
||||
|
||||
class ConfigWidgetBase(QWidget, ConfigWidgetInterface):
|
||||
|
||||
changed_signal = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
if hasattr(self, 'setupUi'):
|
||||
self.setupUi(self)
|
||||
|
||||
def get_plugin(category, name):
|
||||
for plugin in preferences_plugins():
|
||||
if plugin.category == category and plugin.name == name:
|
||||
return plugin
|
||||
raise ValueError(
|
||||
'No Preferences PLugin with category: %s and name: %s found' %
|
||||
(category, name))
|
||||
|
||||
def test_widget(category, name, gui=None): # {{{
|
||||
from PyQt4.Qt import QDialog, QVBoxLayout, QDialogButtonBox
|
||||
pl = get_plugin(category, name)
|
||||
d = QDialog()
|
||||
d.resize(750, 550)
|
||||
bb = QDialogButtonBox(d)
|
||||
bb.setStandardButtons(bb.Apply|bb.Cancel|bb.RestoreDefaults)
|
||||
bb.accepted.connect(d.accept)
|
||||
bb.rejected.connect(d.reject)
|
||||
w = pl.create_widget(d)
|
||||
bb.button(bb.RestoreDefaults).clicked.connect(w.restore_defaults)
|
||||
bb.button(bb.Apply).setEnabled(False)
|
||||
w.changed_signal.connect(lambda : bb.button(bb.Apply).setEnable(True))
|
||||
l = QVBoxLayout()
|
||||
pl.setLayout(l)
|
||||
l.addWidget(w)
|
||||
if gui is None:
|
||||
from calibre.gui2.ui import Main
|
||||
from calibre.gui2.main import option_parser
|
||||
from calibre.library.db import db
|
||||
parser = option_parser()
|
||||
opts, args = parser.parse_args([])
|
||||
actions = tuple(Main.create_application_menubar())
|
||||
db = db()
|
||||
gui = Main(opts)
|
||||
gui.initialize(db.library_path, db, None, actions)
|
||||
w.genesis(gui)
|
||||
if d.exec_() == QDialog.Accepted:
|
||||
w.commit()
|
||||
# }}}
|
||||
|
||||
|
@ -50,6 +50,8 @@ class Listener(Thread): # {{{
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
if self.listener is None:
|
||||
return
|
||||
while self._run:
|
||||
try:
|
||||
conn = self.listener.accept()
|
||||
|
Loading…
x
Reference in New Issue
Block a user