diff --git a/README.asciidoc b/README.asciidoc index 66787a9fe..dcab97005 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -127,6 +127,7 @@ Contributors, sorted by the number of commits in descending order: * Florian Bruhin * Claude * John ShaggyTwoDope Jenkins +* Peter Vilim * rikn00 * Martin Zimmermann * Joel Torstensson @@ -135,10 +136,11 @@ Contributors, sorted by the number of commits in descending order: * Regina Hug * Mathias Fussenegger * Larry Hynes -* Peter Vilim +* Thiago Barroso Perrotta * Matthias Lisin * Helen Sherwood-Taylor * HalosGhost +* Error 800 // QUTE_AUTHORS_END The following people have contributed graphics: diff --git a/doc/INSTALL.asciidoc b/doc/INSTALL.asciidoc index 1c5864e30..c39714ddd 100644 --- a/doc/INSTALL.asciidoc +++ b/doc/INSTALL.asciidoc @@ -39,7 +39,7 @@ your `$PATH` (e.g. `/usr/local/bin/qutebrowser` or `~/bin/qutebrowser`): ---- #!/bin/bash -~/path/to/qutebrowser/.venv/bin/python3 -m qutebrowser +~/path/to/qutebrowser/.venv/bin/python3 -m qutebrowser "$@" ---- On Archlinux diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 8422d9b61..aea88a6e1 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -390,6 +390,7 @@ Valid values: * +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. Default: +pass:[never]+ diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py index dbfcb0303..5543f1455 100644 --- a/qutebrowser/commands/runners.py +++ b/qutebrowser/commands/runners.py @@ -270,8 +270,11 @@ class CommandRunner(QObject): maxsplit=maxsplit) for s in args: # remove quotes and replace \" by " - s = re.sub(r"""(^|[^\\])["']""", r'\1', s) - s = re.sub(r"""\\(["'])""", r'\1', s) + if s == '""' or s == "''": + s = '' + else: + s = re.sub(r"""(^|[^\\])["']""", r'\1', s) + s = re.sub(r"""\\(["'])""", r'\1', s) self._args.append(s) break else: diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 17d812dab..83bcb2c9b 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -940,8 +940,8 @@ KEY_DATA = collections.OrderedDict([ ('tab-move', ['gm']), ('tab-move -', ['gl']), ('tab-move +', ['gr']), - ('tab-next', ['J']), - ('tab-prev', ['K']), + ('tab-next', ['J', 'gt']), + ('tab-prev', ['K', 'gT']), ('tab-clone', ['gC']), ('reload', ['r']), ('reload -f', ['R']), 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 diff --git a/qutebrowser/misc/crashdialog.py b/qutebrowser/misc/crashdialog.py index 56e4d7181..d812e8f12 100644 --- a/qutebrowser/misc/crashdialog.py +++ b/qutebrowser/misc/crashdialog.py @@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton, from qutebrowser.utils import version, log, utils, objreg from qutebrowser.misc import miscwidgets from qutebrowser.browser.network import pastebin +from qutebrowser.config import config class _CrashDialog(QDialog): @@ -298,6 +299,11 @@ class ExceptionCrashDialog(_CrashDialog): if debug: self._chk_log.setChecked(False) self._chk_log.setEnabled(False) + try: + if config.get('general', 'private-browsing'): + self._chk_log.setChecked(False) + except Exception: + log.misc.exception("Error while checking private browsing mode") self._chk_log.toggled.connect(self._set_crash_info) self._vbox.addWidget(self._chk_log) info_label = QLabel("This makes it a lot easier to diagnose the " diff --git a/scripts/init_venv.py b/scripts/init_venv.py index 4b27bbcf8..ea0ef2861 100644 --- a/scripts/init_venv.py +++ b/scripts/init_venv.py @@ -125,14 +125,10 @@ def link_pyqt(): if not globbed_sip: print("Did not find sip in {}!".format(sys_path), file=sys.stderr) sys.exit(1) - elif len(globbed_sip) != 1: - print("Found multiple sip installations: {}!".format(globbed_sip), - file=sys.stderr) - sys.exit(1) - files = ( + files = [ 'PyQt5', - os.path.basename(globbed_sip[0]), - ) + ] + files += [os.path.basename(e) for e in globbed_sip] for fn in files: source = os.path.join(sys_path, fn) link_name = os.path.join(venv_path, fn)