diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index 1348da5e5a..ea11259da2 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -351,3 +351,6 @@ class CatalogPlugin(Plugin): # Default implementation does nothing raise NotImplementedError('CatalogPlugin.generate_catalog() default ' 'method, should be overridden in subclass') + +class InterfaceActionBase(Plugin): + pass diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py index 7b70bfbb4b..b720964c92 100644 --- a/src/calibre/customize/ui.py +++ b/src/calibre/customize/ui.py @@ -6,7 +6,8 @@ import os, shutil, traceback, functools, sys, re from contextlib import closing from calibre.customize import Plugin, CatalogPlugin, FileTypePlugin, \ - MetadataReaderPlugin, MetadataWriterPlugin + MetadataReaderPlugin, MetadataWriterPlugin, \ + InterfaceActionBase as InterfaceAction from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin from calibre.customize.profiles import InputProfile, OutputProfile from calibre.customize.builtins import plugins as builtin_plugins @@ -19,7 +20,6 @@ from calibre.utils.config import make_config_dir, Config, ConfigProxy, \ plugin_dir, OptionParser, prefs from calibre.ebooks.epub.fix import ePubFixer - platform = 'linux' if iswindows: platform = 'windows' @@ -246,6 +246,17 @@ def cover_sources(): # }}} +# Interface Actions # {{{ + +def interface_actions(): + customization = config['plugin_customization'] + for plugin in _initialized_plugins: + if isinstance(plugin, InterfaceAction): + if not is_disabled(plugin): + plugin.site_customization = customization.get(plugin.name, '') + yield plugin +# }}} + # Metadata read/write {{{ _metadata_readers = {} _metadata_writers = {} diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 686d705abb..062e4eeab9 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -244,14 +244,20 @@ def info_dialog(parent, title, msg, det_msg='', show=False): class Dispatcher(QObject): - '''Convenience class to ensure that a function call always happens in the - thread the receiver was created in.''' + ''' + Convenience class to use Qt signals with arbitrary python callables. + By default, ensures that a function call always happens in the + thread this Dispatcher was created in. + ''' dispatch_signal = pyqtSignal(object, object) - def __init__(self, func): - QObject.__init__(self) + def __init__(self, func, queued=True, parent=None): + QObject.__init__(self, parent) self.func = func - self.dispatch_signal.connect(self.dispatch, type=Qt.QueuedConnection) + typ = Qt.QueuedConnection + if not queued: + typ = Qt.AutoConnection if queued is None else Qt.DirectConnection + self.dispatch_signal.connect(self.dispatch, type=typ) def __call__(self, *args, **kwargs): self.dispatch_signal.emit(args, kwargs) diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 96aaa843a0..5c1f2d1535 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -6,6 +6,23 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from calibre.customize import InterfaceActionBase +class InterfaceAction(InterfaceActionBase): + supported_platforms = ['windows', 'osx', 'linux'] + author = 'Kovid Goyal' + type = _('User Interface Action') + + positions = frozenset([]) + separators = frozenset([]) + + def do_genesis(self, gui): + self.gui = gui + self.genesis() + + # Subclassable methods {{{ + def genesis(self): + raise NotImplementedError() + # }}} diff --git a/src/calibre/gui2/actions/add.py b/src/calibre/gui2/actions/add.py index 18a9a4224b..b7be89360f 100644 --- a/src/calibre/gui2/actions/add.py +++ b/src/calibre/gui2/actions/add.py @@ -17,12 +17,14 @@ from calibre.gui2.widgets import IMAGE_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS from calibre.utils.filenames import ascii_filename from calibre.constants import preferred_encoding, filesystem_encoding +from calibre.gui2.actions import InterfaceAction +class AddAction(InterfaceAction): -class AddAction(object): + def genesis(self): + self._add_filesystem_book = Dispatcher(self.__add_filesystem_book, + parent=self.gui) - def __init__(self): - self._add_filesystem_book = Dispatcher(self.__add_filesystem_book) def add_recursive(self, single): root = choose_dir(self, 'recursive book import root dir dialog', diff --git a/src/calibre/manual/plugins.rst b/src/calibre/manual/plugins.rst index 26e544d766..8b6919db90 100644 --- a/src/calibre/manual/plugins.rst +++ b/src/calibre/manual/plugins.rst @@ -157,4 +157,11 @@ The base class for such devices is :class:`calibre.devices.usbms.driver.USBMS`. :members: :member-order: bysource +User Interface Actions +-------------------------- + +.. autoclass:: calibre.gui2.actions.InterfaceAction + :show-inheritance: + :members: + :member-order: bysource