From 815fb4bc30299d44dc26d4d80bc2900770844af3 Mon Sep 17 00:00:00 2001 From: un-pogaz <46523284+un-pogaz@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:17:56 +0200 Subject: [PATCH] allow auto close when all jobs finished --- src/calibre/gui2/__init__.py | 6 +++++ src/calibre/gui2/dialogs/jobs.ui | 11 ++++++++ src/calibre/gui2/dialogs/message_box.py | 34 +++++++++++++++++++++++++ src/calibre/gui2/ui.py | 27 +++++++++++++++++++- 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 6e8e9e1003..4aab84f769 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -843,6 +843,12 @@ def show_restart_warning(msg, parent=None): return d.do_restart +def show_auto_close_warning(parent, timeout=30): + from calibre.gui2.dialogs.message_box import AutoCloseNotification + d = AutoCloseNotification(parent=parent, timeout=timeout) + return d.exec() == QDialog.DialogCode.Accepted + + class Dispatcher(QObject): ''' Convenience class to use Qt signals with arbitrary python callables. diff --git a/src/calibre/gui2/dialogs/jobs.ui b/src/calibre/gui2/dialogs/jobs.ui index c91017b5ef..a582c877ea 100644 --- a/src/calibre/gui2/dialogs/jobs.ui +++ b/src/calibre/gui2/dialogs/jobs.ui @@ -106,6 +106,17 @@ + + + + &Automatically close calibre after all jobs are finished + + + + :/images/dialog_warning.png:/images/dialog_warning.png + + + diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index 7dd810e59b..28ce0235fc 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -25,6 +25,7 @@ from qt.core import ( Qt, QTextBrowser, QTextDocument, + QTimer, QVBoxLayout, QWidget, pyqtSignal, @@ -378,6 +379,39 @@ class ErrorNotification(MessageBox): # {{{ # }}} +class AutoCloseNotification(MessageBox): # {{{ + + def __init__(self, timeout=30, parent=None): + super().__init__( + MessageBox.QUESTION, + _('calibre automatic closing'), + _('calibre is about to close automatically. Do you want to confim or abort the action?'), + parent=parent, + show_copy_button=False, + q_icon='dialog_warning.png', + default_yes=True, + yes_text=None, + no_text=_('Abort'), + ) + self.timeout = timeout + self.timer = QTimer(self) + self.timer.setInterval(self.timeout * 1000) + self.timer.timeout.connect(self.accept) + self.timer.setSingleShot(True) + self.updater = QTimer(self) + self.updater.setInterval(1000) + self.updater.timeout.connect(self.update_texts) + self.updater.setSingleShot(False) + self.timer.start() + self.updater.start() + self.update_texts() + + def update_texts(self): + time = self.timer.remainingTime() // 1000 + self.bb.button(QDialogButtonBox.StandardButton.Yes).setText(_('Close now ({}s)').format(time)) +# }}} + + class JobError(QDialog): # {{{ WIDTH = 600 diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 3082231192..7171b35436 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -26,7 +26,19 @@ from calibre.constants import DEBUG, __appname__, config_dir, filesystem_encodin from calibre.customize import PluginInstallationType from calibre.customize.ui import available_store_plugins, interface_actions from calibre.db.legacy import LibraryDatabase -from calibre.gui2 import Dispatcher, GetMetadata, config, error_dialog, gprefs, info_dialog, max_available_height, open_url, question_dialog, warning_dialog +from calibre.gui2 import ( + Dispatcher, + GetMetadata, + config, + error_dialog, + gprefs, + info_dialog, + max_available_height, + open_url, + question_dialog, + show_auto_close_warning, + warning_dialog, +) from calibre.gui2.auto_add import AutoAdder from calibre.gui2.changes import handle_changes from calibre.gui2.cover_flow import CoverFlowMixin @@ -238,6 +250,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.jobs_dialog = JobsDialog(self, self.job_manager) self.jobs_button = JobsButton(parent=self) self.jobs_button.initialize(self.jobs_dialog, self.job_manager) + self.job_manager.job_done.connect(self._jobs_auto_close) # }}} LayoutMixin.init_layout_mixin(self) @@ -1219,6 +1232,18 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.system_tray_icon.setVisible(False) QApplication.instance().exit() + def _jobs_auto_close(self, nnum): + if self.jobs_dialog.auto_close_calibre.isChecked() and nnum == 0: + self.auto_close_calibre() + + def auto_close_calibre(self): + timed_print('Auto-closing asked...') + if show_auto_close_warning(self): + self.quit(confirm_quit=False) + else: + timed_print('Auto-closing rejected') + self.jobs_dialog.auto_close_calibre.setChecked(False) + def donate(self, *args): from calibre.utils.localization import localize_website_link open_url(QUrl(localize_website_link('https://calibre-ebook.com/donate')))