From 6f89ab628b4cef607e07bd3cfb20dee07fa65f9a Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Sun, 8 Feb 2015 22:03:29 +0100 Subject: [PATCH 01/17] More command actions on downloads. --- qutebrowser/browser/downloads.py | 21 +++++++++++++++++---- qutebrowser/config/configdata.py | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index eef840dea..1677ac4e8 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -745,20 +745,31 @@ class DownloadManager(QAbstractListModel): return download @cmdutils.register(instance='download-manager', scope='window') - def cancel_download(self, count: {'special': 'count'}=1): - """Cancel the first/[count]th download. + def download_cancel(self, count: {'special': 'count'}=0): + """Cancel the last/[count]th download. Args: count: The index of the download to cancel. """ - if count == 0: - return try: download = self.downloads[count - 1] except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) download.cancel() + @cmdutils.register(instance='download-manager', scope='window') + def download_open(self, count: {'special': 'count'}=0): + """Open the last/[count]th download. + + Args: + count: The index of the download to cancel. + """ + try: + download = self.downloads[count - 1] + except IndexError: + raise cmdexc.CommandError("There's no download {}!".format(count)) + download.open_file() + @pyqtSlot(QNetworkRequest, QNetworkReply) def on_redirect(self, download, request, reply): """Handle a HTTP redirect of a download. @@ -820,6 +831,8 @@ class DownloadManager(QAbstractListModel): else: return False + @cmdutils.register(instance='download-manager', name='downloads-clear', + scope='window') def clear(self): """Remove all finished downloads.""" self.remove_items(d for d in self.downloads if d.done) diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index ac7e4770c..a4d4d2da6 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -1029,7 +1029,7 @@ KEY_DATA = collections.OrderedDict([ ('navigate decrement', ['']), ('inspector', ['wi']), ('download-page', ['gd']), - ('cancel-download', ['ad']), + ('download-cancel', ['ad']), ('view-source', ['gf']), ('tab-focus last', ['']), ('enter-mode passthrough', ['']), From 9428338389557813c0986f2cd84b9c5fa68d4549 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Sun, 8 Feb 2015 22:08:16 +0100 Subject: [PATCH 02/17] Merged :download and :download-page. Fix #449 --- qutebrowser/browser/commands.py | 18 ++++++++++++++---- qutebrowser/browser/downloads.py | 12 ------------ qutebrowser/config/configdata.py | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 048d8d9ed..8b4ea326a 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -911,12 +911,22 @@ class CommandDispatcher: cur.inspector.show() @cmdutils.register(instance='command-dispatcher', scope='window') - def download_page(self): - """Download the current page.""" - page = self._current_widget().page() + def download(self, url=None, dest=None): + """Download a given URL, or current page if none given. + + Args: + url: The URL to download, or None to download current page. + dest: The file path to write the download to, or None to ask. + """ download_manager = objreg.get('download-manager', scope='window', window=self._win_id) - download_manager.get(self._current_url(), page) + if (url): + url = urlutils.qurl_from_user_input(url) + urlutils.raise_cmdexc_if_invalid(url) + download_manager.get(url, filename=dest) + else: + page = self._current_widget().page() + download_manager.get(self._current_url(), page) @cmdutils.register(instance='command-dispatcher', scope='window') def view_source(self): diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 1677ac4e8..aa967d273 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -580,18 +580,6 @@ class DownloadManager(QAbstractListModel): self.questions.append(q) return q - @cmdutils.register(instance='download-manager', scope='window') - def download(self, url, dest=None): - """Download a given URL, given as string. - - Args: - url: The URL to download - dest: The file path to write the download to, or None to ask. - """ - url = urlutils.qurl_from_user_input(url) - urlutils.raise_cmdexc_if_invalid(url) - self.get(url, filename=dest) - @pyqtSlot('QUrl', 'QWebPage') def get(self, url, page=None, fileobj=None, filename=None, auto_remove=False): diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index a4d4d2da6..6b7399009 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -1028,7 +1028,7 @@ KEY_DATA = collections.OrderedDict([ ('navigate increment', ['']), ('navigate decrement', ['']), ('inspector', ['wi']), - ('download-page', ['gd']), + ('download', ['gd']), ('download-cancel', ['ad']), ('view-source', ['gf']), ('tab-focus last', ['']), From 6bbb655a5406a57aee1470729c9e531a8d398236 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Sun, 8 Feb 2015 22:21:34 +0100 Subject: [PATCH 03/17] Fixed bug when specifying filename on download. --- 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 aa967d273..8c4bde739 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -632,7 +632,7 @@ class DownloadManager(QAbstractListModel): request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) if fileobj is not None or filename is not None: - return self.fetch_request(request, filename, fileobj, page, + return self.fetch_request(request, page, fileobj, filename, auto_remove) q = self._prepare_question() filename = urlutils.filename_from_url(request.url()) From 767ca42e468244cda2e9ffb4f8d2f2bca8558a98 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Mon, 9 Feb 2015 12:06:49 +0100 Subject: [PATCH 04/17] Some style fixes. --- qutebrowser/browser/commands.py | 10 ++++++++-- qutebrowser/browser/downloads.py | 12 +++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 8b4ea326a..4062102fc 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -912,7 +912,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') def download(self, url=None, dest=None): - """Download a given URL, or current page if none given. + """Download a given URL, or current page if no URL given. Args: url: The URL to download, or None to download current page. @@ -920,7 +920,7 @@ class CommandDispatcher: """ download_manager = objreg.get('download-manager', scope='window', window=self._win_id) - if (url): + if url: url = urlutils.qurl_from_user_input(url) urlutils.raise_cmdexc_if_invalid(url) download_manager.get(url, filename=dest) @@ -928,6 +928,12 @@ class CommandDispatcher: page = self._current_widget().page() download_manager.get(self._current_url(), page) + @cmdutils.register(instance='command-dispatcher', scope='window', + deprecated="Use :download instead.") + def download_page(self): + """Download the current page.""" + self.download() + @cmdutils.register(instance='command-dispatcher', scope='window') def view_source(self): """Show the source of the current page.""" diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 8c4bde739..01d6bf760 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -745,6 +745,16 @@ class DownloadManager(QAbstractListModel): raise cmdexc.CommandError("There's no download {}!".format(count)) download.cancel() + @cmdutils.register(instance='download-manager', scope='window', + deprecated="Use :download instead.") + def cancel_download(self, count: {'special': 'count'}=1): + """Cancel the first/[count]th download. + + Args: + count: The index of the download to cancel. + """ + self.download_cancel(count) + @cmdutils.register(instance='download-manager', scope='window') def download_open(self, count: {'special': 'count'}=0): """Open the last/[count]th download. @@ -820,7 +830,7 @@ class DownloadManager(QAbstractListModel): return False @cmdutils.register(instance='download-manager', name='downloads-clear', - scope='window') + scope='window') def clear(self): """Remove all finished downloads.""" self.remove_items(d for d in self.downloads if d.done) From e9da7b5391aa6eaed524d04ff9aa89ff41ac576a Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Mon, 9 Feb 2015 17:03:02 +0100 Subject: [PATCH 05/17] :download-open now only opens finished downloads. --- qutebrowser/browser/downloads.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 01d6bf760..41fdef180 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -757,13 +757,14 @@ class DownloadManager(QAbstractListModel): @cmdutils.register(instance='download-manager', scope='window') def download_open(self, count: {'special': 'count'}=0): - """Open the last/[count]th download. + """Open the last/[count]th finished download. Args: count: The index of the download to cancel. """ + finished_items = [d for d in self.downloads if d.done] try: - download = self.downloads[count - 1] + download = finished_items[count - 1] except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) download.open_file() From 55193803a199b75c58a47d27b8c6fb98a4bab74b Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Mon, 9 Feb 2015 17:17:34 +0100 Subject: [PATCH 06/17] Changed :downloads-clear to :download-remove. --- qutebrowser/browser/downloads.py | 24 +++++++++++++++--------- qutebrowser/browser/downloadview.py | 3 ++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 41fdef180..25fe19503 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -825,16 +825,22 @@ class DownloadManager(QAbstractListModel): def can_clear(self): """Check if there are finished downloads to clear.""" - if self.downloads: - return any(download.done for download in self.downloads) - else: - return False + return any(download.done for download in self.downloads) - @cmdutils.register(instance='download-manager', name='downloads-clear', - scope='window') - def clear(self): - """Remove all finished downloads.""" - self.remove_items(d for d in self.downloads if d.done) + @cmdutils.register(instance='download-manager', scope='window') + def download_remove(self, all_: {'name': 'all'}=False, + count: {'special': 'count'}=0): + """Remove the last/[count]th finished download. + + Args: + all: Whether to remove all finished downloads. + count: The index of the download to cancel. + """ + finished_items = [d for d in self.downloads if d.done] + if all_: + self.remove_items(finished_items) + else: + self.remove_item(finished_items[count - 1]) def last_index(self): """Get the last index in the model. diff --git a/qutebrowser/browser/downloadview.py b/qutebrowser/browser/downloadview.py index f426a179d..5c50b0b7d 100644 --- a/qutebrowser/browser/downloadview.py +++ b/qutebrowser/browser/downloadview.py @@ -142,7 +142,8 @@ class DownloadView(QListView): actions.append(("Cancel", item.cancel)) if self.model().can_clear(): actions.append((None, None)) - actions.append(("Remove all finished", self.model().clear)) + actions.append(("Remove all finished", functools.partial( + self.model().download_remove, True))) return actions @pyqtSlot('QPoint') From 6e3d5867f907478a42e3ed7ebfb826fe125d6e6f Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Mon, 9 Feb 2015 17:38:50 +0100 Subject: [PATCH 07/17] Fixed docs. --- README.asciidoc | 2 +- doc/help/commands.asciidoc | 48 +++++++++++++++++++++----------- qutebrowser/browser/commands.py | 2 +- qutebrowser/browser/downloads.py | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 52b36cec8..b679d29a8 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -131,11 +131,11 @@ Contributors, sorted by the number of commits in descending order: * Florian Bruhin * Claude * ZDarian +* Joel Torstensson * Peter Vilim * John ShaggyTwoDope Jenkins * rikn00 * Martin Zimmermann -* Joel Torstensson * Error 800 * Brian Jackson * Patric Schmitz diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 51847b09b..8fd0b7608 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -8,10 +8,11 @@ |<>|Update the adblock block lists. |<>|Go back in the history of the current tab. |<>|Bind a key to a command. -|<>|Cancel the first/[count]th download. |<>|Close the current window. -|<>|Download a given URL, given as string. -|<>|Download the current page. +|<>|Download a given URL, or current page if no URL given. +|<>|Cancel the last/[count]th download. +|<>|Open the last/[count]th finished download. +|<>|Remove the last/[count]th finished download. |<>|Go forward in the history of the current tab. |<>|Toggle fullscreen mode. |<>|Show help about a command or setting. @@ -85,30 +86,45 @@ Bind a key to a command. * +*-m*+, +*--mode*+: A comma-separated list of modes to bind the key in (default: `normal`). -[[cancel-download]] -=== cancel-download -Cancel the first/[count]th download. - -==== count -The index of the download to cancel. - [[close]] === close Close the current window. [[download]] === download -Syntax: +:download 'url' ['dest']+ +Syntax: +:download ['url'] ['dest']+ -Download a given URL, given as string. +Download a given URL, or current page if no URL given. ==== positional arguments -* +'url'+: The URL to download +* +'url'+: The URL to download. If not given, download the current page. * +'dest'+: The file path to write the download to to ask. -[[download-page]] -=== download-page -Download the current page. +[[download-cancel]] +=== download-cancel +Cancel the last/[count]th download. + +==== count +The index of the download to cancel. + +[[download-open]] +=== download-open +Open the last/[count]th finished download. + +==== count +The index of the download to cancel. + +[[download-remove]] +=== download-remove +Syntax: +:download-remove [*--all*]+ + +Remove the last/[count]th finished download. + +==== optional arguments +* +*-a*+, +*--all*+: If given removes all finished downloads. + +==== count +The index of the download to cancel. [[forward]] === forward diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 4062102fc..717c523b2 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -915,7 +915,7 @@ class CommandDispatcher: """Download a given URL, or current page if no URL given. Args: - url: The URL to download, or None to download current page. + url: The URL to download. If not given, download the current page. dest: The file path to write the download to, or None to ask. """ download_manager = objreg.get('download-manager', scope='window', diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 25fe19503..6119aee7f 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -833,7 +833,7 @@ class DownloadManager(QAbstractListModel): """Remove the last/[count]th finished download. Args: - all: Whether to remove all finished downloads. + all_: If given removes all finished downloads. count: The index of the download to cancel. """ finished_items = [d for d in self.downloads if d.done] From 658ab70e984d85efd4566f37c43690191dd0a22d Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Wed, 11 Feb 2015 22:13:29 +0100 Subject: [PATCH 08/17] :download-open now also checks whether download was successful. --- 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 6119aee7f..c602bd9cf 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -762,7 +762,7 @@ class DownloadManager(QAbstractListModel): Args: count: The index of the download to cancel. """ - finished_items = [d for d in self.downloads if d.done] + finished_items = [d for d in self.downloads if d.done and d.successful] try: download = finished_items[count - 1] except IndexError: From 91f70566494694577d607ab4888225d5b77c1a41 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 20:43:13 +0100 Subject: [PATCH 09/17] Added indexes to download view. --- qutebrowser/browser/downloads.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index c602bd9cf..814c7c8f9 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -159,6 +159,7 @@ class DownloadItem(QObject): Attributes: done: Whether the download is finished. stats: A DownloadItemStats object. + index: The index of the download in the view. successful: Whether the download has completed sucessfully. error_msg: The current error message, or None autoclose: Whether to close the associated file if the download is @@ -206,6 +207,7 @@ class DownloadItem(QObject): self.done = False self.stats = DownloadItemStats(self) self.stats.updated.connect(self.data_changed) + self.index = 0 self.autoclose = True self.reply = None self._buffer = io.BytesIO() @@ -238,8 +240,9 @@ class DownloadItem(QObject): else: errmsg = " - {}".format(self.error_msg) if all(e is None for e in (perc, remaining, self.stats.total)): - return ('{name} [{speed:>10}|{down}]{errmsg}'.format( - name=self.basename, speed=speed, down=down, errmsg=errmsg)) + return ('{index}: {name} [{speed:>10}|{down}]{errmsg}'.format( + index=self.index, name=self.basename, speed=speed, + down=down, errmsg=errmsg)) if perc is None: perc = '??' else: @@ -250,14 +253,15 @@ class DownloadItem(QObject): remaining = utils.format_seconds(remaining) total = utils.format_size(self.stats.total, suffix='B') if self.done: - return ('{name} [{perc:>2}%|{total}]{errmsg}'.format( - name=self.basename, perc=perc, total=total, - errmsg=errmsg)) + return ('{index}: {name} [{perc:>2}%|{total}]{errmsg}'.format( + index=self.index, name=self.basename, perc=perc, + total=total, errmsg=errmsg)) else: - return ('{name} [{speed:>10}|{remaining:>5}|{perc:>2}%|' + return ('{index}: {name} [{speed:>10}|{remaining:>5}|{perc:>2}%|' '{down}/{total}]{errmsg}'.format( - name=self.basename, speed=speed, remaining=remaining, - perc=perc, down=down, total=total, errmsg=errmsg)) + index=self.index, name=self.basename, speed=speed, + remaining=remaining, perc=perc, down=down, + total=total, errmsg=errmsg)) def _create_fileobj(self): """Creates a file object using the internal filename.""" @@ -707,6 +711,7 @@ class DownloadManager(QAbstractListModel): download.do_retry.connect(self.fetch) download.basename = suggested_filename idx = len(self.downloads) + 1 + download.index = idx self.beginInsertRows(QModelIndex(), idx, idx) self.downloads.append(download) self.endInsertRows() @@ -862,6 +867,7 @@ class DownloadManager(QAbstractListModel): del self.downloads[idx] self.endRemoveRows() download.deleteLater() + self.update_indexes() def remove_items(self, downloads): """Remove an iterable of downloads.""" @@ -891,6 +897,12 @@ class DownloadManager(QAbstractListModel): download.deleteLater() self.endRemoveRows() + def update_indexes(self): + """Update indexes of all DownloadItems""" + for i, d in enumerate(self.downloads, 1): + if not d.index == i: + d.index = i + def headerData(self, section, orientation, role): """Simple constant header.""" if (section == 0 and orientation == Qt.Horizontal and From 1f39200b2810f0e97bbc1501211ce96e46b958f3 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 21:05:53 +0100 Subject: [PATCH 10/17] :download-open and :download-remove now complains if you try to execute on a download that is not done. --- qutebrowser/browser/downloads.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 814c7c8f9..ed3eb8be1 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -767,11 +767,12 @@ class DownloadManager(QAbstractListModel): Args: count: The index of the download to cancel. """ - finished_items = [d for d in self.downloads if d.done and d.successful] try: - download = finished_items[count - 1] + download = self.downloads[count - 1] except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) + if not download.done and not download.successful: + raise cmdexc.CommandError("Download {} is not done!".format(count)) download.open_file() @pyqtSlot(QNetworkRequest, QNetworkReply) @@ -841,11 +842,17 @@ class DownloadManager(QAbstractListModel): all_: If given removes all finished downloads. count: The index of the download to cancel. """ - finished_items = [d for d in self.downloads if d.done] if all_: + finished_items = [d for d in self.downloads if d.done] self.remove_items(finished_items) else: - self.remove_item(finished_items[count - 1]) + try: + download = self.downloads[count - 1] + except IndexError: + raise cmdexc.CommandError("There's no download {}!".format(count)) + if not download.done: + raise cmdexc.CommandError("Download {} is not done!".format(count)) + self.remove_item(download) def last_index(self): """Get the last index in the model. From dd995c434c4cf2e26f5a1c6ed8c21124e6e33718 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 21:17:23 +0100 Subject: [PATCH 11/17] :download-cancel now only cancels downloads that are done. --- qutebrowser/browser/downloads.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index ed3eb8be1..c8a714c37 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -748,6 +748,8 @@ class DownloadManager(QAbstractListModel): download = self.downloads[count - 1] except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) + if download.done: + raise cmdexc.CommandError("Download {} is already done!".format(count)) download.cancel() @cmdutils.register(instance='download-manager', scope='window', From 8cd5f9e6d1ef8af7f69fef924fcb45c726188045 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 22:20:22 +0100 Subject: [PATCH 12/17] Implemented :download-delete. --- qutebrowser/browser/downloads.py | 34 +++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index c8a714c37..17b661d51 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -358,16 +358,19 @@ class DownloadItem(QObject): self.reply = None if self.fileobj is not None: self.fileobj.close() - try: - if (self._filename is not None and os.path.exists(self._filename) - and remove_data): - os.remove(self._filename) - except OSError: - log.downloads.exception("Failed to remove partial file") + if remove_data: + self.delete() self.done = True self.finished.emit() self.data_changed.emit() + def delete(self): + try: + if (self._filename is not None and os.path.exists(self._filename)): + os.remove(self._filename) + except OSError: + log.downloads.exception("Failed to remove partial file") + def retry(self): """Retry a failed download.""" self.cancel() @@ -749,9 +752,26 @@ class DownloadManager(QAbstractListModel): except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) if download.done: - raise cmdexc.CommandError("Download {} is already done!".format(count)) + raise cmdexc.CommandError("Download {} is already done!" + .format(count)) download.cancel() + @cmdutils.register(instance='download-manager', scope='window') + def download_delete(self, count: {'special': 'count'}=0): + """Delete the last/[count]th download from disk. + + Args: + count: The index of the download to cancel. + """ + try: + download = self.downloads[count - 1] + except IndexError: + raise cmdexc.CommandError("There's no download {}!".format(count)) + if not download.successful: + raise cmdexc.CommandError("Download {} is not done!".format(count)) + download.delete() + self.remove_item(download) + @cmdutils.register(instance='download-manager', scope='window', deprecated="Use :download instead.") def cancel_download(self, count: {'special': 'count'}=1): From 9f0658f191963e83343b89ccb8f39292228e6f71 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 22:21:30 +0100 Subject: [PATCH 13/17] Minor fixes. --- qutebrowser/browser/downloads.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 17b661d51..d2d4ad1d7 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -784,7 +784,7 @@ class DownloadManager(QAbstractListModel): @cmdutils.register(instance='download-manager', scope='window') def download_open(self, count: {'special': 'count'}=0): - """Open the last/[count]th finished download. + """Open the last/[count]th download. Args: count: The index of the download to cancel. @@ -793,7 +793,7 @@ class DownloadManager(QAbstractListModel): download = self.downloads[count - 1] except IndexError: raise cmdexc.CommandError("There's no download {}!".format(count)) - if not download.done and not download.successful: + if not download.successful: raise cmdexc.CommandError("Download {} is not done!".format(count)) download.open_file() @@ -858,7 +858,7 @@ class DownloadManager(QAbstractListModel): @cmdutils.register(instance='download-manager', scope='window') def download_remove(self, all_: {'name': 'all'}=False, count: {'special': 'count'}=0): - """Remove the last/[count]th finished download. + """Remove the last/[count]th download from the list. Args: all_: If given removes all finished downloads. From dfb801a0b715e88378fd956063d7ae358e34531a Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 23:29:05 +0100 Subject: [PATCH 14/17] dataChanged is now emited in update_indexes. --- qutebrowser/browser/downloads.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index d2d4ad1d7..b4362c529 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -365,8 +365,9 @@ class DownloadItem(QObject): self.data_changed.emit() def delete(self): + """Delete the downloaded file""" try: - if (self._filename is not None and os.path.exists(self._filename)): + if self._filename is not None and os.path.exists(self._filename): os.remove(self._filename) except OSError: log.downloads.exception("Failed to remove partial file") @@ -871,9 +872,11 @@ class DownloadManager(QAbstractListModel): try: download = self.downloads[count - 1] except IndexError: - raise cmdexc.CommandError("There's no download {}!".format(count)) + raise cmdexc.CommandError("There's no download {}!" + .format(count)) if not download.done: - raise cmdexc.CommandError("Download {} is not done!".format(count)) + raise cmdexc.CommandError("Download {} is not done!" + .format(count)) self.remove_item(download) def last_index(self): @@ -928,9 +931,15 @@ class DownloadManager(QAbstractListModel): def update_indexes(self): """Update indexes of all DownloadItems""" + first_idx = None for i, d in enumerate(self.downloads, 1): - if not d.index == i: - d.index = i + if not first_idx and d.index != i: + first_idx = i - 1 + d.index = i + if first_idx: + model_idx = self.index(first_idx, 0) + qtutils.ensure_valid(model_idx) + self.dataChanged.emit(model_idx, self.last_index()) def headerData(self, section, orientation, role): """Simple constant header.""" From cd5d4f4feeb55d4d657b0c0408e286e1a703bdb8 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Thu, 12 Feb 2015 23:30:31 +0100 Subject: [PATCH 15/17] Regenerated docs. --- README.asciidoc | 2 +- doc/help/commands.asciidoc | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index b679d29a8..d66c060fa 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -130,8 +130,8 @@ Contributors, sorted by the number of commits in descending order: // QUTE_AUTHORS_START * Florian Bruhin * Claude -* ZDarian * Joel Torstensson +* ZDarian * Peter Vilim * John ShaggyTwoDope Jenkins * rikn00 diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 8fd0b7608..2fe38c4d3 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -11,8 +11,9 @@ |<>|Close the current window. |<>|Download a given URL, or current page if no URL given. |<>|Cancel the last/[count]th download. -|<>|Open the last/[count]th finished download. -|<>|Remove the last/[count]th finished download. +|<>|Delete the last/[count]th download from disk. +|<>|Open the last/[count]th download. +|<>|Remove the last/[count]th download from the list. |<>|Go forward in the history of the current tab. |<>|Toggle fullscreen mode. |<>|Show help about a command or setting. @@ -107,9 +108,16 @@ Cancel the last/[count]th download. ==== count The index of the download to cancel. +[[download-delete]] +=== download-delete +Delete the last/[count]th download from disk. + +==== count +The index of the download to cancel. + [[download-open]] === download-open -Open the last/[count]th finished download. +Open the last/[count]th download. ==== count The index of the download to cancel. @@ -118,7 +126,7 @@ The index of the download to cancel. === download-remove Syntax: +:download-remove [*--all*]+ -Remove the last/[count]th finished download. +Remove the last/[count]th download from the list. ==== optional arguments * +*-a*+, +*--all*+: If given removes all finished downloads. From 049a360abc3a77482e20c6d8951e70629a2470ba Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Fri, 13 Feb 2015 12:40:37 +0100 Subject: [PATCH 16/17] Fixed error messages. --- qutebrowser/browser/downloads.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index b4362c529..3026a19aa 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -741,6 +741,16 @@ class DownloadManager(QAbstractListModel): return download + def raise_no_download(self, index): + """Raise an exception that the download doesn't exist + + Args: + index: The index of the download + """ + if not index: + raise cmdexc.CommandError("There's no download!") + raise cmdexc.CommandError("There's no download {}!".format(index)) + @cmdutils.register(instance='download-manager', scope='window') def download_cancel(self, count: {'special': 'count'}=0): """Cancel the last/[count]th download. @@ -751,8 +761,10 @@ class DownloadManager(QAbstractListModel): try: download = self.downloads[count - 1] except IndexError: - raise cmdexc.CommandError("There's no download {}!".format(count)) + self.raise_no_download(count) if download.done: + if not count: + count = len(self.downloads) raise cmdexc.CommandError("Download {} is already done!" .format(count)) download.cancel() @@ -767,8 +779,10 @@ class DownloadManager(QAbstractListModel): try: download = self.downloads[count - 1] except IndexError: - raise cmdexc.CommandError("There's no download {}!".format(count)) + self.raise_no_download(count) if not download.successful: + if not count: + count = len(self.downloads) raise cmdexc.CommandError("Download {} is not done!".format(count)) download.delete() self.remove_item(download) @@ -793,8 +807,10 @@ class DownloadManager(QAbstractListModel): try: download = self.downloads[count - 1] except IndexError: - raise cmdexc.CommandError("There's no download {}!".format(count)) + self.raise_no_download(count) if not download.successful: + if not count: + count = len(self.downloads) raise cmdexc.CommandError("Download {} is not done!".format(count)) download.open_file() @@ -872,9 +888,10 @@ class DownloadManager(QAbstractListModel): try: download = self.downloads[count - 1] except IndexError: - raise cmdexc.CommandError("There's no download {}!" - .format(count)) + self.raise_no_download(count) if not download.done: + if not count: + count = len(self.downloads) raise cmdexc.CommandError("Download {} is not done!" .format(count)) self.remove_item(download) @@ -933,7 +950,7 @@ class DownloadManager(QAbstractListModel): """Update indexes of all DownloadItems""" first_idx = None for i, d in enumerate(self.downloads, 1): - if not first_idx and d.index != i: + if first_idx is not None and d.index != i: first_idx = i - 1 d.index = i if first_idx: From 4d2aa6a4d453ceed87070d5cc94f03dc4d7d64a5 Mon Sep 17 00:00:00 2001 From: Joel Torstensson Date: Sat, 14 Feb 2015 14:11:38 +0100 Subject: [PATCH 17/17] Fixed errors in update_indexes, etc. --- qutebrowser/browser/downloads.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index 3026a19aa..dcbd44cf6 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -741,15 +741,15 @@ class DownloadManager(QAbstractListModel): return download - def raise_no_download(self, index): + def raise_no_download(self, count): """Raise an exception that the download doesn't exist Args: - index: The index of the download + count: The index of the download """ - if not index: + if not count: raise cmdexc.CommandError("There's no download!") - raise cmdexc.CommandError("There's no download {}!".format(index)) + raise cmdexc.CommandError("There's no download {}!".format(count)) @cmdutils.register(instance='download-manager', scope='window') def download_cancel(self, count: {'special': 'count'}=0): @@ -950,10 +950,10 @@ class DownloadManager(QAbstractListModel): """Update indexes of all DownloadItems""" first_idx = None for i, d in enumerate(self.downloads, 1): - if first_idx is not None and d.index != i: + if first_idx is None and d.index != i: first_idx = i - 1 d.index = i - if first_idx: + if first_idx is not None: model_idx = self.index(first_idx, 0) qtutils.ensure_valid(model_idx) self.dataChanged.emit(model_idx, self.last_index())