From 8a3aca63b063bbefc2fc46abecdec31222cf8bd4 Mon Sep 17 00:00:00 2001 From: Peter Vilim Date: Thu, 1 Jan 2015 22:32:39 -0600 Subject: [PATCH] Confirm quit if downloads running --- qutebrowser/config/configtypes.py | 55 +++++++++++++++++++++++++++- qutebrowser/mainwindow/mainwindow.py | 44 +++++++++++++++------- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index 0cc7592b4..4b445cd00 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -25,6 +25,7 @@ import base64 import codecs import os.path import sre_constants +import itertools from PyQt5.QtCore import QUrl from PyQt5.QtGui import QColor, QFont @@ -1223,14 +1224,66 @@ class AcceptCookies(BaseType): ('never', "Don't accept cookies at all.")) -class ConfirmQuit(BaseType): +class ConfirmQuit(List): """Whether to display a confirmation when the window is closed.""" + typestr = 'string-list' + valid_values = ValidValues(('always', "Always show a confirmation."), ('multiple-tabs', "Show a confirmation if " "multiple tabs are opened."), + ('downloads', "show a confirmation if downloads" + "are running"), ('never', "Never show a confirmation.")) + # Values that can be combined with commas + combinable_values = ('multiple-tabs', 'downloads') + + def transform(self, value): + # Backward compatible + if value == 'never': + return value + # Split configuration string into list + else: + return super().transform(value) + + def validate(self, value): + values = self.transform(value) + # Backward compatibility + if values == 'never': + return + # Never can't be set with other options + elif 'never' in values and isinstance(values, list): + raise configexc.ValidationError(value, "List cannot contain never!") + # Always can't be set with other options + elif 'always' in values and isinstance(values, list): + raise configexc.ValidationError(value, + "List cannot contain always!") + # Values have to be valid + elif not set(values).issubset(set(self.valid_values.values)): + raise configexc.ValidationError(value, "List contains invalid" + " values!") + # List can't have duplicates + elif len(set(values)) != len(values): + raise configexc.ValidationError(value, "List contains duplicate" + " values!") + + def complete(self): + combinations = [] + # Generate combinations of the options that can be combined + for size in range(2, len(self.combinable_values) + 1): + combinations = combinations + list( + itertools.combinations(self.combinable_values, size)) + out = [] + # Add valid single values + for val in self.valid_values: + out.append((val, self.valid_values.descriptions[val])) + # Add combinations to list of options + for val in combinations: + desc = '' + val = ','.join(val) + out.append((val, desc)) + return out class ForwardUnboundKeys(BaseType): diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 2b2311dd2..801ded657 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -327,21 +327,37 @@ class MainWindow(QWidget): def closeEvent(self, e): """Override closeEvent to display a confirmation if needed.""" confirm_quit = config.get('ui', 'confirm-quit') - count = self._tabbed_browser.count() - if confirm_quit == 'never': + tab_count = self._tabbed_browser.count() + download_manager = objreg.get('download-manager', scope='window', + window=self.win_id) + download_count = download_manager.rowCount() + quit_text = [] + # Close if set to never ask for confirmation (backward compatible) + if confirm_quit == 'never' or 'never' in confirm_quit: pass - elif confirm_quit == 'multiple-tabs' and count <= 1: - pass - else: - text = "Close {} {}?".format( - count, "tab" if count == 1 else "tabs") - confirmed = message.ask(self.win_id, text, - usertypes.PromptMode.yesno, default=True) - if not confirmed: - log.destroy.debug("Cancelling losing of window {}".format( - self.win_id)) - e.ignore() - return + # Ask if set to always ask before closing + if 'always' in confirm_quit: + quit_text.append("Close?") + # Ask if multiple-tabs are open + if 'multiple-tabs' in confirm_quit and tab_count > 1: + quit_text.append("Close {} {}?".format( + tab_count, "tab" if tab_count == 1 else "tabs")) + # Ask if multiple downloads running + if 'downloads' in confirm_quit and download_count > 0: + quit_text.append("Close {} {}?".format( + tab_count, "download" if tab_count == 1 else "downloads")) + # Process all quit messages that user must confirm + if len(quit_text) > 0: + for text in quit_text: + confirmed = message.ask(self.win_id, text, + usertypes.PromptMode.yesno, + default=True) + # Stop asking if the user cancels + if not confirmed: + log.destroy.debug("Cancelling losing of window {}".format( + self.win_id)) + e.ignore() + return e.accept() objreg.get('app').geometry = bytes(self.saveGeometry()) log.destroy.debug("Closing window {}".format(self.win_id))