diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index 0cc7592b4..d74aa6a0a 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,55 @@ 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 validate(self, value): + values = self.transform(value) + # Never can't be set with other options + if 'never' in values and len(values) > 1: + raise configexc.ValidationError( + value, "List cannot contain never!") + # Always can't be set with other options + elif 'always' in values and len(values) > 1: + 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 += 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 = '' + out.append((','.join(val), desc)) + return out class ForwardUnboundKeys(BaseType): diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 2b2311dd2..c5a0b00a9 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -327,18 +327,32 @@ 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_texts = [] + # Close if set to never ask for confirmation + if '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") + # Ask if multiple-tabs are open + if 'multiple-tabs' in confirm_quit and tab_count > 1: + quit_texts.append("{} {} open.".format( + tab_count, "tab is" if tab_count == 1 else "tabs are")) + # Ask if multiple downloads running + if 'downloads' in confirm_quit and download_count > 0: + quit_texts.append("{} {} running.".format( + tab_count, + "download is" if tab_count == 1 else "downloads are")) + # Process all quit messages that user must confirm + if quit_texts or 'always' in confirm_quit: + text = '\n'.join(['Really quit?'] + quit_texts) confirmed = message.ask(self.win_id, text, - usertypes.PromptMode.yesno, default=True) + usertypes.PromptMode.yesno, + default=True) + # Stop asking if the user cancels if not confirmed: - log.destroy.debug("Cancelling losing of window {}".format( + log.destroy.debug("Cancelling closing of window {}".format( self.win_id)) e.ignore() return