From f6c73f3ad641b9c45409c15041233b07a7c740f9 Mon Sep 17 00:00:00 2001 From: Samuel Walladge Date: Fri, 16 Dec 2016 21:54:04 +1030 Subject: [PATCH 1/5] implement optional download-open handler setting - adds new `general` -> `default-open-dispatcher` setting (string) - if set, will be used instead of QDesktopServices.openUrl (xdg-open backend) - fixes the 'download handlers' part of issue #841 - note that this is only relevent to the `:download-open` command and other methods of opening downloaded files from qutebrowser --- doc/help/settings.asciidoc | 9 +++++++++ qutebrowser/browser/downloads.py | 15 ++++++++++++--- qutebrowser/config/configdata.py | 7 +++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index af3fd459b..5dffe1733 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -11,6 +11,7 @@ |<>|Whether to find text on a page case-insensitively. |<>|The default page(s) to open at the start, separated by commas. |<>|The URL parameters to strip with :yank url, separated by commas. +|<>|The default program used to open downloads. Set to an empty string to use the default internal handler. |<>|The page to open if :open -t/-b/-w is used without URL. Use `about:blank` for a blank page. |<>|Whether to start a search when something else than a URL is entered. |<>|Whether to save the config automatically on quit. @@ -331,6 +332,14 @@ The URL parameters to strip with :yank url, separated by commas. Default: +pass:[ref,utm_source,utm_medium,utm_campaign,utm_term,utm_content]+ +[[general-default-open-dispatcher]] +=== default-open-dispatcher +The default program used to open downloads. Set to an empty string to use the default internal handler. + +Any {} in the string will be expanded to the filename, else the filename will be appended. + +Default: empty + [[general-default-page]] === default-page The page to open if :open -t/-b/-w is used without URL. Use `about:blank` for a blank page. diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 12e766ecb..b8b3de5cd 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -512,8 +512,8 @@ class AbstractDownloadItem(QObject): Args: cmdline: The command to use as string. A `{}` is expanded to the filename. None means to use the system's default - application. If no `{}` is found, the filename is appended - to the cmdline. + application or `default-open-dispatcher` if set. If no + `{}` is found, the filename is appended to the cmdline. """ assert self.successful filename = self._get_open_filename() @@ -521,13 +521,22 @@ class AbstractDownloadItem(QObject): log.downloads.error("No filename to open the download!") return - if cmdline is None: + # the default program to open downloads with - will be empty string + # if we want to use the default + override = config.get('general', 'default-open-dispatcher') + + # precedence order: supplied cmdline > default-open-dispatcher > openUrl + + if cmdline is None and not override: log.downloads.debug("Opening {} with the system application" .format(filename)) url = QUrl.fromLocalFile(filename) QDesktopServices.openUrl(url) return + if cmdline is None and override: + cmdline = override + cmd, *args = shlex.split(cmdline) args = [arg.replace('{}', filename) for arg in args] if '{}' not in cmdline: diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 3a1b71e01..3b71c6044 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -147,6 +147,13 @@ def data(readonly=False): "The URL parameters to strip with :yank url, separated by " "commas."), + ('default-open-dispatcher', + SettingValue(typ.String(none_ok=True), ''), + "The default program used to open downloads. Set to an empty " + "string to use the default internal handler.\n\n" + "Any {} in the string will be expanded to the filename, else " + "the filename will be appended."), + ('default-page', SettingValue(typ.FuzzyUrl(), '${startpage}'), "The page to open if :open -t/-b/-w is used without URL. Use " From aafcd1f1d7be5dc5122dab207e9de84011a53bf2 Mon Sep 17 00:00:00 2001 From: Samuel Walladge Date: Sat, 17 Dec 2016 09:22:22 +1030 Subject: [PATCH 2/5] fix failing pylint test (line too long) --- qutebrowser/browser/downloads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index b8b3de5cd..6326e6279 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -525,7 +525,7 @@ class AbstractDownloadItem(QObject): # if we want to use the default override = config.get('general', 'default-open-dispatcher') - # precedence order: supplied cmdline > default-open-dispatcher > openUrl + # precedence order: cmdline > default-open-dispatcher > openUrl if cmdline is None and not override: log.downloads.debug("Opening {} with the system application" From 3d8dedc48bee1bf54c5ba11c82ca97e51a61ec3f Mon Sep 17 00:00:00 2001 From: Samuel Walladge Date: Tue, 20 Dec 2016 12:09:30 +1030 Subject: [PATCH 3/5] add tests for default-open-dispatcher --- tests/end2end/features/downloads.feature | 14 ++++++++++++++ tests/end2end/features/test_downloads_bdd.py | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/end2end/features/downloads.feature b/tests/end2end/features/downloads.feature index b6a38da29..3bdba2c41 100644 --- a/tests/end2end/features/downloads.feature +++ b/tests/end2end/features/downloads.feature @@ -337,6 +337,20 @@ Feature: Downloading things from a website. And I open the download with a placeholder Then "Opening *download.bin* with [*python*]" should be logged + Scenario: Opening a download with default-open-dispatcher set + When I set general -> default-open-dispatcher to python {} -c "import sys; print(sys.argv[1])" + And I open data/downloads/download.bin without waiting + And I wait until the download is finished + And I open the download with no args + Then "Opening *download.bin* with [*python*]" should be logged + + Scenario: Opening a download with default-open-dispatcher set to cat + When I set general -> default-open-dispatcher to cat + And I open data/downloads/download.bin without waiting + And I wait until the download is finished + And I open the download with no args + Then "Opening *download.bin* with [*cat*]" should be logged + Scenario: Opening a download which does not exist When I run :download-open with count 42 Then the error "There's no download 42!" should be shown diff --git a/tests/end2end/features/test_downloads_bdd.py b/tests/end2end/features/test_downloads_bdd.py index 65ccf1f3e..2538a033e 100644 --- a/tests/end2end/features/test_downloads_bdd.py +++ b/tests/end2end/features/test_downloads_bdd.py @@ -44,7 +44,6 @@ def temporary_download_dir(quteproc, tmpdir): unwritable.ensure(dir=True) unwritable.chmod(0) - @bdd.given("I clean old downloads") def clean_old_downloads(quteproc): quteproc.send_cmd(':download-cancel --all') @@ -108,6 +107,11 @@ def download_open(quteproc): quteproc.send_cmd(':download-open {}'.format(cmd)) +@bdd.when("I open the download with no args") +def download_open_plain(quteproc): + quteproc.send_cmd(':download-open') + + @bdd.when("I open the download with a placeholder") def download_open_placeholder(quteproc): cmd = '{} -c "import sys; print(sys.argv[1])"'.format( From a27d7cddb34d5ddeded523eefd22ead5e880ea82 Mon Sep 17 00:00:00 2001 From: Samuel Walladge Date: Tue, 20 Dec 2016 20:13:22 +1030 Subject: [PATCH 4/5] fix tests and add another --- tests/end2end/features/downloads.feature | 13 ++++++++++--- tests/end2end/features/test_downloads_bdd.py | 13 ++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/end2end/features/downloads.feature b/tests/end2end/features/downloads.feature index 3bdba2c41..d141f8af5 100644 --- a/tests/end2end/features/downloads.feature +++ b/tests/end2end/features/downloads.feature @@ -338,19 +338,26 @@ Feature: Downloading things from a website. Then "Opening *download.bin* with [*python*]" should be logged Scenario: Opening a download with default-open-dispatcher set - When I set general -> default-open-dispatcher to python {} -c "import sys; print(sys.argv[1])" + When I set a test python default-open-dispatcher And I open data/downloads/download.bin without waiting And I wait until the download is finished - And I open the download with no args + And I run :download-open Then "Opening *download.bin* with [*python*]" should be logged Scenario: Opening a download with default-open-dispatcher set to cat When I set general -> default-open-dispatcher to cat And I open data/downloads/download.bin without waiting And I wait until the download is finished - And I open the download with no args + And I run :download-open Then "Opening *download.bin* with [*cat*]" should be logged + Scenario: Opening a download with default-open-dispatcher set and override + When I set general -> default-open-dispatcher to cat + And I open data/downloads/download.bin without waiting + And I wait until the download is finished + And I open the download + Then "Opening *download.bin* with [*python*]" should be logged + Scenario: Opening a download which does not exist When I run :download-open with count 42 Then the error "There's no download 42!" should be shown diff --git a/tests/end2end/features/test_downloads_bdd.py b/tests/end2end/features/test_downloads_bdd.py index 2538a033e..753cfa75c 100644 --- a/tests/end2end/features/test_downloads_bdd.py +++ b/tests/end2end/features/test_downloads_bdd.py @@ -44,6 +44,7 @@ def temporary_download_dir(quteproc, tmpdir): unwritable.ensure(dir=True) unwritable.chmod(0) + @bdd.given("I clean old downloads") def clean_old_downloads(quteproc): quteproc.send_cmd(':download-cancel --all') @@ -100,6 +101,13 @@ def download_prompt(tmpdir, quteproc, path): quteproc.send_cmd(':leave-mode') +@bdd.when("I set a test python default-open-dispatcher") +def default_open_dispatcher_python(quteproc, tmpdir): + cmd = '{} -c "import sys; print(sys.argv[1])"'.format( + shlex.quote(sys.executable)) + quteproc.set_setting('general', 'default-open-dispatcher', cmd) + + @bdd.when("I open the download") def download_open(quteproc): cmd = '{} -c "import sys; print(sys.argv[1])"'.format( @@ -107,11 +115,6 @@ def download_open(quteproc): quteproc.send_cmd(':download-open {}'.format(cmd)) -@bdd.when("I open the download with no args") -def download_open_plain(quteproc): - quteproc.send_cmd(':download-open') - - @bdd.when("I open the download with a placeholder") def download_open_placeholder(quteproc): cmd = '{} -c "import sys; print(sys.argv[1])"'.format( From 0afa74a9de6fc07fbc347a5a320a9070f92d5388 Mon Sep 17 00:00:00 2001 From: Samuel Walladge Date: Tue, 20 Dec 2016 20:48:56 +1030 Subject: [PATCH 5/5] remove cat test --- tests/end2end/features/downloads.feature | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/end2end/features/downloads.feature b/tests/end2end/features/downloads.feature index d141f8af5..5b4c4f9a4 100644 --- a/tests/end2end/features/downloads.feature +++ b/tests/end2end/features/downloads.feature @@ -344,13 +344,6 @@ Feature: Downloading things from a website. And I run :download-open Then "Opening *download.bin* with [*python*]" should be logged - Scenario: Opening a download with default-open-dispatcher set to cat - When I set general -> default-open-dispatcher to cat - And I open data/downloads/download.bin without waiting - And I wait until the download is finished - And I run :download-open - Then "Opening *download.bin* with [*cat*]" should be logged - Scenario: Opening a download with default-open-dispatcher set and override When I set general -> default-open-dispatcher to cat And I open data/downloads/download.bin without waiting