mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
When running the content server do not hide the main calibre window during shutdown until the content server has stopped. Show a shutting down message in the window so that the user knows what is happening.
Create a new type of plugin LibraryClosePlugin that is run every time an open library is closed/switched from. Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
8493f4ea15
@ -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.54 because that is when support was added
|
||||
minimum_calibre_version = (2, 54, 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,
|
||||
InterfaceActionBase as InterfaceAction,
|
||||
PreferencesPlugin, platform, InvalidPlugin,
|
||||
StoreBase as Store, ViewerPlugin, EditBookToolPlugin)
|
||||
StoreBase as Store, ViewerPlugin, EditBookToolPlugin,
|
||||
LibraryClosedPlugin)
|
||||
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||
from calibre.customize.zipplugin import loader
|
||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||
@ -246,6 +247,23 @@ def preferences_plugins():
|
||||
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
|
||||
|
||||
def has_library_closed_plugins():
|
||||
for plugin in _initialized_plugins:
|
||||
if isinstance(plugin, LibraryClosedPlugin):
|
||||
if not is_disabled(plugin):
|
||||
return True
|
||||
return False
|
||||
# }}}
|
||||
|
||||
# Store Plugins # {{{
|
||||
|
||||
def store_plugins():
|
||||
|
@ -2013,6 +2013,13 @@ class Cache(object):
|
||||
|
||||
@write_api
|
||||
def close(self):
|
||||
from calibre.customize.ui import available_library_closed_plugins
|
||||
for plugin in available_library_closed_plugins():
|
||||
try:
|
||||
plugin.run(self)
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
self.backend.close()
|
||||
|
||||
@write_api
|
||||
|
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.Qt import (QIcon, Qt, QWidget, QSize,
|
||||
pyqtSignal, QToolButton, QMenu, QAction,
|
||||
pyqtSignal, QToolButton, QMenu, QAction, QCoreApplication,
|
||||
QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup)
|
||||
|
||||
|
||||
@ -304,10 +304,25 @@ class MainWindowMixin(object): # {{{
|
||||
pass # PyQt5 seems to be missing this property
|
||||
|
||||
l = self.centralwidget.layout()
|
||||
|
||||
# Add in the widget for the shutdown messages. It is invisible until a
|
||||
# message is shown
|
||||
smw = self.shutdown_message_widget = QLabel('')
|
||||
smw.setMinimumHeight(200)
|
||||
smw.setAlignment(Qt.AlignCenter)
|
||||
self.shutdown_message_widget.setVisible(False)
|
||||
l.addWidget(smw)
|
||||
|
||||
# And now, start adding the real widgets
|
||||
l.addWidget(self.search_bar)
|
||||
|
||||
|
||||
def show_shutdown_message(self, message):
|
||||
smw = self.shutdown_message_widget
|
||||
smw.setVisible(True)
|
||||
txt = smw.text()
|
||||
txt += '\n' + message
|
||||
smw.setText(txt)
|
||||
# Force processing the events needed to show the message
|
||||
QCoreApplication.processEvents()
|
||||
# }}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -878,7 +878,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
return True
|
||||
|
||||
def shutdown(self, write_settings=True):
|
||||
self.show_shutdown_message(_('Shutting down'))
|
||||
|
||||
from calibre.customize.ui import has_library_closed_plugins
|
||||
if has_library_closed_plugins():
|
||||
self.show_shutdown_message(
|
||||
_('Running database shutdown plugins. This could take a few seconds...'))
|
||||
|
||||
self.grid_view.shutdown()
|
||||
db = None
|
||||
try:
|
||||
db = self.library_view.model().db
|
||||
cf = db.clean
|
||||
@ -908,10 +916,17 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
if mb is not None:
|
||||
mb.stop()
|
||||
|
||||
self.hide_windows()
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
try:
|
||||
try:
|
||||
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.
|
||||
self.show_shutdown_message(
|
||||
_('Shutting down the content server. This could take a while ...'))
|
||||
s = self.content_server
|
||||
self.content_server = None
|
||||
s.exit()
|
||||
@ -919,15 +934,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
self.hide_windows()
|
||||
# Do not report any errors that happen after the shutdown
|
||||
sys.excepthook = sys.__excepthook__
|
||||
if self._spare_pool is not None:
|
||||
self._spare_pool.shutdown()
|
||||
from calibre.db.delete_service import shutdown
|
||||
shutdown()
|
||||
time.sleep(2)
|
||||
self.istores.join()
|
||||
self.hide_windows()
|
||||
# Do not report any errors that happen after the shutdown
|
||||
sys.excepthook = sys.__excepthook__
|
||||
return True
|
||||
|
||||
def run_wizard(self, *args):
|
||||
|
Loading…
x
Reference in New Issue
Block a user