Migrate Fetch Annotations action and refactor plugins so as to delay load the gui components

This commit is contained in:
Kovid Goyal 2010-08-12 12:12:16 -06:00
parent 82dc900a11
commit 206547021d
6 changed files with 80 additions and 40 deletions

View File

@ -353,4 +353,10 @@ class CatalogPlugin(Plugin):
'method, should be overridden in subclass') 'method, should be overridden in subclass')
class InterfaceActionBase(Plugin): class InterfaceActionBase(Plugin):
pass
supported_platforms = ['windows', 'osx', 'linux']
author = 'Kovid Goyal'
type = _('User Interface Action')
can_be_disabled = False
actual_plugin = None

View File

@ -574,3 +574,15 @@ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataWriter')] x.__name__.endswith('MetadataWriter')]
plugins += input_profiles + output_profiles plugins += input_profiles + output_profiles
from calibre.customize import InterfaceActionBase
class ActionAdd(InterfaceActionBase):
name = 'action_add'
actual_plugin = 'calibre.gui2.actions.add:AddAction'
class ActionFetchAnnotations(InterfaceActionBase):
name = 'action_fetch_annotations'
actual_plugin = 'calibre.gui2.actions.annotate:FetchAnnotationsAction'
plugins += [ActionAdd, ActionFetchAnnotations]

View File

@ -7,17 +7,14 @@ __docformat__ = 'restructuredtext en'
from functools import partial from functools import partial
from PyQt4.Qt import QToolButton, QAction, QIcon from PyQt4.Qt import QToolButton, QAction, QIcon, QObject
from calibre.customize import InterfaceActionBase
from calibre.gui2 import Dispatcher from calibre.gui2 import Dispatcher
class InterfaceAction(InterfaceActionBase): class InterfaceAction(QObject):
supported_platforms = ['windows', 'osx', 'linux']
author = 'Kovid Goyal'
type = _('User Interface Action')
name = 'Implement me'
priority = 1
positions = frozenset([]) positions = frozenset([])
separators = frozenset([]) separators = frozenset([])
@ -28,15 +25,22 @@ class InterfaceAction(InterfaceActionBase):
#: shortcut must be a translated string if not None #: shortcut must be a translated string if not None
action_spec = ('text', 'icon', None, None) action_spec = ('text', 'icon', None, None)
def do_genesis(self, gui): def __init__(self, parent, site_customization):
self.gui = gui QObject.__init__(self, parent)
self.Dispatcher = partial(Dispatcher, parent=gui) self.gui = parent
self.site_customization = site_customization
def do_genesis(self):
self.Dispatcher = partial(Dispatcher, parent=self)
self.create_action() self.create_action()
self.genesis() self.genesis()
def create_action(self): def create_action(self):
text, icon, tooltip, shortcut = self.action_spec text, icon, tooltip, shortcut = self.action_spec
action = QAction(QIcon(I(icon)), text, self) if icon is not None:
action = QAction(QIcon(I(icon)), text, self.gui)
else:
action = QAction(text, self.gui)
text = tooltip if tooltip else text text = tooltip if tooltip else text
action.setToolTip(text) action.setToolTip(text)
action.setStatusTip(text) action.setStatusTip(text)

View File

@ -9,19 +9,26 @@ import os, datetime
from PyQt4.Qt import pyqtSignal, QModelIndex, QThread, Qt from PyQt4.Qt import pyqtSignal, QModelIndex, QThread, Qt
from calibre.gui2 import error_dialog, Dispatcher, gprefs from calibre.gui2 import error_dialog, gprefs
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString
from calibre import strftime from calibre import strftime
from calibre.gui2.actions import InterfaceAction
class AnnotationsAction(object): class FetchAnnotationsAction(InterfaceAction):
name = 'Fetch Annotations'
action_spec = (_('Fetch Annotations'), None, None, None)
def genesis(self):
pass
def fetch_annotations(self, *args): def fetch_annotations(self, *args):
# Generate a path_map from selected ids # Generate a path_map from selected ids
def get_ids_from_selected_rows(): def get_ids_from_selected_rows():
rows = self.library_view.selectionModel().selectedRows() rows = self.gui.library_view.selectionModel().selectedRows()
if not rows or len(rows) < 2: if not rows or len(rows) < 2:
rows = xrange(self.library_view.model().rowCount(QModelIndex())) rows = xrange(self.gui.library_view.model().rowCount(QModelIndex()))
ids = map(self.library_view.model().id, rows) ids = map(self.gui.library_view.model().id, rows)
return ids return ids
def get_formats(id): def get_formats(id):
@ -42,18 +49,18 @@ class AnnotationsAction(object):
path_map[id] = dict(path=a_path, fmts=get_formats(id)) path_map[id] = dict(path=a_path, fmts=get_formats(id))
return path_map return path_map
device = self.device_manager.device device = self.gui.device_manager.device
if self.current_view() is not self.library_view: if self.gui.current_view() is not self.gui.library_view:
return error_dialog(self, _('Use library only'), return error_dialog(self.gui, _('Use library only'),
_('User annotations generated from main library only'), _('User annotations generated from main library only'),
show=True) show=True)
db = self.library_view.model().db db = self.gui.library_view.model().db
# Get the list of ids # Get the list of ids
ids = get_ids_from_selected_rows() ids = get_ids_from_selected_rows()
if not ids: if not ids:
return error_dialog(self, _('No books selected'), return error_dialog(self.gui, _('No books selected'),
_('No books selected to fetch annotations from'), _('No books selected to fetch annotations from'),
show=True) show=True)
@ -61,7 +68,7 @@ class AnnotationsAction(object):
path_map = generate_annotation_paths(ids, db, device) path_map = generate_annotation_paths(ids, db, device)
# Dispatch to devices.kindle.driver.get_annotations() # Dispatch to devices.kindle.driver.get_annotations()
self.device_manager.annotations(Dispatcher(self.annotations_fetched), self.gui.device_manager.annotations(self.Dispatcher(self.annotations_fetched),
path_map) path_map)
def annotations_fetched(self, job): def annotations_fetched(self, job):
@ -70,7 +77,7 @@ class AnnotationsAction(object):
from calibre.gui2.dialogs.progress import ProgressDialog from calibre.gui2.dialogs.progress import ProgressDialog
from calibre.library.cli import do_add_format from calibre.library.cli import do_add_format
class Updater(QThread): class Updater(QThread): # {{{
update_progress = pyqtSignal(int) update_progress = pyqtSignal(int)
update_done = pyqtSignal() update_done = pyqtSignal()
@ -220,16 +227,18 @@ class AnnotationsAction(object):
self.update_done.emit() self.update_done.emit()
self.done_callback(self.am.keys()) self.done_callback(self.am.keys())
# }}}
if not job.result: return if not job.result: return
if self.current_view() is not self.library_view: if self.gui.current_view() is not self.gui.library_view:
return error_dialog(self, _('Use library only'), return error_dialog(self.gui, _('Use library only'),
_('User annotations generated from main library only'), _('User annotations generated from main library only'),
show=True) show=True)
db = self.library_view.model().db db = self.gui.library_view.model().db
self.__annotation_updater = Updater(self, db, job.result, self.__annotation_updater = Updater(self.gui, db, job.result,
Dispatcher(self.library_view.model().refresh_ids)) self.Dispatcher(self.gui.library_view.model().refresh_ids))
self.__annotation_updater.start() self.__annotation_updater.start()

View File

@ -652,7 +652,8 @@ class DeviceMixin(object): # {{{
self.connect(self._sync_menu, self.connect(self._sync_menu,
SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
self.dispatch_sync_event) self.dispatch_sync_event)
self._sync_menu.fetch_annotations.connect(self.fetch_annotations) self._sync_menu.fetch_annotations.connect(
self.iactions['Fetch Annotations'].fetch_annotations)
self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device) self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device)
if self.device_connected: if self.device_connected:
self.share_conn_menu.connect_to_folder_action.setEnabled(False) self.share_conn_menu.connect_to_folder_action.setEnabled(False)

View File

@ -23,6 +23,8 @@ from calibre.constants import __appname__, isosx
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.config import prefs, dynamic from calibre.utils.config import prefs, dynamic
from calibre.utils.ipc.server import Server from calibre.utils.ipc.server import Server
from calibre.library.database2 import LibraryDatabase2
from calibre.customize import interface_actions
from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \ from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \
gprefs, max_available_height, config, info_dialog, Dispatcher gprefs, max_available_height, config, info_dialog, Dispatcher
from calibre.gui2.cover_flow import CoverFlowMixin from calibre.gui2.cover_flow import CoverFlowMixin
@ -33,16 +35,11 @@ from calibre.gui2.layout import MainWindowMixin
from calibre.gui2.device import DeviceMixin from calibre.gui2.device import DeviceMixin
from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton from calibre.gui2.jobs import JobManager, JobsDialog, JobsButton
from calibre.gui2.dialogs.config import ConfigDialog from calibre.gui2.dialogs.config import ConfigDialog
from calibre.gui2.dialogs.book_info import BookInfo from calibre.gui2.dialogs.book_info import BookInfo
from calibre.library.database2 import LibraryDatabase2
from calibre.gui2.init import LibraryViewMixin, LayoutMixin from calibre.gui2.init import LibraryViewMixin, LayoutMixin
from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin from calibre.gui2.search_box import SearchBoxMixin, SavedSearchBoxMixin
from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin from calibre.gui2.search_restriction_mixin import SearchRestrictionMixin
from calibre.gui2.tag_view import TagBrowserMixin from calibre.gui2.tag_view import TagBrowserMixin
from calibre.gui2.actions import AnnotationsAction, AddAction, DeleteAction, \
EditMetadataAction, SaveToDiskAction, GenerateCatalogAction, FetchNewsAction, \
ConvertAction, ViewAction
class Listener(Thread): # {{{ class Listener(Thread): # {{{
@ -91,16 +88,26 @@ class SystemTrayIcon(QSystemTrayIcon): # {{{
class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
TagBrowserMixin, CoverFlowMixin, LibraryViewMixin, SearchBoxMixin, TagBrowserMixin, CoverFlowMixin, LibraryViewMixin, SearchBoxMixin,
SavedSearchBoxMixin, SearchRestrictionMixin, LayoutMixin, UpdateMixin, SavedSearchBoxMixin, SearchRestrictionMixin, LayoutMixin, UpdateMixin
AnnotationsAction, AddAction, DeleteAction, ):
EditMetadataAction, SaveToDiskAction, GenerateCatalogAction, FetchNewsAction,
ConvertAction, ViewAction):
'The main GUI' 'The main GUI'
def __init__(self, opts, parent=None): def __init__(self, opts, parent=None):
MainWindow.__init__(self, opts, parent) MainWindow.__init__(self, opts, parent)
self.opts = opts self.opts = opts
acmap = {}
for action in interface_actions():
mod, cls = action.actual_plugin.split(':')
ac = getattr(__import__(mod, fromlist=['1'], level=0), cls)(self,
action.site_customization)
if ac.name in acmap:
if ac.priority >= acmap[ac.name].priority:
acmap[ac.name] = ac
else:
acmap[ac.name] = ac
self.iactions = acmap
def initialize(self, library_path, db, listener, actions): def initialize(self, library_path, db, listener, actions):
opts = self.opts opts = self.opts
@ -120,6 +127,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
self.check_messages_timer.start(1000) self.check_messages_timer.start(1000)
MainWindowMixin.__init__(self, db) MainWindowMixin.__init__(self, db)
for ac in self.iactions.values():
ac.do_genesis()
# Jobs Button {{{ # Jobs Button {{{
self.job_manager = JobManager() self.job_manager = JobManager()
@ -249,7 +258,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
self.start_content_server() self.start_content_server()
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
AddAction.__init__(self)
self.read_settings() self.read_settings()
self.finalize_layout() self.finalize_layout()