From 32edd35c7a1a16bb8ba65bcd1ff63857dbf8f862 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 22 Apr 2016 22:43:25 +1200 Subject: [PATCH 1/3] buffer completion: handle deleting items see issue #1443 Allows to use ctrl+d to close tabs from the buffer completion widget when they are selected. Respects current tab settings like whether you can close the last tab in a window. Had to change the `rebuild()` method to use `setData()` when possible because the selection was being lost if the whole model was being rebuilt. Current problems are: 1) When opening a new window while you already the tab completion open on one window a category is added for the new window but new rows in that category aren't picked up. Interesting if you open a third window then close the second window the completion display is now correct... I can see that the model is being updated correctly but I am not sure why that isn't propagating to the view. Not sure whether it is worth looking into (further) either. 2) Bit of duplication of code, it iterates over the window registry twice. Could put everything in one loop but then that would be dependant on the current behaviour of the `tab_closed` signal being called with the relevant `tabbed_browser` still existing but with the `shutting_down` flag set. 3) I'm still using just the one `rebuild()` method and removing items from the end then calling `setData` on everything rather than having special `on_tab/window_closed` methods (or partial functions) that delete the actual corresponding item. Because if I did that I would also have to special case tab moves etc. --- qutebrowser/completion/models/miscmodels.py | 61 ++++++++++++++++++--- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py index 3b71a6548..a13604b58 100644 --- a/qutebrowser/completion/models/miscmodels.py +++ b/qutebrowser/completion/models/miscmodels.py @@ -23,7 +23,7 @@ from PyQt5.QtCore import Qt, QTimer, pyqtSlot from qutebrowser.browser import webview from qutebrowser.config import config, configdata -from qutebrowser.utils import objreg, log +from qutebrowser.utils import objreg, log, qtutils from qutebrowser.commands import cmdutils from qutebrowser.completion.models import base @@ -153,7 +153,7 @@ class TabCompletionModel(base.BaseCompletionModel): # https://github.com/The-Compiler/qutebrowser/issues/545 # pylint: disable=abstract-method - #IDX_COLUMN = 0 + IDX_COLUMN = 0 URL_COLUMN = 1 TEXT_COLUMN = 2 @@ -204,15 +204,58 @@ class TabCompletionModel(base.BaseCompletionModel): make sure we handled background loads too ... but iterating over a few/few dozen/few hundred tabs doesn't take very long at all. """ - self.removeRows(0, self.rowCount()) + window_count = 0 for win_id in objreg.window_registry: + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window=win_id) + if not tabbed_browser.shutting_down: + window_count = window_count + 1 + + if window_count < self.rowCount(): + self.removeRows(window_count, self.rowCount()-window_count) + + for i, win_id in enumerate(objreg.window_registry): tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) if tabbed_browser.shutting_down: continue - c = self.new_category("{}".format(win_id)) - for i in range(tabbed_browser.count()): - tab = tabbed_browser.widget(i) - self.new_item(c, "{}/{}".format(win_id, i+1), - tab.url().toDisplayString(), - tabbed_browser.page_title(i)) + if i >= self.rowCount(): + c = self.new_category("{}".format(win_id)) + else: + c = self.item(i, 0) + c.setData("{}".format(win_id), Qt.DisplayRole) + if tabbed_browser.count() < c.rowCount(): + c.removeRows(tabbed_browser.count(), + c.rowCount()-tabbed_browser.count()) + for idx in range(tabbed_browser.count()): + tab = tabbed_browser.widget(idx) + if idx >= c.rowCount(): + self.new_item(c, "{}/{}".format(win_id, idx+1), + tab.url().toDisplayString(), + tabbed_browser.page_title(idx)) + else: + c.child(idx, 0).setData("{}/{}".format(win_id, idx+1), + Qt.DisplayRole) + c.child(idx, 1).setData(tab.url().toDisplayString(), + Qt.DisplayRole) + c.child(idx, 2).setData(tabbed_browser.page_title(idx), + Qt.DisplayRole) + + def delete_cur_item(self, completion): + """Delete the selected item. + + Args: + completion: The Completion object to use. + """ + index = completion.currentIndex() + qtutils.ensure_valid(index) + category = index.parent() + qtutils.ensure_valid(category) + index = category.child(index.row(), self.IDX_COLUMN) + win_id, tab_index = index.data().split('/') + win_id = int(win_id) + tab_index = int(tab_index) + + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window=win_id) + tabbed_browser.on_tab_close_requested(tab_index-1) From c228bb263bbf380d867b7d7bc751aefefd07d0c5 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 28 Apr 2016 07:05:55 +0200 Subject: [PATCH 2/3] Update docs --- CHANGELOG.asciidoc | 2 ++ README.asciidoc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index b463f8902..7e3707d40 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -36,6 +36,8 @@ Changed the right. - `:yank` can now yank the pretty/decoded URL by adding `--pretty` - `:navigate` now clears the URL fragment +- `:completion-item-del` (`Ctrl-D`) can now be used in `:buffer` completion to + close a tab Fixed ~~~~~ diff --git a/README.asciidoc b/README.asciidoc index 4e122417e..52cb56215 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -162,12 +162,12 @@ Contributors, sorted by the number of commits in descending order: * Kevin Velghe * Austin Anderson * Panagiotis Ktistakis +* Jimmy * Alexey "Averrin" Nabrodov * avk * ZDarian * Milan Svoboda * John ShaggyTwoDope Jenkins -* Jimmy * Peter Vilim * Clayton Craft * Oliver Caldwell From 2f10ab4e9a0f2780315185b7f7740500eee42c7e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 28 Apr 2016 07:07:49 +0200 Subject: [PATCH 3/3] Clean up coding style --- qutebrowser/completion/models/miscmodels.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py index 657a73c8c..62267d51c 100644 --- a/qutebrowser/completion/models/miscmodels.py +++ b/qutebrowser/completion/models/miscmodels.py @@ -206,10 +206,10 @@ class TabCompletionModel(base.BaseCompletionModel): tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) if not tabbed_browser.shutting_down: - window_count = window_count + 1 + window_count += 1 if window_count < self.rowCount(): - self.removeRows(window_count, self.rowCount()-window_count) + self.removeRows(window_count, self.rowCount() - window_count) for i, win_id in enumerate(objreg.window_registry): tabbed_browser = objreg.get('tabbed-browser', scope='window', @@ -223,15 +223,15 @@ class TabCompletionModel(base.BaseCompletionModel): c.setData("{}".format(win_id), Qt.DisplayRole) if tabbed_browser.count() < c.rowCount(): c.removeRows(tabbed_browser.count(), - c.rowCount()-tabbed_browser.count()) + c.rowCount() - tabbed_browser.count()) for idx in range(tabbed_browser.count()): tab = tabbed_browser.widget(idx) if idx >= c.rowCount(): - self.new_item(c, "{}/{}".format(win_id, idx+1), + self.new_item(c, "{}/{}".format(win_id, idx + 1), tab.url().toDisplayString(), tabbed_browser.page_title(idx)) else: - c.child(idx, 0).setData("{}/{}".format(win_id, idx+1), + c.child(idx, 0).setData("{}/{}".format(win_id, idx + 1), Qt.DisplayRole) c.child(idx, 1).setData(tab.url().toDisplayString(), Qt.DisplayRole) @@ -250,9 +250,7 @@ class TabCompletionModel(base.BaseCompletionModel): qtutils.ensure_valid(category) index = category.child(index.row(), self.IDX_COLUMN) win_id, tab_index = index.data().split('/') - win_id = int(win_id) - tab_index = int(tab_index) tabbed_browser = objreg.get('tabbed-browser', scope='window', - window=win_id) - tabbed_browser.on_tab_close_requested(tab_index-1) + window=int(win_id)) + tabbed_browser.on_tab_close_requested(int(tab_index) - 1)