mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add a LibraryClosed plugin type that is called when the library is closed (new_api). Add a way to provide a message during shutdown.
This commit is contained in:
parent
9235097db2
commit
22ca6dcbba
@ -781,3 +781,25 @@ class EditBookToolPlugin(Plugin): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
class LibraryClosedPlugin(Plugin): # {{{
|
||||||
|
'''
|
||||||
|
LibraryClosedPlugins are run when a library is closed, either at shutdown,
|
||||||
|
when the library is changed, or when a library is used in some other way.
|
||||||
|
At the moment these plugins won't be called by the CLI functions.
|
||||||
|
'''
|
||||||
|
type = _('Library Closed')
|
||||||
|
|
||||||
|
# minimum version 2 because it requires the new db
|
||||||
|
minimum_calibre_version = (2, 0, 0)
|
||||||
|
|
||||||
|
def run(self, db):
|
||||||
|
'''
|
||||||
|
The db will be a reference to the new_api (db.cache.py).
|
||||||
|
|
||||||
|
The plugin must run to completion. It must not use the GUI, threads, or
|
||||||
|
any signals.
|
||||||
|
'''
|
||||||
|
raise NotImplementedError('LibraryClosedPlugin '
|
||||||
|
'run method must be overridden in subclass')
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ from calibre.customize import (CatalogPlugin, FileTypePlugin, PluginNotFound,
|
|||||||
MetadataReaderPlugin, MetadataWriterPlugin,
|
MetadataReaderPlugin, MetadataWriterPlugin,
|
||||||
InterfaceActionBase as InterfaceAction,
|
InterfaceActionBase as InterfaceAction,
|
||||||
PreferencesPlugin, platform, InvalidPlugin,
|
PreferencesPlugin, platform, InvalidPlugin,
|
||||||
StoreBase as Store, ViewerPlugin, EditBookToolPlugin)
|
StoreBase as Store, ViewerPlugin, EditBookToolPlugin,
|
||||||
|
LibraryClosedPlugin)
|
||||||
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||||
from calibre.customize.zipplugin import loader
|
from calibre.customize.zipplugin import loader
|
||||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||||
@ -246,6 +247,16 @@ def preferences_plugins():
|
|||||||
yield plugin
|
yield plugin
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
# Library Closed Plugins # {{{
|
||||||
|
def available_library_closed_plugins():
|
||||||
|
customization = config['plugin_customization']
|
||||||
|
for plugin in _initialized_plugins:
|
||||||
|
if isinstance(plugin, LibraryClosedPlugin):
|
||||||
|
if not is_disabled(plugin):
|
||||||
|
plugin.site_customization = customization.get(plugin.name, '')
|
||||||
|
yield plugin
|
||||||
|
# }}}
|
||||||
|
|
||||||
# Store Plugins # {{{
|
# Store Plugins # {{{
|
||||||
|
|
||||||
def store_plugins():
|
def store_plugins():
|
||||||
|
@ -2013,6 +2013,13 @@ class Cache(object):
|
|||||||
|
|
||||||
@write_api
|
@write_api
|
||||||
def close(self):
|
def close(self):
|
||||||
|
from calibre.customize.ui import available_library_closed_plugins
|
||||||
|
for plugin in available_library_closed_plugins():
|
||||||
|
try:
|
||||||
|
plugin.run(self)
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
self.backend.close()
|
self.backend.close()
|
||||||
|
|
||||||
@write_api
|
@write_api
|
||||||
|
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt5.Qt import (QIcon, Qt, QWidget, QSize,
|
from PyQt5.Qt import (QIcon, Qt, QWidget, QSize,
|
||||||
pyqtSignal, QToolButton, QMenu, QAction,
|
pyqtSignal, QToolButton, QMenu, QAction, QCoreApplication,
|
||||||
QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup)
|
QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup)
|
||||||
|
|
||||||
|
|
||||||
@ -306,8 +306,34 @@ class MainWindowMixin(object): # {{{
|
|||||||
l = self.centralwidget.layout()
|
l = self.centralwidget.layout()
|
||||||
l.addWidget(self.search_bar)
|
l.addWidget(self.search_bar)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def show_shutdown_message(self, message):
|
||||||
|
msgs = getattr(self, 'shutdown_messages', None)
|
||||||
|
if msgs is None:
|
||||||
|
msgs = self.shutdown_messages = []
|
||||||
|
msgs.append(message)
|
||||||
|
|
||||||
|
smw = QWidget()
|
||||||
|
sml = QVBoxLayout()
|
||||||
|
smw.setLayout(sml)
|
||||||
|
|
||||||
|
# Construct the widget containing all the messages to date. Add stretch
|
||||||
|
# to make it vertically centered.
|
||||||
|
sml.addStretch()
|
||||||
|
for msg in msgs:
|
||||||
|
sml.addWidget(QLabel(msg), alignment=Qt.AlignHCenter)
|
||||||
|
sml.addStretch()
|
||||||
|
|
||||||
|
# The next line is needed to prevent the main widget from being garbage
|
||||||
|
# collected just in case more processing is required (and it is). As we
|
||||||
|
# are shutting down, the memory leak isn't of concern
|
||||||
|
if getattr(self, 'saved_central_widget', None) is None:
|
||||||
|
self.saved_central_widget = self.centralWidget
|
||||||
|
|
||||||
|
# Show the shutdown messages
|
||||||
|
self.setCentralWidget(smw)
|
||||||
|
# Force processing the events needed to show the message
|
||||||
|
QCoreApplication.processEvents()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -878,7 +878,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def shutdown(self, write_settings=True):
|
def shutdown(self, write_settings=True):
|
||||||
|
get_gui().show_shutdown_message(_('Shutting down'))
|
||||||
|
|
||||||
|
from calibre.customize.ui import available_library_closed_plugins
|
||||||
|
if available_library_closed_plugins():
|
||||||
|
get_gui().show_shutdown_message(
|
||||||
|
_('Running database shutdown plugins. This could take a few seconds...'))
|
||||||
|
|
||||||
self.grid_view.shutdown()
|
self.grid_view.shutdown()
|
||||||
|
db = None
|
||||||
try:
|
try:
|
||||||
db = self.library_view.model().db
|
db = self.library_view.model().db
|
||||||
cf = db.clean
|
cf = db.clean
|
||||||
@ -908,10 +916,20 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
if mb is not None:
|
if mb is not None:
|
||||||
mb.stop()
|
mb.stop()
|
||||||
|
|
||||||
self.hide_windows()
|
if db is not None:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
# This happens again later. Don't do it here because it hides the
|
||||||
|
# shutdown messages
|
||||||
|
# self.hide_windows()
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
if self.content_server is not None:
|
if self.content_server is not None:
|
||||||
|
# If the content server has any sockets being closed then
|
||||||
|
# this can take quite a long time (minutes). Tell the user that it is
|
||||||
|
# happening.
|
||||||
|
get_gui().show_shutdown_message(
|
||||||
|
_('Shutting down the content server. This could take a while ...'))
|
||||||
s = self.content_server
|
s = self.content_server
|
||||||
self.content_server = None
|
self.content_server = None
|
||||||
s.exit()
|
s.exit()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user