From 9d0dfd5726faa81613144bbe0d07c6b025ba9ece Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Sat, 7 Oct 2017 15:18:57 +0200
Subject: [PATCH 01/99] Always run best-matching command
---
qutebrowser/commands/runners.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py
index 9d480cc5d..21ec41e58 100644
--- a/qutebrowser/commands/runners.py
+++ b/qutebrowser/commands/runners.py
@@ -218,7 +218,7 @@ class CommandParser:
for valid_command in cmdutils.cmd_dict:
if valid_command.find(cmdstr) == 0:
matches.append(valid_command)
- if len(matches) == 1:
+ if len(matches) >= 1:
cmdstr = matches[0]
return cmdstr
From 71048a1b55fe3383f98f54237558e665b91be52b Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Sat, 7 Oct 2017 15:42:42 +0200
Subject: [PATCH 02/99] Add (and use) completion.use_best_match config
---
qutebrowser/commands/runners.py | 4 +++-
qutebrowser/config/configdata.yml | 5 +++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py
index 21ec41e58..d6a12e2c7 100644
--- a/qutebrowser/commands/runners.py
+++ b/qutebrowser/commands/runners.py
@@ -218,7 +218,9 @@ class CommandParser:
for valid_command in cmdutils.cmd_dict:
if valid_command.find(cmdstr) == 0:
matches.append(valid_command)
- if len(matches) >= 1:
+ if len(matches) == 1:
+ cmdstr = matches[0]
+ elif len(matches) > 1 and config.val.completion.use_best_match:
cmdstr = matches[0]
return cmdstr
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 56b58f8e1..acee49f40 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -656,6 +656,11 @@ completion.web_history_max_items:
0: no history / -1: unlimited
+completion.use_best_match:
+ type: Bool
+ default: true
+ desc: Whether to execute the best-matching command on a partial match.
+
## downloads
downloads.location.directory:
From 0578349e290e8292f4fbd3ba2890edb7a6ce91da Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Mon, 9 Oct 2017 11:06:25 +0200
Subject: [PATCH 03/99] Default completion.use_best_match to false
---
qutebrowser/config/configdata.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index acee49f40..e3c6c6e7a 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -658,7 +658,7 @@ completion.web_history_max_items:
completion.use_best_match:
type: Bool
- default: true
+ default: false
desc: Whether to execute the best-matching command on a partial match.
## downloads
From 019d66a4c626d9a8ee8a5e3a026eb680347598a0 Mon Sep 17 00:00:00 2001
From: Joakim Reinert
Date: Wed, 27 Sep 2017 13:39:33 +0200
Subject: [PATCH 04/99] add adjustable delay for completion updates
---
qutebrowser/completion/completer.py | 4 +++-
qutebrowser/config/configdata.yml | 7 +++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py
index efd6b3490..23c77b59a 100644
--- a/qutebrowser/completion/completer.py
+++ b/qutebrowser/completion/completer.py
@@ -196,6 +196,8 @@ class Completer(QObject):
For performance reasons we don't want to block here, instead we do this
in the background.
+
+ We delay the update only if we've already input some text.
"""
if (self._cmd.cursorPosition() == self._last_cursor_pos and
self._cmd.text() == self._last_text):
@@ -203,7 +205,7 @@ class Completer(QObject):
"changes.")
else:
log.completion.debug("Scheduling completion update.")
- self._timer.start()
+ self._timer.start(config.val.completion.delay if self._last_text else 0)
self._last_cursor_pos = self._cmd.cursorPosition()
self._last_text = self._cmd.text()
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index f500a2f0f..71ab4c8b0 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -656,6 +656,13 @@ completion.web_history_max_items:
0: no history / -1: unlimited
+completion.delay:
+ default: 0
+ type:
+ name: Int
+ minval: 0
+ desc: Delay in ms before updating completions after typing a character
+
## downloads
downloads.location.directory:
From 0226025308819df0381887e42ec14287d9e7c65b Mon Sep 17 00:00:00 2001
From: Joakim Reinert
Date: Wed, 27 Sep 2017 13:41:06 +0200
Subject: [PATCH 05/99] add adjustable amount of chars required to update
completions
---
qutebrowser/completion/completer.py | 11 +++++++++--
qutebrowser/config/configdata.yml | 7 +++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py
index 23c77b59a..aa7f170a9 100644
--- a/qutebrowser/completion/completer.py
+++ b/qutebrowser/completion/completer.py
@@ -197,9 +197,16 @@ class Completer(QObject):
For performance reasons we don't want to block here, instead we do this
in the background.
- We delay the update only if we've already input some text.
+ We delay the update only if we've already input some text and ignore
+ updates if the text is shorter than completion.min_chars (unless we're
+ hitting backspace in which case updates won't be ignored).
"""
- if (self._cmd.cursorPosition() == self._last_cursor_pos and
+ cmd, _sep, rest = self._cmd.text().partition(' ')
+ if (0 < len(rest) < config.val.completion.min_chars and
+ self._cmd.cursorPosition() > self._last_cursor_pos):
+ log.completion.debug("Ignoring update because the length of "
+ "the text is less than completion.min_chars.")
+ elif (self._cmd.cursorPosition() == self._last_cursor_pos and
self._cmd.text() == self._last_text):
log.completion.debug("Ignoring update because there were no "
"changes.")
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 71ab4c8b0..23349de29 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -663,6 +663,13 @@ completion.delay:
minval: 0
desc: Delay in ms before updating completions after typing a character
+completion.min_chars:
+ default: 1
+ type:
+ name: Int
+ minval: 1
+ desc: Minimum amount of characters needed to update completions
+
## downloads
downloads.location.directory:
From 5078080bb00f9a8d40ace9810b18eeb751cd7fad Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Tue, 10 Oct 2017 22:02:25 +0200
Subject: [PATCH 06/99] Add (not fully working) tests for use_best_match
---
tests/unit/config/test_configcommands.py | 31 +++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py
index 21ec040f7..ed69e7c32 100644
--- a/tests/unit/config/test_configcommands.py
+++ b/tests/unit/config/test_configcommands.py
@@ -25,7 +25,7 @@ import pytest
from PyQt5.QtCore import QUrl, QProcess
from qutebrowser.config import configcommands
-from qutebrowser.commands import cmdexc
+from qutebrowser.commands import cmdexc, runners
from qutebrowser.utils import usertypes
from qutebrowser.misc import objects
@@ -532,3 +532,32 @@ class TestBind:
"""
with pytest.raises(cmdexc.CommandError, match=expected):
commands.unbind(key, mode=mode)
+
+
+class TestCompletions:
+
+ """Tests for completions.use_best_match."""
+
+ def test_dont_use_best_match(self, config_stub, monkeypatch):
+ """Test multiple completion options with use_best_match set to false.
+
+ Should raise NoSuchCommandError
+ """
+ config_stub.val.completion.use_best_match = False
+ monkeypatch.setattr('qutebrowser.config', config_stub)
+ parser = runners.CommandParser(partial_match=True)
+
+ with pytest.raises(cmdexc.NoSuchCommandError):
+ result = parser.parse('do')
+
+ def test_use_best_match(self, config_stub, monkeypatch):
+ """Test multiple completion options with use_best_match set to true.
+
+ The resulting command should be the best match
+ """
+ config_stub.val.completion.use_best_match = True
+ monkeypatch.setattr('qutebrowser.config', config_stub)
+ parser = runners.CommandParser(partial_match=True)
+
+ result = parser.parse('do')
+ assert result.cmd.name == 'download'
From 787e3db3d50aa5d42227f708477a01526b015416 Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Tue, 10 Oct 2017 22:51:40 +0200
Subject: [PATCH 07/99] Move tests to test_runners.py
---
tests/unit/commands/test_runners.py | 29 ++++++++++++++++++++++
tests/unit/config/test_configcommands.py | 31 +-----------------------
2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/tests/unit/commands/test_runners.py b/tests/unit/commands/test_runners.py
index 75558b390..daa8541e8 100644
--- a/tests/unit/commands/test_runners.py
+++ b/tests/unit/commands/test_runners.py
@@ -74,3 +74,32 @@ class TestCommandParser:
parser = runners.CommandParser(partial_match=True)
result = parser.parse('message-i')
assert result.cmd.name == 'message-info'
+
+
+class TestCompletions:
+
+ """Tests for completions.use_best_match."""
+
+ def test_dont_use_best_match(self, config_stub, monkeypatch):
+ """Test multiple completion options with use_best_match set to false.
+
+ Should raise NoSuchCommandError
+ """
+ config_stub.val.completion.use_best_match = False
+ monkeypatch.setattr('qutebrowser.config', config_stub)
+ parser = runners.CommandParser(partial_match=True)
+
+ with pytest.raises(cmdexc.NoSuchCommandError):
+ result = parser.parse('do')
+
+ def test_use_best_match(self, config_stub, monkeypatch):
+ """Test multiple completion options with use_best_match set to true.
+
+ The resulting command should be the best match
+ """
+ config_stub.val.completion.use_best_match = True
+ monkeypatch.setattr('qutebrowser.config', config_stub)
+ parser = runners.CommandParser(partial_match=True)
+
+ result = parser.parse('do')
+ assert result.cmd.name == 'download'
diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py
index ed69e7c32..21ec040f7 100644
--- a/tests/unit/config/test_configcommands.py
+++ b/tests/unit/config/test_configcommands.py
@@ -25,7 +25,7 @@ import pytest
from PyQt5.QtCore import QUrl, QProcess
from qutebrowser.config import configcommands
-from qutebrowser.commands import cmdexc, runners
+from qutebrowser.commands import cmdexc
from qutebrowser.utils import usertypes
from qutebrowser.misc import objects
@@ -532,32 +532,3 @@ class TestBind:
"""
with pytest.raises(cmdexc.CommandError, match=expected):
commands.unbind(key, mode=mode)
-
-
-class TestCompletions:
-
- """Tests for completions.use_best_match."""
-
- def test_dont_use_best_match(self, config_stub, monkeypatch):
- """Test multiple completion options with use_best_match set to false.
-
- Should raise NoSuchCommandError
- """
- config_stub.val.completion.use_best_match = False
- monkeypatch.setattr('qutebrowser.config', config_stub)
- parser = runners.CommandParser(partial_match=True)
-
- with pytest.raises(cmdexc.NoSuchCommandError):
- result = parser.parse('do')
-
- def test_use_best_match(self, config_stub, monkeypatch):
- """Test multiple completion options with use_best_match set to true.
-
- The resulting command should be the best match
- """
- config_stub.val.completion.use_best_match = True
- monkeypatch.setattr('qutebrowser.config', config_stub)
- parser = runners.CommandParser(partial_match=True)
-
- result = parser.parse('do')
- assert result.cmd.name == 'download'
From 052c527e4c8cafc576691fa49496d4397dca5a6a Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Tue, 10 Oct 2017 22:52:57 +0200
Subject: [PATCH 08/99] Avoid explicit config monkeypatching
---
tests/unit/commands/test_runners.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tests/unit/commands/test_runners.py b/tests/unit/commands/test_runners.py
index daa8541e8..4497cb843 100644
--- a/tests/unit/commands/test_runners.py
+++ b/tests/unit/commands/test_runners.py
@@ -80,25 +80,23 @@ class TestCompletions:
"""Tests for completions.use_best_match."""
- def test_dont_use_best_match(self, config_stub, monkeypatch):
+ def test_dont_use_best_match(self, config_stub):
"""Test multiple completion options with use_best_match set to false.
Should raise NoSuchCommandError
"""
config_stub.val.completion.use_best_match = False
- monkeypatch.setattr('qutebrowser.config', config_stub)
parser = runners.CommandParser(partial_match=True)
with pytest.raises(cmdexc.NoSuchCommandError):
result = parser.parse('do')
- def test_use_best_match(self, config_stub, monkeypatch):
+ def test_use_best_match(self, config_stub):
"""Test multiple completion options with use_best_match set to true.
The resulting command should be the best match
"""
config_stub.val.completion.use_best_match = True
- monkeypatch.setattr('qutebrowser.config', config_stub)
parser = runners.CommandParser(partial_match=True)
result = parser.parse('do')
From c8d41a4f879f2acfc5304d94285f3517c784ebe4 Mon Sep 17 00:00:00 2001
From: Luca Benci
Date: Tue, 10 Oct 2017 22:54:49 +0200
Subject: [PATCH 09/99] Make tests pass
---
tests/unit/commands/test_runners.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/commands/test_runners.py b/tests/unit/commands/test_runners.py
index 4497cb843..fad96c558 100644
--- a/tests/unit/commands/test_runners.py
+++ b/tests/unit/commands/test_runners.py
@@ -100,4 +100,4 @@ class TestCompletions:
parser = runners.CommandParser(partial_match=True)
result = parser.parse('do')
- assert result.cmd.name == 'download'
+ assert result.cmd.name == 'download-cancel'
From b7061dc7db4cd4e9d44fc21aedf3a41487e4cbcf Mon Sep 17 00:00:00 2001
From: Michael Hoang
Date: Wed, 4 Oct 2017 04:33:23 +1100
Subject: [PATCH 10/99] Separate logic for resolving buffers from index
---
qutebrowser/browser/commands.py | 74 +++++++++++++++++++--------------
1 file changed, 43 insertions(+), 31 deletions(-)
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 7a8825720..7a3bbe159 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -1009,40 +1009,27 @@ class CommandDispatcher:
raise cmdexc.CommandError(e)
self._open(url, tab, bg, window)
- @cmdutils.register(instance='command-dispatcher', scope='window')
- @cmdutils.argument('index', completion=miscmodels.buffer)
- @cmdutils.argument('count', count=True)
- def buffer(self, index=None, count=None):
- """Select tab by index or url/title best match.
-
- Focuses window if necessary when index is given. If both index and
- count are given, use count.
+ def _resolve_buffer_index(self, index):
+ """Resolves a buffer index to the tabbedbrowser and tab.
Args:
- index: The [win_id/]index of the tab to focus. Or a substring
+ index: The [win_id/]index of the tab to be selected. Or a substring
in which case the closest match will be focused.
- count: The tab index to focus, starting with 1.
"""
- if count is not None:
- index_parts = [count]
- elif index is None:
- raise cmdexc.CommandError("buffer: Either a count or the argument "
- "index must be specified.")
- else:
- index_parts = index.split('/', 1)
+ index_parts = index.split('/', 1)
- try:
- for part in index_parts:
- int(part)
- except ValueError:
- model = miscmodels.buffer()
- model.set_pattern(index)
- if model.count() > 0:
- index = model.data(model.first_item())
- index_parts = index.split('/', 1)
- else:
- raise cmdexc.CommandError(
- "No matching tab for: {}".format(index))
+ try:
+ for part in index_parts:
+ int(part)
+ except ValueError:
+ model = miscmodels.buffer()
+ model.set_pattern(index)
+ if model.count() > 0:
+ index = model.data(model.first_item())
+ index_parts = index.split('/', 1)
+ else:
+ raise cmdexc.CommandError(
+ "No matching tab for: {}".format(index))
if len(index_parts) == 2:
win_id = int(index_parts[0])
@@ -1066,10 +1053,35 @@ class CommandDispatcher:
raise cmdexc.CommandError(
"There's no tab with index {}!".format(idx))
- window = objreg.window_registry[win_id]
+ return (tabbed_browser, tabbed_browser.widget(idx-1))
+
+ @cmdutils.register(instance='command-dispatcher', scope='window')
+ @cmdutils.argument('index', completion=miscmodels.buffer)
+ @cmdutils.argument('count', count=True)
+ def buffer(self, index=None, count=None):
+ """Select tab by index or url/title best match.
+
+ Focuses window if necessary when index is given. If both index and
+ count are given, use count.
+
+ Args:
+ index: The [win_id/]index of the tab to focus. Or a substring
+ in which case the closest match will be focused.
+ count: The tab index to focus, starting with 1.
+ """
+ if count is None and index is None:
+ raise cmdexc.CommandError("buffer: Either a count or the argument "
+ "index must be specified.")
+
+ if count is not None:
+ index = str(count)
+
+ tabbed_browser, tab = self._resolve_buffer_index(index)
+
+ window = tabbed_browser.window()
window.activateWindow()
window.raise_()
- tabbed_browser.setCurrentIndex(idx-1)
+ tabbed_browser.setCurrentWidget(tab)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('index', choices=['last'])
From 67437a0d5d78736e279927b195f27ceed23230a2 Mon Sep 17 00:00:00 2001
From: Michael Hoang
Date: Wed, 4 Oct 2017 05:05:00 +1100
Subject: [PATCH 11/99] Add :tab-give and :tab-take commands and tests
---
doc/help/commands.asciidoc | 21 +++++++++
qutebrowser/browser/commands.py | 33 ++++++++++++++
qutebrowser/completion/models/miscmodels.py | 19 ++++++++
tests/end2end/features/tabs.feature | 50 +++++++++++++++++++++
4 files changed, 123 insertions(+)
diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc
index 137bf3ef8..e166e51eb 100644
--- a/doc/help/commands.asciidoc
+++ b/doc/help/commands.asciidoc
@@ -85,11 +85,13 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|<>|Close the current/[count]th tab.
|<>|Detach the current tab to its own window.
|<>|Select the tab given as argument/[count].
+|<>|Give the current tab to another window.
|<>|Move the current tab according to the argument and [count].
|<>|Switch to the next tab, or switch [count] tabs forward.
|<>|Close all tabs except for the current one.
|<>|Pin/Unpin the current/[count]th tab.
|<>|Switch to the previous tab, or switch [count] tabs back.
+|<>|Take a tab from another window.
|<>|Unbind a keychain.
|<>|Re-open a closed tab.
|<>|Show version information.
@@ -967,6 +969,15 @@ If neither count nor index are given, it behaves like tab-next. If both are give
==== count
The tab index to focus, starting with 1.
+[[tab-give]]
+=== tab-give
+Syntax: +:tab-give 'win-id'+
+
+Give the current tab to another window.
+
+==== positional arguments
+* +'win-id'+: The window ID of the window to give the current tab to.
+
[[tab-move]]
=== tab-move
Syntax: +:tab-move ['index']+
@@ -1019,6 +1030,16 @@ Switch to the previous tab, or switch [count] tabs back.
==== count
How many tabs to switch back.
+[[tab-take]]
+=== tab-take
+Syntax: +:tab-take 'index'+
+
+Take a tab from another window.
+
+==== positional arguments
+* +'index'+: The [win_id/]index of the tab to take. Or a substring in which case the closest match will be taken.
+
+
[[unbind]]
=== unbind
Syntax: +:unbind [*--mode* 'mode'] 'key'+
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 7a3bbe159..b7ed82af9 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -523,6 +523,39 @@ class CommandDispatcher:
cur_widget = self._current_widget()
self._tabbed_browser.close_tab(cur_widget, add_undo=False)
+ @cmdutils.register(instance='command-dispatcher', scope='window')
+ @cmdutils.argument('index', completion=miscmodels.buffer)
+ def tab_take(self, index):
+ """Take a tab from another window.
+
+ Args:
+ index: The [win_id/]index of the tab to take. Or a substring
+ in which case the closest match will be taken.
+ """
+ tabbed_browser, tab = self._resolve_buffer_index(index)
+
+ if tabbed_browser is self._tabbed_browser:
+ raise cmdexc.CommandError("Can't take a tab from the same window")
+
+ self._open(tab.url(), tab=True)
+ tabbed_browser.close_tab(tab, add_undo=False)
+
+ @cmdutils.register(instance='command-dispatcher', scope='window')
+ @cmdutils.argument('win_id', completion=miscmodels.window)
+ def tab_give(self, win_id: int):
+ """Give the current tab to another window.
+
+ Args:
+ win_id: The window ID of the window to give the current tab to.
+ """
+ if win_id == self._win_id:
+ raise cmdexc.CommandError("Can't give a tab to the same window")
+
+ tabbed_browser = objreg.get('tabbed-browser', scope='window',
+ window=win_id)
+ tabbed_browser.tabopen(self._current_url())
+ self._tabbed_browser.close_tab(self._current_widget(), add_undo=False)
+
def _back_forward(self, tab, bg, window, count, forward):
"""Helper function for :back/:forward."""
history = self._current_widget().history
diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py
index 3244c7bf3..9b7783e4f 100644
--- a/qutebrowser/completion/models/miscmodels.py
+++ b/qutebrowser/completion/models/miscmodels.py
@@ -122,3 +122,22 @@ def buffer(*, info=None): # pylint: disable=unused-argument
model.add_category(cat)
return model
+
+
+def window(*, info=None): # pylint: disable=unused-argument
+ """A model to complete on all open windows."""
+ model = completionmodel.CompletionModel(column_widths=(6, 30, 64))
+
+ windows = []
+
+ for win_id in objreg.window_registry:
+ tabbed_browser = objreg.get('tabbed-browser', scope='window',
+ window=win_id)
+ tab_titles = (tab.title() for tab in tabbed_browser.widgets())
+ windows.append(("{}".format(win_id),
+ objreg.window_registry[win_id].windowTitle(),
+ ", ".join(tab_titles)))
+
+ model.add_category(listcategory.ListCategory("Windows", windows))
+
+ return model
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
index b510a4f66..ba20f9a75 100644
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -1010,6 +1010,56 @@ Feature: Tab management
And I run :buffer "1/2/3"
Then the error "No matching tab for: 1/2/3" should be shown
+ # :tab-take
+
+ @xfail_norun
+ Scenario: Take a tab from another window
+ Given I have a fresh instance
+ When I open data/numbers/1.txt
+ And I open data/numbers/2.txt in a new window
+ And I run :tab-take 0/1
+ Then the session should look like:
+ windows:
+ - tabs:
+ - history:
+ - url: about:blank
+ - tabs:
+ - history:
+ - url: http://localhost:*/data/numbers/2.txt
+ - history:
+ - url: http://localhost:*/data/numbers/1.txt
+
+ Scenario: Take a tab from the same window
+ Given I have a fresh instance
+ When I open data/numbers/1.txt
+ And I run :tab-take 0/1
+ Then the error "Can't take a tab from the same window" should be shown
+
+ # :tab-give
+
+ @xfail_norun
+ Scenario: Give a tab to another window
+ Given I have a fresh instance
+ When I open data/numbers/1.txt
+ And I open data/numbers/2.txt in a new window
+ And I run :tab-give 0
+ Then the session should look like:
+ windows:
+ - tabs:
+ - history:
+ - url: http://localhost:*/data/numbers/1.txt
+ - history:
+ - url: http://localhost:*/data/numbers/2.txt
+ - tabs:
+ - history:
+ - url: about:blank
+
+ Scenario: Give a tab to the same window
+ Given I have a fresh instance
+ When I open data/numbers/1.txt
+ And I run :tab-give 0
+ Then the error "Can't give a tab to the same window" should be shown
+
# Other
Scenario: Using :tab-next after closing last tab (#1448)
From 29f66dcd9591016585602566af46cbbbb63efb2b Mon Sep 17 00:00:00 2001
From: Michael Hoang
Date: Wed, 4 Oct 2017 13:35:40 +1100
Subject: [PATCH 12/99] Merge :tab-detach with :tab-give
---
doc/help/commands.asciidoc | 13 ++++-----
qutebrowser/browser/commands.py | 28 +++++++++---------
tests/end2end/features/invoke.feature | 4 +--
tests/end2end/features/tabs.feature | 42 +++++++++++++--------------
4 files changed, 41 insertions(+), 46 deletions(-)
diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc
index e166e51eb..fed4e88d4 100644
--- a/doc/help/commands.asciidoc
+++ b/doc/help/commands.asciidoc
@@ -83,9 +83,8 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|<>|Stop loading in the current/[count]th tab.
|<>|Duplicate the current tab.
|<>|Close the current/[count]th tab.
-|<>|Detach the current tab to its own window.
|<>|Select the tab given as argument/[count].
-|<>|Give the current tab to another window.
+|<>|Give the current tab to a new or existing window if win_id given.
|<>|Move the current tab according to the argument and [count].
|<>|Switch to the next tab, or switch [count] tabs forward.
|<>|Close all tabs except for the current one.
@@ -948,10 +947,6 @@ Close the current/[count]th tab.
==== count
The tab index to close
-[[tab-detach]]
-=== tab-detach
-Detach the current tab to its own window.
-
[[tab-focus]]
=== tab-focus
Syntax: +:tab-focus ['index']+
@@ -971,9 +966,11 @@ The tab index to focus, starting with 1.
[[tab-give]]
=== tab-give
-Syntax: +:tab-give 'win-id'+
+Syntax: +:tab-give ['win-id']+
-Give the current tab to another window.
+Give the current tab to a new or existing window if win_id given.
+
+If no win_id is given, the tab will get detached into a new window.
==== positional arguments
* +'win-id'+: The window ID of the window to give the current tab to.
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index b7ed82af9..a3eed85df 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -513,16 +513,6 @@ class CommandDispatcher:
new_tabbed_browser.set_tab_pinned(newtab, curtab.data.pinned)
return newtab
- @cmdutils.register(instance='command-dispatcher', scope='window')
- def tab_detach(self):
- """Detach the current tab to its own window."""
- if self._count() < 2:
- raise cmdexc.CommandError("Cannot detach one tab.")
- url = self._current_url()
- self._open(url, window=True)
- cur_widget = self._current_widget()
- self._tabbed_browser.close_tab(cur_widget, add_undo=False)
-
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('index', completion=miscmodels.buffer)
def tab_take(self, index):
@@ -542,8 +532,10 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('win_id', completion=miscmodels.window)
- def tab_give(self, win_id: int):
- """Give the current tab to another window.
+ def tab_give(self, win_id: int = None):
+ """Give the current tab to a new or existing window if win_id given.
+
+ If no win_id is given, the tab will get detached into a new window.
Args:
win_id: The window ID of the window to give the current tab to.
@@ -551,8 +543,16 @@ class CommandDispatcher:
if win_id == self._win_id:
raise cmdexc.CommandError("Can't give a tab to the same window")
- tabbed_browser = objreg.get('tabbed-browser', scope='window',
- window=win_id)
+ if win_id is not None:
+ tabbed_browser = objreg.get('tabbed-browser', scope='window',
+ window=win_id)
+ else:
+ if self._count() < 2:
+ raise cmdexc.CommandError("Cannot detach from a window with "
+ "only one tab")
+
+ tabbed_browser = self._new_tabbed_browser(
+ private=self._tabbed_browser.private)
tabbed_browser.tabopen(self._current_url())
self._tabbed_browser.close_tab(self._current_widget(), add_undo=False)
diff --git a/tests/end2end/features/invoke.feature b/tests/end2end/features/invoke.feature
index d343db593..9be38659e 100644
--- a/tests/end2end/features/invoke.feature
+++ b/tests/end2end/features/invoke.feature
@@ -74,12 +74,12 @@ Feature: Invoking a new process
# issue #1060
- Scenario: Using target_window = first-opened after tab-detach
+ Scenario: Using target_window = first-opened after tab-give
When I set new_instance_open_target to tab
And I set new_instance_open_target_window to first-opened
And I open data/title.html
And I open data/search.html in a new tab
- And I run :tab-detach
+ And I run :tab-give
And I wait until data/search.html is loaded
And I open data/hello.txt as a URL
Then the session should look like:
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
index ba20f9a75..4c35547dc 100644
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -638,28 +638,6 @@ Feature: Tab management
And I run :tab-clone
Then no crash should happen
- # :tab-detach
-
- Scenario: Detaching a tab
- When I open data/numbers/1.txt
- And I open data/numbers/2.txt in a new tab
- And I run :tab-detach
- And I wait until data/numbers/2.txt is loaded
- Then the session should look like:
- windows:
- - tabs:
- - history:
- - url: about:blank
- - url: http://localhost:*/data/numbers/1.txt
- - tabs:
- - history:
- - url: http://localhost:*/data/numbers/2.txt
-
- Scenario: Detach tab from window with only one tab
- When I open data/hello.txt
- And I run :tab-detach
- Then the error "Cannot detach one tab." should be shown
-
# :undo
Scenario: Undo without any closed tabs
@@ -1060,6 +1038,26 @@ Feature: Tab management
And I run :tab-give 0
Then the error "Can't give a tab to the same window" should be shown
+ Scenario: Give a tab to a new window
+ When I open data/numbers/1.txt
+ And I open data/numbers/2.txt in a new tab
+ And I run :tab-give
+ And I wait until data/numbers/2.txt is loaded
+ Then the session should look like:
+ windows:
+ - tabs:
+ - history:
+ - url: about:blank
+ - url: http://localhost:*/data/numbers/1.txt
+ - tabs:
+ - history:
+ - url: http://localhost:*/data/numbers/2.txt
+
+ Scenario: Give a tab from window with only one tab
+ When I open data/hello.txt
+ And I run :tab-give
+ Then the error "Cannot detach from a window with only one tab" should be shown
+
# Other
Scenario: Using :tab-next after closing last tab (#1448)
From 249e497d368759d38a8751d0ceb6490c8db22667 Mon Sep 17 00:00:00 2001
From: Michael Hoang
Date: Wed, 11 Oct 2017 17:14:18 +1100
Subject: [PATCH 13/99] Add test for window completion
---
tests/helpers/fixtures.py | 3 +++
tests/helpers/stubs.py | 3 +++
tests/unit/completion/test_models.py | 24 ++++++++++++++++++++++++
3 files changed, 30 insertions(+)
diff --git a/tests/helpers/fixtures.py b/tests/helpers/fixtures.py
index 09307711f..3434760ec 100644
--- a/tests/helpers/fixtures.py
+++ b/tests/helpers/fixtures.py
@@ -60,6 +60,9 @@ class WinRegistryHelper:
registry = attr.ib()
+ def windowTitle(self):
+ return 'window title - qutebrowser'
+
def __init__(self):
self._ids = []
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
index 15d2ce8a0..0a6df9b35 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -520,6 +520,9 @@ class TabbedBrowserStub(QObject):
def count(self):
return len(self.tabs)
+ def widgets(self):
+ return self.tabs
+
def widget(self, i):
return self.tabs[i]
diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py
index 30241b1b3..80b3234a9 100644
--- a/tests/unit/completion/test_models.py
+++ b/tests/unit/completion/test_models.py
@@ -528,6 +528,30 @@ def test_tab_completion_delete(qtmodeltester, fake_web_tab, app_stub,
QUrl('https://duckduckgo.com')]
+def test_window_completion(qtmodeltester, fake_web_tab, tabbed_browser_stubs):
+ tabbed_browser_stubs[0].tabs = [
+ fake_web_tab(QUrl('https://github.com'), 'GitHub', 0),
+ fake_web_tab(QUrl('https://wikipedia.org'), 'Wikipedia', 1),
+ fake_web_tab(QUrl('https://duckduckgo.com'), 'DuckDuckGo', 2)
+ ]
+ tabbed_browser_stubs[1].tabs = [
+ fake_web_tab(QUrl('https://wiki.archlinux.org'), 'ArchWiki', 0)
+ ]
+
+ model = miscmodels.window()
+ model.set_pattern('')
+ qtmodeltester.data_display_may_return_none = True
+ qtmodeltester.check(model)
+
+ _check_completions(model, {
+ 'Windows': [
+ ('0', 'window title - qutebrowser',
+ 'GitHub, Wikipedia, DuckDuckGo'),
+ ('1', 'window title - qutebrowser', 'ArchWiki')
+ ]
+ })
+
+
def test_setting_option_completion(qtmodeltester, config_stub,
configdata_stub, info):
model = configmodel.option(info=info)
From 7c584e7b6c6a1514ecd28bc7962d63c74bab74e7 Mon Sep 17 00:00:00 2001
From: Joakim Reinert
Date: Mon, 9 Oct 2017 16:23:45 +0200
Subject: [PATCH 14/99] add optional interval argument to start function of
Timer stubs
Fixes failing tests for completer
---
tests/helpers/stubs.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
index 15d2ce8a0..d86d6c1d7 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -377,7 +377,9 @@ class FakeTimer(QObject):
def isSingleShot(self):
return self._singleshot
- def start(self):
+ def start(self, interval=None):
+ if interval:
+ self._interval = interval
self._started = True
def stop(self):
@@ -396,7 +398,7 @@ class InstaTimer(QObject):
timeout = pyqtSignal()
- def start(self):
+ def start(self, interval=None):
self.timeout.emit()
def setSingleShot(self, yes):
From efef588c30102edc9673a01442fe8198c7858576 Mon Sep 17 00:00:00 2001
From: Joakim Reinert
Date: Thu, 12 Oct 2017 14:43:22 +0200
Subject: [PATCH 15/99] fix lints in completer
---
qutebrowser/completion/completer.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py
index aa7f170a9..eaf74f959 100644
--- a/qutebrowser/completion/completer.py
+++ b/qutebrowser/completion/completer.py
@@ -201,8 +201,9 @@ class Completer(QObject):
updates if the text is shorter than completion.min_chars (unless we're
hitting backspace in which case updates won't be ignored).
"""
- cmd, _sep, rest = self._cmd.text().partition(' ')
- if (0 < len(rest) < config.val.completion.min_chars and
+ _cmd, _sep, rest = self._cmd.text().partition(' ')
+ input_length = len(rest)
+ if (0 < input_length < config.val.completion.min_chars and
self._cmd.cursorPosition() > self._last_cursor_pos):
log.completion.debug("Ignoring update because the length of "
"the text is less than completion.min_chars.")
@@ -212,7 +213,8 @@ class Completer(QObject):
"changes.")
else:
log.completion.debug("Scheduling completion update.")
- self._timer.start(config.val.completion.delay if self._last_text else 0)
+ start_delay = config.val.completion.delay if self._last_text else 0
+ self._timer.start(start_delay)
self._last_cursor_pos = self._cmd.cursorPosition()
self._last_text = self._cmd.text()
From 69ced4e033dd9aac21e8a7ff7be9d13fbcee864a Mon Sep 17 00:00:00 2001
From: Ryan Roden-Corrent
Date: Thu, 12 Oct 2017 11:51:03 -0400
Subject: [PATCH 16/99] Note how to ignore pylint in configuring doc.
The doc explains how to ignore flake8 errors, but the `c` and `config`
variables may also make pylint unhappy
---
doc/help/configuring.asciidoc | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index 9c350cbaf..f4996e16c 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -349,12 +349,13 @@ bind_chained('', 'clear-keychain', 'search')
Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^
-If you use an editor with flake8 integration which complains about `c` and `config` being undefined, you can use:
+If you use an editor with flake8 and pylint integration which complains about
+`c` and `config` being undefined or invalid, you can use:
[source,python]
----
-c = c # noqa: F821
-config = config # noqa: F821
+c = c # noqa: F821 pylint: disable=invalid-name,undefined-variable
+config = config # noqa: F821 pylint: disable=invalid-name,undefined-variable
----
For type annotation support (note that those imports aren't guaranteed to be
From 0e527d2584ce26bcde565a6bea63585a0e05f073 Mon Sep 17 00:00:00 2001
From: Bryan Gilbert
Date: Thu, 12 Oct 2017 12:11:00 -0400
Subject: [PATCH 17/99] Consistently space + center favicons when using
vertical tabs
---
qutebrowser/mainwindow/tabwidget.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py
index c5566f877..f97188930 100644
--- a/qutebrowser/mainwindow/tabwidget.py
+++ b/qutebrowser/mainwindow/tabwidget.py
@@ -652,7 +652,7 @@ class TabBarStyle(QCommonStyle):
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
else QIcon.Off)
icon = opt.icon.pixmap(opt.iconSize, icon_mode, icon_state)
- p.drawPixmap(layouts.icon.x(), layouts.icon.y(), icon)
+ p.drawItemPixmap(layouts.icon, Qt.AlignCenter, icon)
def drawControl(self, element, opt, p, widget=None):
"""Override drawControl to draw odd tabs in a different color.
@@ -819,8 +819,7 @@ class TabBarStyle(QCommonStyle):
else QIcon.Off)
# reserve space for favicon when tab bar is vertical (issue #1968)
position = config.val.tabs.position
- if (opt.icon.isNull() and
- position in [QTabWidget.East, QTabWidget.West] and
+ if (position in [QTabWidget.East, QTabWidget.West] and
config.val.tabs.favicons.show):
tab_icon_size = icon_size
else:
@@ -828,6 +827,7 @@ class TabBarStyle(QCommonStyle):
tab_icon_size = QSize(
min(actual_size.width(), icon_size.width()),
min(actual_size.height(), icon_size.height()))
+
icon_top = text_rect.center().y() + 1 - tab_icon_size.height() / 2
icon_rect = QRect(QPoint(text_rect.left(), icon_top), tab_icon_size)
icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
From dde50c23bc8f387508e7d3fed6e7c84e3d226e1e Mon Sep 17 00:00:00 2001
From: Ryan Roden-Corrent
Date: Fri, 13 Oct 2017 07:44:26 -0400
Subject: [PATCH 18/99] Fix up pylint notes in configuring.asciidoc.
- Use short form of pylint disable
- Update the following code block as well
- Add pylint ignore for missing-module-docstring
---
doc/help/configuring.asciidoc | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index f4996e16c..39a72201b 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -349,13 +349,15 @@ bind_chained('', 'clear-keychain', 'search')
Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^
-If you use an editor with flake8 and pylint integration which complains about
-`c` and `config` being undefined or invalid, you can use:
+If you use an editor with flake8 and pylint integration, it may have some
+complaints about invalid names, undefined variables, or missing docstrings.
+You can silence those with:
[source,python]
----
-c = c # noqa: F821 pylint: disable=invalid-name,undefined-variable
-config = config # noqa: F821 pylint: disable=invalid-name,undefined-variable
+# pylint: disable=C0111
+c = c # noqa: F821 pylint: disable=E0602,C0103
+config = config # noqa: F821 pylint: disable=E0602,C0103
----
For type annotation support (note that those imports aren't guaranteed to be
@@ -363,8 +365,9 @@ stable across qutebrowser versions):
[source,python]
----
+# pylint: disable=C0111
from qutebrowser.config.configfiles import ConfigAPI # noqa: F401
from qutebrowser.config.config import ConfigContainer # noqa: F401
-config = config # type: ConfigAPI # noqa: F821
-c = c # type: ConfigContainer # noqa: F821
+config = config # type: ConfigAPI # noqa: F821 pylint: disable=E0602,C0103
+c = c # type: ConfigContainer # noqa: F821 pylint: disable=E0602,C0103
----
From ee3d7463f607126667ac8fe6d5a1248cab3e7967 Mon Sep 17 00:00:00 2001
From: Jay Kamat
Date: Fri, 13 Oct 2017 21:33:03 -0400
Subject: [PATCH 19/99] Change qute:version git commit to display hash
Replaces output of git-describe
Closes #3095
---
qutebrowser/utils/version.py | 11 ++++++++---
tests/unit/utils/test_version.py | 4 +++-
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py
index 0f1b2233d..9cb770710 100644
--- a/qutebrowser/utils/version.py
+++ b/qutebrowser/utils/version.py
@@ -148,13 +148,18 @@ def _git_str_subprocess(gitpath):
if not os.path.isdir(os.path.join(gitpath, ".git")):
return None
try:
- cid = subprocess.check_output(
- ['git', 'describe', '--tags', '--dirty', '--always'],
+ commit_hash = subprocess.check_output(
+ ['git',
+ 'describe',
+ '--match=NeVeRmAtCh',
+ '--always',
+ '--abbrev=40',
+ '--dirty'],
cwd=gitpath).decode('UTF-8').strip()
date = subprocess.check_output(
['git', 'show', '-s', '--format=%ci', 'HEAD'],
cwd=gitpath).decode('UTF-8').strip()
- return '{} ({})'.format(cid, date)
+ return '{} ({})'.format(commit_hash, date)
except (subprocess.CalledProcessError, OSError):
return None
diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py
index 489806f8c..cfd8c06a6 100644
--- a/tests/unit/utils/test_version.py
+++ b/tests/unit/utils/test_version.py
@@ -356,7 +356,9 @@ class TestGitStrSubprocess:
def test_real_git(self, git_repo):
"""Test with a real git repository."""
ret = version._git_str_subprocess(str(git_repo))
- assert ret == 'foobar (1970-01-01 01:00:00 +0100)'
+ assert ret == \
+ '6e4b65a529c0ab78fb370c1527d5809f7436b8f3 ' \
+ + '(1970-01-01 01:00:00 +0100)'
def test_missing_dir(self, tmpdir):
"""Test with a directory which doesn't exist."""
From 4d2ca878ead78979af7de83dcf3b44a077bc6272 Mon Sep 17 00:00:00 2001
From: sMailund
Date: Sat, 14 Oct 2017 10:26:55 +0200
Subject: [PATCH 20/99] add color configuration to passthrough mode
---
qutebrowser/config/configdata.yml | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 7e7f024f3..1acac8641 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -524,7 +524,6 @@ content.netrc_file:
content.notifications:
default: ask
type: BoolAsk
- backend: QtWebKit
desc: Allow websites to show notifications.
content.pdfjs:
@@ -1504,6 +1503,16 @@ colors.completion.match.fg:
type: QssColor
desc: Foreground color of the matched text in the completion.
+colors.statusbar.passthrough.fg:
+ default: white
+ type: QssColor
+ desc: Foreground color of the statusbar in passthrough mode.
+
+colors.statusbar.passthrough.bg:
+ default: darkblue
+ type: QssColor
+ desc: Background color of the statusbar in passthrough mode.
+
colors.completion.scrollbar.fg:
default: white
type: QssColor
From 57c4285dbc9d2ba6e8a7e690a899dc77974bdf58 Mon Sep 17 00:00:00 2001
From: sMailund
Date: Sat, 14 Oct 2017 10:29:34 +0200
Subject: [PATCH 21/99] configure colorflags for passthrough mode
---
qutebrowser/mainwindow/statusbar/bar.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py
index e8aacc935..e7a6256a2 100644
--- a/qutebrowser/mainwindow/statusbar/bar.py
+++ b/qutebrowser/mainwindow/statusbar/bar.py
@@ -43,6 +43,7 @@ class ColorFlags:
command: If we're currently in command mode.
mode: The current caret mode (CaretMode.off/.on/.selection).
private: Whether this window is in private browsing mode.
+ passthrough: If we're currently in passthrough-mode
"""
CaretMode = usertypes.enum('CaretMode', ['off', 'on', 'selection'])
@@ -51,6 +52,7 @@ class ColorFlags:
command = attr.ib(False)
caret = attr.ib(CaretMode.off)
private = attr.ib(False)
+ passthrough = attr.ib(False)
def to_stringlist(self):
"""Get a string list of set flags used in the stylesheet.
@@ -66,6 +68,8 @@ class ColorFlags:
strings.append('command')
if self.private:
strings.append('private')
+ if self.passthrough:
+ strings.append('passthrough')
if self.private and self.command:
strings.append('private-command')
@@ -88,6 +92,7 @@ def _generate_stylesheet():
('prompt', 'prompts'),
('insert', 'statusbar.insert'),
('command', 'statusbar.command'),
+ ('passthrough', 'statusbar.passthrough'),
('private-command', 'statusbar.command.private'),
]
stylesheet = """
From 14005e368493963078631344668e218b082be025 Mon Sep 17 00:00:00 2001
From: sMailund
Date: Sat, 14 Oct 2017 10:30:44 +0200
Subject: [PATCH 22/99] trigger color change on passthrough mode
---
qutebrowser/mainwindow/statusbar/bar.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py
index e7a6256a2..ec01fe89b 100644
--- a/qutebrowser/mainwindow/statusbar/bar.py
+++ b/qutebrowser/mainwindow/statusbar/bar.py
@@ -249,6 +249,9 @@ class StatusBar(QWidget):
if mode == usertypes.KeyMode.insert:
log.statusbar.debug("Setting insert flag to {}".format(val))
self._color_flags.insert = val
+ if mode == usertypes.KeyMode.passthrough:
+ log.statusbar.debug("Setting passthrough flag to {}".format(val))
+ self._color_flags.passthrough = val
if mode == usertypes.KeyMode.command:
log.statusbar.debug("Setting command flag to {}".format(val))
self._color_flags.command = val
@@ -312,7 +315,8 @@ class StatusBar(QWidget):
usertypes.KeyMode.command,
usertypes.KeyMode.caret,
usertypes.KeyMode.prompt,
- usertypes.KeyMode.yesno]:
+ usertypes.KeyMode.yesno,
+ usertypes.KeyMode.passthrough]:
self.set_mode_active(mode, True)
@pyqtSlot(usertypes.KeyMode, usertypes.KeyMode)
@@ -329,7 +333,8 @@ class StatusBar(QWidget):
usertypes.KeyMode.command,
usertypes.KeyMode.caret,
usertypes.KeyMode.prompt,
- usertypes.KeyMode.yesno]:
+ usertypes.KeyMode.yesno,
+ usertypes.KeyMode.passthrough]:
self.set_mode_active(old_mode, False)
@pyqtSlot(browsertab.AbstractTab)
From f5cccfb0977bdb2f3957a28b1f4ee91c921f4100 Mon Sep 17 00:00:00 2001
From: sMailund
Date: Sat, 14 Oct 2017 10:43:34 +0200
Subject: [PATCH 23/99] re-add erroneously removed line
---
qutebrowser/config/configdata.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 1acac8641..0ac82837b 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -524,6 +524,7 @@ content.netrc_file:
content.notifications:
default: ask
type: BoolAsk
+ backend: QtWebKit
desc: Allow websites to show notifications.
content.pdfjs:
From ffab9e263f6903315ef76261c006c39f37a9a84d Mon Sep 17 00:00:00 2001
From: Kimat Boven
Date: Fri, 13 Oct 2017 22:44:02 +0200
Subject: [PATCH 24/99] it was not possible to show the current_url in tab or
window title
note that I couldn't use {url} as field for the FormatString
---
doc/help/settings.asciidoc | 2 ++
qutebrowser/config/configdata.yml | 5 +++++
qutebrowser/mainwindow/tabwidget.py | 5 +++++
3 files changed, 12 insertions(+)
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index 1973418ad..55f8af99a 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -2792,6 +2792,7 @@ The following placeholders are defined:
* `{host}`: The host of the current web page.
* `{backend}`: Either ''webkit'' or ''webengine''
* `{private}` : Indicates when private mode is enabled.
+* `{current_url}` : The url of the current web page.
Type: <>
@@ -2928,6 +2929,7 @@ The following placeholders are defined:
* `{host}`: The host of the current web page.
* `{backend}`: Either ''webkit'' or ''webengine''
* `{private}` : Indicates when private mode is enabled.
+* `{current_url}` : The url of the current web page.
Type: <>
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 7e7f024f3..3cfc1ced5 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -1224,6 +1224,7 @@ tabs.title.format:
- scroll_pos
- host
- private
+ - current_url
none_ok: true
desc: |
The format to use for the tab title.
@@ -1239,6 +1240,7 @@ tabs.title.format:
* `{host}`: The host of the current web page.
* `{backend}`: Either ''webkit'' or ''webengine''
* `{private}` : Indicates when private mode is enabled.
+ * `{current_url}` : The url of the current web page.
tabs.title.format_pinned:
default: '{index}'
@@ -1254,6 +1256,7 @@ tabs.title.format_pinned:
- scroll_pos
- host
- private
+ - current_url
none_ok: true
desc: The format to use for the tab title for pinned tabs. The same placeholders
like for `tabs.title.format` are defined.
@@ -1371,6 +1374,7 @@ window.title_format:
- host
- backend
- private
+ - current_url
default: '{perc}{title}{title_sep}qutebrowser'
desc: |
The format to use for the window title.
@@ -1385,6 +1389,7 @@ window.title_format:
* `{host}`: The host of the current web page.
* `{backend}`: Either ''webkit'' or ''webengine''
* `{private}` : Indicates when private mode is enabled.
+ * `{current_url}` : The url of the current web page.
## zoom
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py
index c5566f877..a8bc45cc0 100644
--- a/qutebrowser/mainwindow/tabwidget.py
+++ b/qutebrowser/mainwindow/tabwidget.py
@@ -164,6 +164,11 @@ class TabWidget(QTabWidget):
except qtutils.QtValueError:
fields['host'] = ''
+ try:
+ fields['current_url'] = self.tab_url(idx).url()
+ except qtutils.QtValueError:
+ fields['current_url'] = ''
+
y = tab.scroller.pos_perc()[1]
if y is None:
scroll_pos = '???'
From 8ca0c87b1ffb0e7b3cf3906f1490b4b3a7123ed8 Mon Sep 17 00:00:00 2001
From: Kimat Boven
Date: Sat, 14 Oct 2017 20:03:58 +0200
Subject: [PATCH 25/99] FakeUrl had no url
---
tests/helpers/stubs.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
index 15d2ce8a0..1313649bc 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -131,10 +131,11 @@ class FakeUrl:
"""QUrl stub which provides .path(), isValid() and host()."""
- def __init__(self, path=None, valid=True, host=None):
+ def __init__(self, path=None, valid=True, host=None, url=None):
self.path = mock.Mock(return_value=path)
self.isValid = mock.Mock(returl_value=valid)
self.host = mock.Mock(returl_value=host)
+ self.url = mock.Mock(return_value=url)
class FakeNetworkReply:
From 4ff44eff7bb789cdde9db254f24feb92a8250c66 Mon Sep 17 00:00:00 2001
From: Jay Kamat
Date: Sat, 14 Oct 2017 11:32:23 -0400
Subject: [PATCH 26/99] Clean up logic for finding git hash
Also add implementation for release scripts as well
---
qutebrowser/utils/version.py | 8 ++------
scripts/setupcommon.py | 7 ++++---
tests/unit/utils/test_version.py | 4 +---
3 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py
index 9cb770710..4c31aa60d 100644
--- a/qutebrowser/utils/version.py
+++ b/qutebrowser/utils/version.py
@@ -148,13 +148,9 @@ def _git_str_subprocess(gitpath):
if not os.path.isdir(os.path.join(gitpath, ".git")):
return None
try:
+ # https://stackoverflow.com/questions/21017300/21017394#21017394
commit_hash = subprocess.check_output(
- ['git',
- 'describe',
- '--match=NeVeRmAtCh',
- '--always',
- '--abbrev=40',
- '--dirty'],
+ ['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
cwd=gitpath).decode('UTF-8').strip()
date = subprocess.check_output(
['git', 'show', '-s', '--format=%ci', 'HEAD'],
diff --git a/scripts/setupcommon.py b/scripts/setupcommon.py
index a2e4dfca9..1f85b225f 100644
--- a/scripts/setupcommon.py
+++ b/scripts/setupcommon.py
@@ -50,13 +50,14 @@ def _git_str():
if not os.path.isdir(os.path.join(BASEDIR, ".git")):
return None
try:
- cid = subprocess.check_output(
- ['git', 'describe', '--tags', '--dirty', '--always'],
+ # https://stackoverflow.com/questions/21017300/21017394#21017394
+ commit_hash = subprocess.check_output(
+ ['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
cwd=BASEDIR).decode('UTF-8').strip()
date = subprocess.check_output(
['git', 'show', '-s', '--format=%ci', 'HEAD'],
cwd=BASEDIR).decode('UTF-8').strip()
- return '{} ({})'.format(cid, date)
+ return '{} ({})'.format(commit_hash, date)
except (subprocess.CalledProcessError, OSError):
return None
diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py
index cfd8c06a6..9db7603e3 100644
--- a/tests/unit/utils/test_version.py
+++ b/tests/unit/utils/test_version.py
@@ -356,9 +356,7 @@ class TestGitStrSubprocess:
def test_real_git(self, git_repo):
"""Test with a real git repository."""
ret = version._git_str_subprocess(str(git_repo))
- assert ret == \
- '6e4b65a529c0ab78fb370c1527d5809f7436b8f3 ' \
- + '(1970-01-01 01:00:00 +0100)'
+ assert ret == '6e4b65a (1970-01-01 01:00:00 +0100)'
def test_missing_dir(self, tmpdir):
"""Test with a directory which doesn't exist."""
From 71f48a1e30a8cba319b8218b213bf73675c3ad6c Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 00:21:35 +0200
Subject: [PATCH 27/99] Move statusbar colors together in configdata.yml
---
qutebrowser/config/configdata.yml | 40 +++++++++++++++----------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 941135d22..2a8c4c32b 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -1469,16 +1469,6 @@ colors.completion.category.border.bottom:
type: QssColor
desc: Bottom border color of the completion widget category headers.
-colors.statusbar.insert.fg:
- default: white
- type: QssColor
- desc: Foreground color of the statusbar in insert mode.
-
-colors.statusbar.insert.bg:
- default: darkgreen
- type: QssColor
- desc: Background color of the statusbar in insert mode.
-
colors.completion.item.selected.fg:
default: black
type: QtColor
@@ -1504,16 +1494,6 @@ colors.completion.match.fg:
type: QssColor
desc: Foreground color of the matched text in the completion.
-colors.statusbar.passthrough.fg:
- default: white
- type: QssColor
- desc: Foreground color of the statusbar in passthrough mode.
-
-colors.statusbar.passthrough.bg:
- default: darkblue
- type: QssColor
- desc: Background color of the statusbar in passthrough mode.
-
colors.completion.scrollbar.fg:
default: white
type: QssColor
@@ -1678,6 +1658,26 @@ colors.statusbar.normal.bg:
type: QssColor
desc: Background color of the statusbar.
+colors.statusbar.insert.fg:
+ default: white
+ type: QssColor
+ desc: Foreground color of the statusbar in insert mode.
+
+colors.statusbar.insert.bg:
+ default: darkgreen
+ type: QssColor
+ desc: Background color of the statusbar in insert mode.
+
+colors.statusbar.passthrough.fg:
+ default: white
+ type: QssColor
+ desc: Foreground color of the statusbar in passthrough mode.
+
+colors.statusbar.passthrough.bg:
+ default: darkblue
+ type: QssColor
+ desc: Background color of the statusbar in passthrough mode.
+
colors.statusbar.private.fg:
default: white
type: QssColor
From e3a305a81455299078b5c094b16e23125228501b Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 00:21:56 +0200
Subject: [PATCH 28/99] Regenerate docs
---
doc/help/settings.asciidoc | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index 1973418ad..9bf058c96 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -70,6 +70,8 @@
|<>|Foreground color of the statusbar in insert mode.
|<>|Background color of the statusbar.
|<>|Foreground color of the statusbar.
+|<>|Background color of the statusbar in passthrough mode.
+|<>|Foreground color of the statusbar in passthrough mode.
|<>|Background color of the statusbar in private browsing mode.
|<>|Foreground color of the statusbar in private browsing mode.
|<>|Background color of the progress bar.
@@ -1093,6 +1095,22 @@ Type: <>
Default: +pass:[white]+
+[[colors.statusbar.passthrough.bg]]
+=== colors.statusbar.passthrough.bg
+Background color of the statusbar in passthrough mode.
+
+Type: <>
+
+Default: +pass:[darkblue]+
+
+[[colors.statusbar.passthrough.fg]]
+=== colors.statusbar.passthrough.fg
+Foreground color of the statusbar in passthrough mode.
+
+Type: <>
+
+Default: +pass:[white]+
+
[[colors.statusbar.private.bg]]
=== colors.statusbar.private.bg
Background color of the statusbar in private browsing mode.
From f4796b5ec61663453953e5482de74f6b21f78858 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 00:22:19 +0200
Subject: [PATCH 29/99] Add missing period
---
qutebrowser/mainwindow/statusbar/bar.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py
index ec01fe89b..da18deae8 100644
--- a/qutebrowser/mainwindow/statusbar/bar.py
+++ b/qutebrowser/mainwindow/statusbar/bar.py
@@ -43,7 +43,7 @@ class ColorFlags:
command: If we're currently in command mode.
mode: The current caret mode (CaretMode.off/.on/.selection).
private: Whether this window is in private browsing mode.
- passthrough: If we're currently in passthrough-mode
+ passthrough: If we're currently in passthrough-mode.
"""
CaretMode = usertypes.enum('CaretMode', ['off', 'on', 'selection'])
From 2eba2cc8f5abf5bbefbbf526d150e326018b4faa Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 00:26:26 +0200
Subject: [PATCH 30/99] Skip another history test on AppVeyor
---
tests/end2end/features/history.feature | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/end2end/features/history.feature b/tests/end2end/features/history.feature
index ca5adbb97..69af64941 100644
--- a/tests/end2end/features/history.feature
+++ b/tests/end2end/features/history.feature
@@ -99,6 +99,8 @@ Feature: Page history
Then the page should contain the plaintext "3.txt"
Then the page should contain the plaintext "4.txt"
+ # Hangs a lot on AppVeyor
+ @posix
Scenario: Listing history with qute:history redirect
When I open data/numbers/3.txt
And I open data/numbers/4.txt
From af3c9a2b9ecb2cee519ed58b80230e44e875c16f Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 00:29:45 +0200
Subject: [PATCH 31/99] Update changelog
---
doc/changelog.asciidoc | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 00281d562..931dd8fd3 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -15,10 +15,19 @@ breaking changes (such as renamed commands) can happen in minor releases.
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
+v1.1.0 (unreleased)
+-------------------
+
+Added
+~~~~~
+
+- New `{current_url}` field for `window.title_format` and `tabs.title.format`.
+- New `colors.statusbar.passthrough.fg`/`.bg` settings.
+
v1.0.2 (unreleased)
-------------------
-Fixes
+Fixed
~~~~~
- Fixed workaround for black screens with Nvidia cards
@@ -27,7 +36,7 @@ Fixes
v1.0.1
------
-Fixes
+Fixed
~~~~~
- Fixed starting after customizing `fonts.tabs` or `fonts.debug_console`.
From 392ea8825bb31e6888557df4c9ee18af5e4b7329 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 12:21:14 +0200
Subject: [PATCH 32/99] Clarify completion keybinding changes
See #3125
[ci skip]
---
doc/changelog.asciidoc | 3 +++
doc/help/configuring.asciidoc | 5 +++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 931dd8fd3..5a48959bd 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -74,6 +74,9 @@ Major changes
the entire browsing history. The default for
`completion.web_history_max_items` got changed to `-1` (unlimited). If the
completion is too slow on your machine, try setting it to a few 1000 items.
+- Up/Down now navigates through the command history instead of selecting
+ completion items. Either use Tab to cycle through the completion, or
+ https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc#migrating-older-configurations[restore the old behavior].
Added
~~~~~
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index 39a72201b..997e47246 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -18,8 +18,9 @@ the old defaults.
Other changes in default settings:
- `` and `` in the completion now navigate through command history
- instead of selecting completion items. You can get back the old behavior by
- doing:
+ instead of selecting completion items. Use ``/`` to cycle
+ through the completion instead.
+ You can get back the old behavior by doing:
+
----
:bind -f -m command completion-item-focus prev
From e90a5f509e1745f33095882d30570924e8512e5b Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 12:25:57 +0200
Subject: [PATCH 33/99] Improve install docs
[ci skip]
---
doc/install.asciidoc | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/doc/install.asciidoc b/doc/install.asciidoc
index de6e9f2f2..15e3ac93e 100644
--- a/doc/install.asciidoc
+++ b/doc/install.asciidoc
@@ -221,6 +221,10 @@ https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[qutebrows
mailinglist] to get notified on new releases). You can install a newer version
without uninstalling the older one.
+The binary release ships with a QtWebEngine built without proprietary codec
+support. To get support for e.g. h264/h265 videos, you'll need to build
+QtWebEngine from source yourself with support for that enabled.
+
https://chocolatey.org/packages/qutebrowser[Chocolatey package]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -261,6 +265,10 @@ Note that you'll need to upgrade to new versions manually (subscribe to the
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[qutebrowser-announce
mailinglist] to get notified on new releases).
+The binary release ships with a QtWebEngine built without proprietary codec
+support. To get support for e.g. h264/h265 videos, you'll need to build
+QtWebEngine from source yourself with support for that enabled.
+
This binary is also available through the
https://caskroom.github.io/[Homebrew Cask] package manager:
@@ -355,6 +363,18 @@ also typically means you'll be using an older release of QtWebEngine.
On Windows, run `tox -e 'mkvenv-win' instead, however make sure that ONLY
Python3 is in your PATH before running tox.
+Building the docs
+~~~~~~~~~~~~~~~~~
+
+To build the documentation, install `asciidoc` (note that LaTeX which comes as
+optional/recommended dependency with some distributions is not required).
+
+Then, run:
+
+----
+$ python3 scripts/asciidoc2html.py
+----
+
Creating a wrapper script
~~~~~~~~~~~~~~~~~~~~~~~~~
From fa4a66f7b38ed038e11f74011c796e2577b3f005 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 21:09:37 +0200
Subject: [PATCH 34/99] Add SQLITE_READONLY to environmental errors
---
doc/changelog.asciidoc | 1 +
qutebrowser/misc/sql.py | 11 +++++------
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 5a48959bd..7eecf3b82 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -32,6 +32,7 @@ Fixed
- Fixed workaround for black screens with Nvidia cards
- Mark the content.notifications setting as QtWebKit only correctly
+- Handle a filesystem going read-only gracefully
v1.0.1
------
diff --git a/qutebrowser/misc/sql.py b/qutebrowser/misc/sql.py
index 5b0d3361d..e04c3f6e3 100644
--- a/qutebrowser/misc/sql.py
+++ b/qutebrowser/misc/sql.py
@@ -65,13 +65,12 @@ class SqliteError(SqlError):
log.sql.debug("error code: {}".format(error.nativeErrorCode()))
# https://sqlite.org/rescode.html
+ # https://github.com/qutebrowser/qutebrowser/issues/2930
+ # https://github.com/qutebrowser/qutebrowser/issues/3004
environmental_errors = [
- # SQLITE_LOCKED,
- # https://github.com/qutebrowser/qutebrowser/issues/2930
- '9',
- # SQLITE_FULL,
- # https://github.com/qutebrowser/qutebrowser/issues/3004
- '13',
+ '8', # SQLITE_READONLY
+ '9', # SQLITE_LOCKED,
+ '13', # SQLITE_FULL,
]
self.environmental = error.nativeErrorCode() in environmental_errors
From e003b116704a12b01c65af442af6060df5d9c0a4 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Sun, 15 Oct 2017 22:30:17 +0200
Subject: [PATCH 35/99] Fix overflow handling for QtWebKit scrolling
If we do "m * val / 100", the value gets bigger, so we need to check for an
overflow afterwards.
---
qutebrowser/browser/webkit/webkittab.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py
index 43a38ea61..43bec3456 100644
--- a/qutebrowser/browser/webkit/webkittab.py
+++ b/qutebrowser/browser/webkit/webkittab.py
@@ -422,12 +422,13 @@ class WebKitScroller(browsertab.AbstractScroller):
else:
for val, orientation in [(x, Qt.Horizontal), (y, Qt.Vertical)]:
if val is not None:
- val = qtutils.check_overflow(val, 'int', fatal=False)
frame = self._widget.page().mainFrame()
- m = frame.scrollBarMaximum(orientation)
- if m == 0:
+ maximum = frame.scrollBarMaximum(orientation)
+ if maximum == 0:
continue
- frame.setScrollBarValue(orientation, int(m * val / 100))
+ pos = int(maximum * val / 100)
+ pos = qtutils.check_overflow(pos, 'int', fatal=False)
+ frame.setScrollBarValue(orientation, pos)
def _key_press(self, key, count=1, getter_name=None, direction=None):
frame = self._widget.page().mainFrame()
From 2a65cadb67ec8ec1792e5e6f90b770ae82e6b221 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 06:18:09 +0200
Subject: [PATCH 36/99] Fix setting monospace fonts with None values
Fixes #3130
---
qutebrowser/config/configinit.py | 4 +++-
tests/unit/config/test_configinit.py | 9 +++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/config/configinit.py b/qutebrowser/config/configinit.py
index c76efba00..027aedb04 100644
--- a/qutebrowser/config/configinit.py
+++ b/qutebrowser/config/configinit.py
@@ -104,7 +104,9 @@ def _update_monospace_fonts():
continue
elif not isinstance(opt.typ, configtypes.Font):
continue
- elif not config.instance.get_obj(name).endswith(' monospace'):
+
+ value = config.instance.get_obj(name)
+ if value is None or not value.endswith(' monospace'):
continue
config.instance.changed.emit(name)
diff --git a/tests/unit/config/test_configinit.py b/tests/unit/config/test_configinit.py
index 820b03a38..1501b794d 100644
--- a/tests/unit/config/test_configinit.py
+++ b/tests/unit/config/test_configinit.py
@@ -258,6 +258,15 @@ class TestEarlyInit:
# Font subclass, but doesn't end with "monospace"
assert 'fonts.web.family.standard' not in changed_options
+ def test_setting_monospace_fonts_family(self, init_patch, args):
+ """Make sure setting fonts.monospace after a family works.
+
+ See https://github.com/qutebrowser/qutebrowser/issues/3130
+ """
+ configinit.early_init(args)
+ config.instance.set_str('fonts.web.family.standard', '')
+ config.instance.set_str('fonts.monospace', 'Terminus')
+
def test_force_software_rendering(self, monkeypatch, config_stub):
"""Setting force_software_rendering should set the environment var."""
envvar = 'QT_XCB_FORCE_SOFTWARE_OPENGL'
From 09868c1e7fb091ae51bdb6c242f692f3095f23ef Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 08:17:45 +0200
Subject: [PATCH 37/99] Update docs
---
doc/changelog.asciidoc | 2 ++
doc/help/settings.asciidoc | 18 ++++++++++++++++++
qutebrowser/config/configdata.yml | 4 ++--
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 7eecf3b82..cccc7bb22 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -23,6 +23,8 @@ Added
- New `{current_url}` field for `window.title_format` and `tabs.title.format`.
- New `colors.statusbar.passthrough.fg`/`.bg` settings.
+- New `completion.delay` and `completion.min_chars` settings to update the
+ completion less often.
v1.0.2 (unreleased)
-------------------
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index f9a5aaeb0..7678583b7 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -96,7 +96,9 @@
|<>|Foreground color of selected odd tabs.
|<>|Background color for webpages if unset (or empty to use the theme's color)
|<>|How many commands to save in the command history.
+|<>|Delay in ms before updating completions after typing a character.
|<>|The height of the completion, in px or as percentage of the window.
+|<>|Minimum amount of characters needed to update completions.
|<>|Move on to the next part when there's only one possible completion left.
|<>|Padding of scrollbar handle in the completion window (in px).
|<>|Width of the scrollbar in the completion window (in px).
@@ -1311,6 +1313,14 @@ Type: <>
Default: +pass:[100]+
+[[completion.delay]]
+=== completion.delay
+Delay in ms before updating completions after typing a character.
+
+Type: <>
+
+Default: +pass:[0]+
+
[[completion.height]]
=== completion.height
The height of the completion, in px or as percentage of the window.
@@ -1319,6 +1329,14 @@ Type: <>
Default: +pass:[50%]+
+[[completion.min_chars]]
+=== completion.min_chars
+Minimum amount of characters needed to update completions.
+
+Type: <>
+
+Default: +pass:[1]+
+
[[completion.quick]]
=== completion.quick
Move on to the next part when there's only one possible completion left.
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 700dd4ddd..44c405a2f 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -683,14 +683,14 @@ completion.delay:
type:
name: Int
minval: 0
- desc: Delay in ms before updating completions after typing a character
+ desc: Delay in ms before updating completions after typing a character.
completion.min_chars:
default: 1
type:
name: Int
minval: 1
- desc: Minimum amount of characters needed to update completions
+ desc: Minimum amount of characters needed to update completions.
## downloads
From caeab959a52369968767e377f3795bd41a11c2cf Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 08:32:11 +0200
Subject: [PATCH 38/99] Update changelog
---
doc/changelog.asciidoc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index cccc7bb22..14a9379e7 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -26,6 +26,11 @@ Added
- New `completion.delay` and `completion.min_chars` settings to update the
completion less often.
+Fixed
+~~~~~
+
+- More consistent sizing for favicons with vertical tabs.
+
v1.0.2 (unreleased)
-------------------
From 5307b97ca587696981f61b863fa951780f76f776 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 09:24:31 +0200
Subject: [PATCH 39/99] Improve checkpyver error message
---
qutebrowser/misc/checkpyver.py | 2 +-
tests/unit/misc/test_checkpyver.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/misc/checkpyver.py b/qutebrowser/misc/checkpyver.py
index fc3dde673..d4ea13bcd 100644
--- a/qutebrowser/misc/checkpyver.py
+++ b/qutebrowser/misc/checkpyver.py
@@ -49,7 +49,7 @@ def check_python_version():
# pylint: disable=bad-builtin
version_str = '.'.join(map(str, sys.version_info[:3]))
text = ("At least Python 3.5 is required to run qutebrowser, but " +
- version_str + " is installed!\n")
+ "it's running with " + version_str + ".\n")
if Tk and '--no-err-windows' not in sys.argv: # pragma: no cover
root = Tk()
root.withdraw()
diff --git a/tests/unit/misc/test_checkpyver.py b/tests/unit/misc/test_checkpyver.py
index a25e1d187..8864a63a6 100644
--- a/tests/unit/misc/test_checkpyver.py
+++ b/tests/unit/misc/test_checkpyver.py
@@ -28,8 +28,8 @@ import pytest
from qutebrowser.misc import checkpyver
-TEXT = (r"At least Python 3.5 is required to run qutebrowser, but "
- r"\d+\.\d+\.\d+ is installed!\n")
+TEXT = (r"At least Python 3.5 is required to run qutebrowser, but it's running "
+ r"with \d+\.\d+\.\d+.\n")
@pytest.mark.not_frozen
From 7adab9ec78ad2ee531870c086a06a472e1bb33b3 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 09:58:44 +0200
Subject: [PATCH 40/99] Fix long line
---
tests/unit/misc/test_checkpyver.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/unit/misc/test_checkpyver.py b/tests/unit/misc/test_checkpyver.py
index 8864a63a6..c5fa83a48 100644
--- a/tests/unit/misc/test_checkpyver.py
+++ b/tests/unit/misc/test_checkpyver.py
@@ -28,8 +28,8 @@ import pytest
from qutebrowser.misc import checkpyver
-TEXT = (r"At least Python 3.5 is required to run qutebrowser, but it's running "
- r"with \d+\.\d+\.\d+.\n")
+TEXT = (r"At least Python 3.5 is required to run qutebrowser, but it's "
+ r"running with \d+\.\d+\.\d+.\n")
@pytest.mark.not_frozen
From e766fe14fcde6769f50e02f822b0d788266acc3f Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 12:27:13 +0200
Subject: [PATCH 41/99] Fix HTML escaping in completion
---
doc/changelog.asciidoc | 1 +
qutebrowser/completion/completiondelegate.py | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 14a9379e7..3e2aeeb12 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -40,6 +40,7 @@ Fixed
- Fixed workaround for black screens with Nvidia cards
- Mark the content.notifications setting as QtWebKit only correctly
- Handle a filesystem going read-only gracefully
+- Fix wrong rendering of keys like `` in the completion
v1.0.1
------
diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py
index 8248b3745..6688a2dfa 100644
--- a/qutebrowser/completion/completiondelegate.py
+++ b/qutebrowser/completion/completiondelegate.py
@@ -202,7 +202,8 @@ class CompletionItemDelegate(QStyledItemDelegate):
if index.column() in columns_to_filter and pattern:
repl = r'\g<0>'
text = re.sub(re.escape(pattern).replace(r'\ ', r'|'),
- repl, self._opt.text, flags=re.IGNORECASE)
+ repl, html.escape(self._opt.text),
+ flags=re.IGNORECASE)
self._doc.setHtml(text)
else:
self._doc.setPlainText(self._opt.text)
From e89fda189ae5fa3ead1e9d37fb593bf507bfd6dd Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 13:44:51 +0200
Subject: [PATCH 42/99] Fix tab sizing when we get a QPainter and not a
QStylePainter
I'm not sure yet how that happens, but I got a crash report for that.
See #3099
---
qutebrowser/mainwindow/tabwidget.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py
index b0786a3b7..56cb922f8 100644
--- a/qutebrowser/mainwindow/tabwidget.py
+++ b/qutebrowser/mainwindow/tabwidget.py
@@ -657,7 +657,7 @@ class TabBarStyle(QCommonStyle):
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
else QIcon.Off)
icon = opt.icon.pixmap(opt.iconSize, icon_mode, icon_state)
- p.drawItemPixmap(layouts.icon, Qt.AlignCenter, icon)
+ self._style.drawItemPixmap(p, layouts.icon, Qt.AlignCenter, icon)
def drawControl(self, element, opt, p, widget=None):
"""Override drawControl to draw odd tabs in a different color.
From dd70019d4ccd4e7b4b3a51820fe2253f700a41b7 Mon Sep 17 00:00:00 2001
From: pyup-bot
Date: Mon, 16 Oct 2017 16:53:13 +0200
Subject: [PATCH 43/99] Update setuptools from 36.5.0 to 36.6.0
---
misc/requirements/requirements-pip.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc/requirements/requirements-pip.txt b/misc/requirements/requirements-pip.txt
index b8d75bcc1..b643e0667 100644
--- a/misc/requirements/requirements-pip.txt
+++ b/misc/requirements/requirements-pip.txt
@@ -3,6 +3,6 @@
appdirs==1.4.3
packaging==16.8
pyparsing==2.2.0
-setuptools==36.5.0
+setuptools==36.6.0
six==1.11.0
wheel==0.30.0
From eec129807e0a8f0cbff8aac1b37d0020b2d44f76 Mon Sep 17 00:00:00 2001
From: pyup-bot
Date: Mon, 16 Oct 2017 16:53:15 +0200
Subject: [PATCH 44/99] Update hypothesis from 3.32.0 to 3.33.0
---
misc/requirements/requirements-tests.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt
index 9cd025e4e..1bacf0cfc 100644
--- a/misc/requirements/requirements-tests.txt
+++ b/misc/requirements/requirements-tests.txt
@@ -11,7 +11,7 @@ fields==5.0.0
Flask==0.12.2
glob2==0.6
hunter==2.0.1
-hypothesis==3.32.0
+hypothesis==3.33.0
itsdangerous==0.24
# Jinja2==2.9.6
Mako==1.0.7
From 039edd8d85b8830c4bcc1ea03b41353d0952e756 Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 21:32:53 +0200
Subject: [PATCH 45/99] Add a basic appdata.xml file
---
misc/qutebrowser.appdata.xml | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 misc/qutebrowser.appdata.xml
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
new file mode 100644
index 000000000..7a3260226
--- /dev/null
+++ b/misc/qutebrowser.appdata.xml
@@ -0,0 +1,33 @@
+
+
+
+ qutebrowser.desktop
+ CC-BY-SA-3.0
+ GPL-3.0
+ qutebrowser
+ A keyboard-driven web browser
+
+
+ qutebrowser is a keyboard-focused browser with a minimal GUI.
+ It was inspired by other browsers/addons like dwb and Vimperator/Pentadactyl,
+ and is based on Python and PyQt5.
+
+
+
+
+ https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/main.png
+
+
+ https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/downloads.png
+
+
+ https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/completion.png
+
+
+ https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/hints.png
+
+
+ https://www.qutebrowser.org/
+
+
+
From 1d5d6acdeacd330936676e3fad7b9fb304b5ed67 Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 21:34:08 +0200
Subject: [PATCH 46/99] Add info to appdata.xml
---
misc/qutebrowser.appdata.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index 7a3260226..5aaa013bb 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -13,6 +13,7 @@
and is based on Python and PyQt5.
+ qutebrowser.desktop
https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/main.png
From a76fdfe205229d124c6fab8af9c89a71fcd43d7d Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 21:55:24 +0200
Subject: [PATCH 47/99] Add more URLs to appdata file
---
misc/qutebrowser.appdata.xml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index 5aaa013bb..a70f55112 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -28,7 +28,9 @@
https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/hints.png
- https://www.qutebrowser.org/
+ https://www.qutebrowser.org
+ https://github.com/qutebrowser/qutebrowser/issues/
+ https://github.com/qutebrowser/qutebrowser#donating
From 3084e7be029195b50a57e6a8fccdd6087451078e Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 21:57:10 +0200
Subject: [PATCH 48/99] Add to appdata.xml file
---
misc/qutebrowser.appdata.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index a70f55112..f52db9e9a 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -13,6 +13,10 @@
and is based on Python and PyQt5.
+
+ Network
+ WebBrowser
+
qutebrowser.desktop
From 18776456f3e9d78581ba44af5d241cd4f1771183 Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 21:58:24 +0200
Subject: [PATCH 49/99] Add to appdata.xml file
---
misc/qutebrowser.appdata.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index f52db9e9a..3f9923cc8 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -17,6 +17,9 @@
Network
WebBrowser
+
+ qutebrowser
+
qutebrowser.desktop
From 30f7f7b03c8555954ebbabf0d559b1f41442386b Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 22:05:07 +0200
Subject: [PATCH 50/99] Change in appdata.xml to match the
{tld}.{vendor}.{product} scheme
---
misc/qutebrowser.appdata.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index 3f9923cc8..e72850100 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -1,7 +1,7 @@
- qutebrowser.desktop
+ org.qutebrowser.qutebrowser.desktop
CC-BY-SA-3.0
GPL-3.0
qutebrowser
From 914d72a2160c575ef8085cdf5f250c738ea5127f Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 22:26:46 +0200
Subject: [PATCH 51/99] Remove the .desktop suffix from in appdata.xml
This used to be required by the standard, but is no longer the case.
---
misc/qutebrowser.appdata.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index e72850100..8684beecc 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -1,7 +1,7 @@
- org.qutebrowser.qutebrowser.desktop
+ org.qutebrowser.qutebrowser
CC-BY-SA-3.0
GPL-3.0
qutebrowser
From 2ad7bafcdffaede36b26de47651483f964aaf82d Mon Sep 17 00:00:00 2001
From: suve
Date: Mon, 16 Oct 2017 22:30:51 +0200
Subject: [PATCH 52/99] Add "faq" and "help" links in appdata.xml file
---
misc/qutebrowser.appdata.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index 8684beecc..ba333702f 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -36,6 +36,8 @@
https://www.qutebrowser.org
+ https://qutebrowser.org/doc/faq.html
+ https://qutebrowser.org/doc/help/
https://github.com/qutebrowser/qutebrowser/issues/
https://github.com/qutebrowser/qutebrowser#donating
From 8acd014d39acce2643f206bd8cbeda816f9c0c81 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Mon, 16 Oct 2017 15:54:18 +0200
Subject: [PATCH 53/99] Ignore new Qt 5.10 debug build messages
---
tests/end2end/fixtures/quteprocess.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py
index 8a976ba96..4f5f3a572 100644
--- a/tests/end2end/fixtures/quteprocess.py
+++ b/tests/end2end/fixtures/quteprocess.py
@@ -105,6 +105,12 @@ def is_ignored_lowlevel_message(message):
elif (message.startswith('QNetworkProxyFactory: factory 0x') and
message.endswith(' has returned an empty result set')):
return True
+ elif message == ' Error: No such file or directory':
+ # Qt 5.10 with debug Chromium
+ # [1016/155149.941048:WARNING:stack_trace_posix.cc(625)] Failed to open
+ # file: /home/florian/#14687139 (deleted)
+ # Error: No such file or directory
+ return True
return False
@@ -170,6 +176,12 @@ def is_ignored_chromium_message(line):
# WebFrame LEAKED 1 TIMES
'WebFrame LEAKED 1 TIMES',
+ # Qt 5.10 with debug Chromium
+ # [1016/155149.941048:WARNING:stack_trace_posix.cc(625)] Failed to open
+ # file: /home/florian/#14687139 (deleted)
+ # Error: No such file or directory
+ 'Failed to open file: * (deleted)',
+
# macOS on Travis
# [5140:5379:0911/063441.239771:ERROR:mach_port_broker.mm(175)]
# Unknown process 5176 is sending Mach IPC messages!
From 544c508fac0e955ef66b19e9a8d08c8451370890 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 06:22:40 +0200
Subject: [PATCH 54/99] Add standardpaths_tester.py
---
scripts/dev/standardpaths_tester.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 scripts/dev/standardpaths_tester.py
diff --git a/scripts/dev/standardpaths_tester.py b/scripts/dev/standardpaths_tester.py
new file mode 100644
index 000000000..e9bdd6e4c
--- /dev/null
+++ b/scripts/dev/standardpaths_tester.py
@@ -0,0 +1,18 @@
+import os
+import sys
+
+from PyQt5.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion,
+ QStandardPaths)
+
+print("Python {}".format(sys.version))
+print("os.name: {}".format(os.name))
+print("sys.platform: {}".format(sys.platform))
+print()
+
+print("Qt {}, compiled {}".format(qVersion(), QT_VERSION_STR))
+print("PyQt {}".format(PYQT_VERSION_STR))
+print()
+
+for name, obj in vars(QStandardPaths).items():
+ if isinstance(obj, QStandardPaths.StandardLocation):
+ print("{:25} {}".format(name, QStandardPaths.writableLocation(obj)))
From d8384ced0a958e9841dfbb7f7b0d75f1f8c92f19 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 06:26:42 +0200
Subject: [PATCH 55/99] Show better error message when trying to toggle with
:set
---
doc/changelog.asciidoc | 5 +++++
qutebrowser/config/configcommands.py | 4 ++++
tests/unit/config/test_configcommands.py | 14 ++++++++++++--
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 3e2aeeb12..f0af67b97 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -42,6 +42,11 @@ Fixed
- Handle a filesystem going read-only gracefully
- Fix wrong rendering of keys like `` in the completion
+Changed
+~~~~~~~
+
+- Nicer error messages and other minor improvements
+
v1.0.1
------
diff --git a/qutebrowser/config/configcommands.py b/qutebrowser/config/configcommands.py
index 5848c9680..340175f23 100644
--- a/qutebrowser/config/configcommands.py
+++ b/qutebrowser/config/configcommands.py
@@ -75,6 +75,10 @@ class ConfigCommands:
tabbed_browser.openurl(QUrl('qute://settings'), newtab=False)
return
+ if option.endswith('!'):
+ raise cmdexc.CommandError("Toggling values was moved to the "
+ ":config-cycle command")
+
if option.endswith('?') and option != '?':
self._print_value(option[:-1])
return
diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py
index 1841e6260..c33bb54d4 100644
--- a/tests/unit/config/test_configcommands.py
+++ b/tests/unit/config/test_configcommands.py
@@ -133,9 +133,9 @@ class TestSet:
"QtWebEngine backend!"):
commands.set(0, 'content.cookies.accept', 'all')
- @pytest.mark.parametrize('option', ['?', '!', 'url.auto_search'])
+ @pytest.mark.parametrize('option', ['?', 'url.auto_search'])
def test_empty(self, commands, option):
- """Run ':set ?' / ':set !' / ':set url.auto_search'.
+ """Run ':set ?' / ':set url.auto_search'.
Should show an error.
See https://github.com/qutebrowser/qutebrowser/issues/1109
@@ -145,6 +145,16 @@ class TestSet:
"value"):
commands.set(win_id=0, option=option)
+ def test_toggle(self, commands):
+ """Try toggling a value.
+
+ Should show an nicer error.
+ """
+ with pytest.raises(cmdexc.CommandError,
+ match="Toggling values was moved to the "
+ ":config-cycle command"):
+ commands.set(win_id=0, option='javascript.enabled!')
+
def test_invalid(self, commands):
"""Run ':set foo?'.
From 1a7612e559560e8b1a1fb95ebaf9151a3643e9c4 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 06:28:22 +0200
Subject: [PATCH 56/99] Bump up yaml timeout a bit
---
qutebrowser/utils/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py
index d8e63af1a..018a0f18a 100644
--- a/qutebrowser/utils/utils.py
+++ b/qutebrowser/utils/utils.py
@@ -882,7 +882,7 @@ def yaml_load(f):
end = datetime.datetime.now()
delta = (end - start).total_seconds()
- deadline = 3 if 'CI' in os.environ else 1
+ deadline = 3 if 'CI' in os.environ else 2
if delta > deadline: # pragma: no cover
log.misc.warning(
"YAML load took unusually long, please report this at "
From db874d8bbab6c027451480e157b7f7bc572d2419 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 06:34:08 +0200
Subject: [PATCH 57/99] Show apps with/without QApplication in
standardpaths_tester
---
scripts/dev/standardpaths_tester.py | 48 ++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 11 deletions(-)
diff --git a/scripts/dev/standardpaths_tester.py b/scripts/dev/standardpaths_tester.py
index e9bdd6e4c..dd7117b32 100644
--- a/scripts/dev/standardpaths_tester.py
+++ b/scripts/dev/standardpaths_tester.py
@@ -2,17 +2,43 @@ import os
import sys
from PyQt5.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion,
- QStandardPaths)
+ QStandardPaths, QCoreApplication)
-print("Python {}".format(sys.version))
-print("os.name: {}".format(os.name))
-print("sys.platform: {}".format(sys.platform))
-print()
-print("Qt {}, compiled {}".format(qVersion(), QT_VERSION_STR))
-print("PyQt {}".format(PYQT_VERSION_STR))
-print()
+def print_header():
+ print("Python {}".format(sys.version))
+ print("os.name: {}".format(os.name))
+ print("sys.platform: {}".format(sys.platform))
+ print()
-for name, obj in vars(QStandardPaths).items():
- if isinstance(obj, QStandardPaths.StandardLocation):
- print("{:25} {}".format(name, QStandardPaths.writableLocation(obj)))
+ print("Qt {}, compiled {}".format(qVersion(), QT_VERSION_STR))
+ print("PyQt {}".format(PYQT_VERSION_STR))
+ print()
+
+
+def print_paths():
+ for name, obj in vars(QStandardPaths).items():
+ if isinstance(obj, QStandardPaths.StandardLocation):
+ print("{:25} {}".format(name, QStandardPaths.writableLocation(obj)))
+
+
+def main():
+ print_header()
+
+ print("No QApplication")
+ print("===============")
+ print()
+ print_paths()
+
+ app = QCoreApplication(sys.argv)
+ app.setApplicationName("qapp_name")
+
+ print()
+ print("With QApplication")
+ print("=================")
+ print()
+ print_paths()
+
+
+if __name__ == '__main__':
+ main()
From 6bc35a18422ae62a0b38269064f64d93f796c36c Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 07:39:09 +0200
Subject: [PATCH 58/99] Remove blank lines
---
misc/qutebrowser.appdata.xml | 2 --
1 file changed, 2 deletions(-)
diff --git a/misc/qutebrowser.appdata.xml b/misc/qutebrowser.appdata.xml
index ba333702f..bac4539ab 100644
--- a/misc/qutebrowser.appdata.xml
+++ b/misc/qutebrowser.appdata.xml
@@ -41,5 +41,3 @@
https://github.com/qutebrowser/qutebrowser/issues/
https://github.com/qutebrowser/qutebrowser#donating
-
-
From 14a63b8a82961ddcba3ad326e27fdd0767a1dca1 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 07:39:44 +0200
Subject: [PATCH 59/99] Include appdata file in MANIFEST
---
MANIFEST.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/MANIFEST.in b/MANIFEST.in
index a3ae1ee28..f09e9c0ef 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -13,6 +13,7 @@ include qutebrowser/utils/testfile
include qutebrowser/git-commit-id
include LICENSE doc/* README.asciidoc
include misc/qutebrowser.desktop
+include misc/qutebrowser.appdata.xml
include requirements.txt
include tox.ini
include qutebrowser.py
From 373ad28d2eb85861c46a255fb78cf03ac14af74e Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 07:41:15 +0200
Subject: [PATCH 60/99] Release v1.0.2
(cherry picked from commit 55a88ceea674fdfaf5577c255bc704e41e3353a3)
---
doc/changelog.asciidoc | 10 ++++++----
qutebrowser/__init__.py | 2 +-
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index f0af67b97..757b149d0 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -31,15 +31,17 @@ Fixed
- More consistent sizing for favicons with vertical tabs.
-v1.0.2 (unreleased)
--------------------
+v1.0.2
+------
Fixed
~~~~~
-- Fixed workaround for black screens with Nvidia cards
-- Mark the content.notifications setting as QtWebKit only correctly
+- Fix workaround for black screens or crashes with Nvidia cards
- Handle a filesystem going read-only gracefully
+- Fix crash when setting `fonts.monospace`
+- Fix list options not being modifyable via `.append()` in `config.py`
+- Mark the content.notifications setting as QtWebKit only correctly
- Fix wrong rendering of keys like `` in the completion
Changed
diff --git a/qutebrowser/__init__.py b/qutebrowser/__init__.py
index 0061e755b..a0da19248 100644
--- a/qutebrowser/__init__.py
+++ b/qutebrowser/__init__.py
@@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2017 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
-__version_info__ = (1, 0, 1)
+__version_info__ = (1, 0, 2)
__version__ = '.'.join(str(e) for e in __version_info__)
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."
From a8eae03ee944ae8f5e0476e17c4ef7f276c596ec Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 07:52:43 +0200
Subject: [PATCH 61/99] Update release checklist
---
doc/contributing.asciidoc | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/doc/contributing.asciidoc b/doc/contributing.asciidoc
index 2069263fd..2dda2f817 100644
--- a/doc/contributing.asciidoc
+++ b/doc/contributing.asciidoc
@@ -681,7 +681,6 @@ qutebrowser release
* Adjust `__version_info__` in `qutebrowser/__init__.py`.
* Update changelog (remove *(unreleased)*).
-* Run tests again.
* Commit.
* Create annotated git tag (`git tag -s "v1.$x.$y" -m "Release v1.$x.$y"`).
@@ -691,9 +690,9 @@ qutebrowser release
* Mark the milestone at https://github.com/qutebrowser/qutebrowser/milestones
as closed.
-* Linux: Run `python3 scripts/dev/build_release.py --upload v1.$x.$y`.
-* Windows: Run `C:\Python36-32\python scripts\dev\build_release.py --asciidoc C:\Python27\python C:\asciidoc-8.6.9\asciidoc.py --upload v1.X.Y` (replace X/Y by hand).
-* macOS: Run `python3 scripts/dev/build_release.py --upload v1.X.Y` (replace X/Y by hand).
+* Linux: Run `git checkout v1.$x.$y && python3 scripts/dev/build_release.py --upload v1.$x.$y`.
+* Windows: Run `git checkout v1.X.Y; C:\Python36-32\python scripts\dev\build_release.py --asciidoc C:\Python27\python C:\asciidoc-8.6.9\asciidoc.py --upload v1.X.Y` (replace X/Y by hand).
+* macOS: Run `git checkout v1.X.Y && python3 scripts/dev/build_release.py --upload v1.X.Y` (replace X/Y by hand).
* On server: Run `python3 scripts/dev/download_release.py v1.X.Y` (replace X/Y by hand).
* Update `qutebrowser-git` PKGBUILD if dependencies/install changed.
* Announce to qutebrowser and qutebrowser-announce mailinglist.
From 8d169597ae79fb492edcb4a7c7b79e417cab0cdc Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 09:06:52 +0200
Subject: [PATCH 62/99] Fix lint for standardpaths_tester
---
scripts/dev/standardpaths_tester.py | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/scripts/dev/standardpaths_tester.py b/scripts/dev/standardpaths_tester.py
index dd7117b32..a53b0320a 100644
--- a/scripts/dev/standardpaths_tester.py
+++ b/scripts/dev/standardpaths_tester.py
@@ -1,3 +1,25 @@
+#!/usr/bin/env python3
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2017 Florian Bruhin (The Compiler)
+#
+# This file is part of qutebrowser.
+#
+# qutebrowser is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# qutebrowser is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with qutebrowser. If not, see .
+
+"""Show various QStandardPath paths."""
+
import os
import sys
@@ -6,6 +28,7 @@ from PyQt5.QtCore import (QT_VERSION_STR, PYQT_VERSION_STR, qVersion,
def print_header():
+ """Show system information."""
print("Python {}".format(sys.version))
print("os.name: {}".format(os.name))
print("sys.platform: {}".format(sys.platform))
@@ -19,7 +42,8 @@ def print_header():
def print_paths():
for name, obj in vars(QStandardPaths).items():
if isinstance(obj, QStandardPaths.StandardLocation):
- print("{:25} {}".format(name, QStandardPaths.writableLocation(obj)))
+ location = QStandardPaths.writableLocation(obj)
+ print("{:25} {}".format(name, location))
def main():
From 2c867889016445f2e78f52582929f80d12825f39 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 09:14:02 +0200
Subject: [PATCH 63/99] Update changelog
---
doc/changelog.asciidoc | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 757b149d0..db84d803e 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -25,12 +25,20 @@ Added
- New `colors.statusbar.passthrough.fg`/`.bg` settings.
- New `completion.delay` and `completion.min_chars` settings to update the
completion less often.
+- New `:tab-give` and `:tab-take` commands, to give tabs to another window, or
+ take them from another window.
Fixed
~~~~~
- More consistent sizing for favicons with vertical tabs.
+Removed
+~~~~~~~
+
+- `:tab-detach` has been removed, as `:tab-give` without argument can be used
+ instead.
+
v1.0.2
------
From ced4713fda1619bb6131e0dd9a02b227d18efc60 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 09:14:59 +0200
Subject: [PATCH 64/99] Reverse if/else
---
qutebrowser/browser/commands.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index a3eed85df..2e8ed2ade 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -543,16 +543,17 @@ class CommandDispatcher:
if win_id == self._win_id:
raise cmdexc.CommandError("Can't give a tab to the same window")
- if win_id is not None:
- tabbed_browser = objreg.get('tabbed-browser', scope='window',
- window=win_id)
- else:
+ if win_id is None:
if self._count() < 2:
raise cmdexc.CommandError("Cannot detach from a window with "
"only one tab")
tabbed_browser = self._new_tabbed_browser(
- private=self._tabbed_browser.private)
+ private=self._tabbed_browser.private)
+ else:
+ tabbed_browser = objreg.get('tabbed-browser', scope='window',
+ window=win_id)
+
tabbed_browser.tabopen(self._current_url())
self._tabbed_browser.close_tab(self._current_widget(), add_undo=False)
From f84af0a6fb1a8afaf5edf2b77ffa3172cd4756e2 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 09:33:20 +0200
Subject: [PATCH 65/99] Fix docstring
---
qutebrowser/browser/commands.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 2e8ed2ade..0575d01d2 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -1044,7 +1044,7 @@ class CommandDispatcher:
self._open(url, tab, bg, window)
def _resolve_buffer_index(self, index):
- """Resolves a buffer index to the tabbedbrowser and tab.
+ """Resolve a buffer index to the tabbedbrowser and tab.
Args:
index: The [win_id/]index of the tab to be selected. Or a substring
From f1ddf58260936ecdcb2932997d5ac8955ebc6ee8 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 10:28:28 +0200
Subject: [PATCH 66/99] Add a deprecated :tab-detach
---
doc/changelog.asciidoc | 6 +++---
qutebrowser/browser/commands.py | 6 ++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index db84d803e..bd29784fe 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -33,10 +33,10 @@ Fixed
- More consistent sizing for favicons with vertical tabs.
-Removed
-~~~~~~~
+Deprecated
+~~~~~~~~~~
-- `:tab-detach` has been removed, as `:tab-give` without argument can be used
+- `:tab-detach` has been deprecated, as `:tab-give` without argument can be used
instead.
v1.0.2
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 0575d01d2..2983bbd02 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -557,6 +557,12 @@ class CommandDispatcher:
tabbed_browser.tabopen(self._current_url())
self._tabbed_browser.close_tab(self._current_widget(), add_undo=False)
+ @cmdutils.register(instance='command-dispatcher', hide=True, scope='window',
+ deprecated='Use :tab-give instead!')
+ def tab_detach(self):
+ """Deprecated way to detach a tab."""
+ self.tab_give()
+
def _back_forward(self, tab, bg, window, count, forward):
"""Helper function for :back/:forward."""
history = self._current_widget().history
From 458a45c172a87c5917f097d33306e0e24451cc40 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 10:31:45 +0200
Subject: [PATCH 67/99] Remove old deprecated commands
---
doc/changelog.asciidoc | 6 ++++
qutebrowser/browser/commands.py | 45 --------------------------
qutebrowser/mainwindow/prompt.py | 14 --------
tests/end2end/features/prompts.feature | 16 ---------
4 files changed, 6 insertions(+), 75 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index bd29784fe..1d30a6d9e 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -39,6 +39,12 @@ Deprecated
- `:tab-detach` has been deprecated, as `:tab-give` without argument can be used
instead.
+Removed
+~~~~~~~
+
+- The long-deprecated `:prompt-yes`, `:prompt-no`, `:paste-primary` and `:paste`
+ commands have been removed.
+
v1.0.2
------
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 2983bbd02..801ff290d 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -1012,43 +1012,6 @@ class CommandDispatcher:
else:
raise cmdexc.CommandError("Last tab")
- @cmdutils.register(instance='command-dispatcher', scope='window',
- deprecated="Use :open {clipboard}")
- def paste(self, sel=False, tab=False, bg=False, window=False):
- """Open a page from the clipboard.
-
- If the pasted text contains newlines, each line gets opened in its own
- tab.
-
- Args:
- sel: Use the primary selection instead of the clipboard.
- tab: Open in a new tab.
- bg: Open in a background tab.
- window: Open in new window.
- """
- force_search = False
- if not utils.supports_selection():
- sel = False
- try:
- text = utils.get_clipboard(selection=sel)
- except utils.ClipboardError as e:
- raise cmdexc.CommandError(e)
- text_urls = [u for u in text.split('\n') if u.strip()]
- if (len(text_urls) > 1 and not urlutils.is_url(text_urls[0]) and
- urlutils.get_path_if_valid(
- text_urls[0], check_exists=True) is None):
- force_search = True
- text_urls = [text]
- for i, text_url in enumerate(text_urls):
- if not window and i > 0:
- tab = False
- bg = True
- try:
- url = urlutils.fuzzy_url(text_url, force_search=force_search)
- except urlutils.InvalidUrlError as e:
- raise cmdexc.CommandError(e)
- self._open(url, tab, bg, window)
-
def _resolve_buffer_index(self, index):
"""Resolve a buffer index to the tabbedbrowser and tab.
@@ -1676,14 +1639,6 @@ class CommandDispatcher:
except webelem.Error as e:
raise cmdexc.CommandError(str(e))
- @cmdutils.register(instance='command-dispatcher',
- deprecated="Use :insert-text {primary}",
- modes=[KeyMode.insert], hide=True, scope='window',
- backend=usertypes.Backend.QtWebKit)
- def paste_primary(self):
- """Paste the primary selection at cursor position."""
- self.insert_text(utils.get_clipboard(selection=True, fallback=True))
-
@cmdutils.register(instance='command-dispatcher', maxsplit=0,
scope='window')
def insert_text(self, text):
diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py
index 1f4c47c78..d00e57174 100644
--- a/qutebrowser/mainwindow/prompt.py
+++ b/qutebrowser/mainwindow/prompt.py
@@ -388,20 +388,6 @@ class PromptContainer(QWidget):
message.global_bridge.prompt_done.emit(self._prompt.KEY_MODE)
question.done()
- @cmdutils.register(instance='prompt-container', hide=True, scope='window',
- modes=[usertypes.KeyMode.yesno],
- deprecated='Use :prompt-accept yes instead!')
- def prompt_yes(self):
- """Answer yes to a yes/no prompt."""
- self.prompt_accept('yes')
-
- @cmdutils.register(instance='prompt-container', hide=True, scope='window',
- modes=[usertypes.KeyMode.yesno],
- deprecated='Use :prompt-accept no instead!')
- def prompt_no(self):
- """Answer no to a yes/no prompt."""
- self.prompt_accept('no')
-
@cmdutils.register(instance='prompt-container', hide=True, scope='window',
modes=[usertypes.KeyMode.prompt], maxsplit=0)
def prompt_open_download(self, cmdline: str = None):
diff --git a/tests/end2end/features/prompts.feature b/tests/end2end/features/prompts.feature
index 7f8ba291d..b11a214b6 100644
--- a/tests/end2end/features/prompts.feature
+++ b/tests/end2end/features/prompts.feature
@@ -387,22 +387,6 @@ Feature: Prompts
Then the javascript message "confirm reply: true" should be logged
And the error "No default value was set for this question!" should be shown
- Scenario: Javascript confirm with deprecated :prompt-yes command
- When I open data/prompt/jsconfirm.html
- And I run :click-element id button
- And I wait for a prompt
- And I run :prompt-yes
- Then the javascript message "confirm reply: true" should be logged
- And the warning "prompt-yes is deprecated - Use :prompt-accept yes instead!" should be shown
-
- Scenario: Javascript confirm with deprecated :prompt-no command
- When I open data/prompt/jsconfirm.html
- And I run :click-element id button
- And I wait for a prompt
- And I run :prompt-no
- Then the javascript message "confirm reply: false" should be logged
- And the warning "prompt-no is deprecated - Use :prompt-accept no instead!" should be shown
-
# Other
@qtwebengine_skip
From 44e5dc1c5a7d07144603b3bd1785f7e081902651 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 10:45:58 +0200
Subject: [PATCH 68/99] Add a comment to @xfail_norun
---
tests/end2end/features/tabs.feature | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
index 4c35547dc..8a3c38775 100644
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -990,7 +990,7 @@ Feature: Tab management
# :tab-take
- @xfail_norun
+ @xfail_norun # Needs qutewm
Scenario: Take a tab from another window
Given I have a fresh instance
When I open data/numbers/1.txt
@@ -1015,7 +1015,7 @@ Feature: Tab management
# :tab-give
- @xfail_norun
+ @xfail_norun # Needs qutewm
Scenario: Give a tab to another window
Given I have a fresh instance
When I open data/numbers/1.txt
From c3441ae4a8d81c90a0ee90846d6d4d4a01bf1fe2 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 11:34:46 +0200
Subject: [PATCH 69/99] Update changelog
---
doc/changelog.asciidoc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 1d30a6d9e..e0b4caf6d 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -25,6 +25,8 @@ Added
- New `colors.statusbar.passthrough.fg`/`.bg` settings.
- New `completion.delay` and `completion.min_chars` settings to update the
completion less often.
+- New `completion.use_best_match` setting to automatically use the best-matching
+ command in the completion.
- New `:tab-give` and `:tab-take` commands, to give tabs to another window, or
take them from another window.
From 52423fa426753898e71ce9f4ba144fafee101df5 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 11:37:19 +0200
Subject: [PATCH 70/99] Remove unneeded variable
---
tests/unit/commands/test_runners.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/commands/test_runners.py b/tests/unit/commands/test_runners.py
index fad96c558..18db9f01c 100644
--- a/tests/unit/commands/test_runners.py
+++ b/tests/unit/commands/test_runners.py
@@ -89,7 +89,7 @@ class TestCompletions:
parser = runners.CommandParser(partial_match=True)
with pytest.raises(cmdexc.NoSuchCommandError):
- result = parser.parse('do')
+ parser.parse('do')
def test_use_best_match(self, config_stub):
"""Test multiple completion options with use_best_match set to true.
From 2e64dda592e81387d598d1c2301a374408fc6eb8 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 11:39:30 +0200
Subject: [PATCH 71/99] Clean up getting matching commands
---
qutebrowser/commands/runners.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py
index a1f4accd7..52c4ea613 100644
--- a/qutebrowser/commands/runners.py
+++ b/qutebrowser/commands/runners.py
@@ -214,10 +214,7 @@ class CommandParser:
Return:
cmdstr modified to the matching completion or unmodified
"""
- matches = []
- for valid_command in cmdutils.cmd_dict:
- if valid_command.find(cmdstr) == 0:
- matches.append(valid_command)
+ matches = [cmd for cmd in cmdutils.cmd_dict if cmdstr in cmd]
if len(matches) == 1:
cmdstr = matches[0]
elif len(matches) > 1 and config.val.completion.use_best_match:
From 4f263505eea1d35660bd9180b3fd3aaf599277d0 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 11:49:46 +0200
Subject: [PATCH 72/99] Improve tests for partial matching
---
tests/unit/commands/test_runners.py | 33 ++++++++++++++++++-----------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/tests/unit/commands/test_runners.py b/tests/unit/commands/test_runners.py
index 18db9f01c..0cbcd37a5 100644
--- a/tests/unit/commands/test_runners.py
+++ b/tests/unit/commands/test_runners.py
@@ -21,7 +21,7 @@
import pytest
-from qutebrowser.commands import runners, cmdexc
+from qutebrowser.commands import runners, cmdexc, cmdutils
class TestCommandParser:
@@ -66,19 +66,28 @@ class TestCommandParser:
with pytest.raises(cmdexc.NoSuchCommandError):
parser.parse_all(command)
- def test_partial_parsing(self):
+
+class TestCompletions:
+
+ """Tests for completions.use_best_match."""
+
+ @pytest.fixture(autouse=True)
+ def cmdutils_stub(self, monkeypatch, stubs):
+ """Patch the cmdutils module to provide fake commands."""
+ monkeypatch.setattr(cmdutils, 'cmd_dict', {
+ 'one': stubs.FakeCommand(name='one'),
+ 'two': stubs.FakeCommand(name='two'),
+ 'two-foo': stubs.FakeCommand(name='two-foo'),
+ })
+
+ def test_partial_parsing(self, config_stub):
"""Test partial parsing with a runner where it's enabled.
The same with it being disabled is tested by test_parse_all.
"""
parser = runners.CommandParser(partial_match=True)
- result = parser.parse('message-i')
- assert result.cmd.name == 'message-info'
-
-
-class TestCompletions:
-
- """Tests for completions.use_best_match."""
+ result = parser.parse('on')
+ assert result.cmd.name == 'one'
def test_dont_use_best_match(self, config_stub):
"""Test multiple completion options with use_best_match set to false.
@@ -89,7 +98,7 @@ class TestCompletions:
parser = runners.CommandParser(partial_match=True)
with pytest.raises(cmdexc.NoSuchCommandError):
- parser.parse('do')
+ parser.parse('tw')
def test_use_best_match(self, config_stub):
"""Test multiple completion options with use_best_match set to true.
@@ -99,5 +108,5 @@ class TestCompletions:
config_stub.val.completion.use_best_match = True
parser = runners.CommandParser(partial_match=True)
- result = parser.parse('do')
- assert result.cmd.name == 'download-cancel'
+ result = parser.parse('tw')
+ assert result.cmd.name == 'two'
From 2fccc083af88da7a8de3990b480a644fda9714e9 Mon Sep 17 00:00:00 2001
From: Fritz Reichwald
Date: Tue, 17 Oct 2017 12:03:27 +0200
Subject: [PATCH 73/99] fix debian install instructions to fit debian9 and new
apt
---
doc/install.asciidoc | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/doc/install.asciidoc b/doc/install.asciidoc
index 15e3ac93e..3ccc6c677 100644
--- a/doc/install.asciidoc
+++ b/doc/install.asciidoc
@@ -41,21 +41,17 @@ Debian Stretch / Ubuntu 17.04 and newer
Those versions come with QtWebEngine in the repositories. This makes it possible
to install qutebrowser via the Debian package.
-Install the dependencies via apt-get:
-
-----
-# apt install python-tox python3-{lxml,pyqt5,sip,jinja2,pygments,yaml,attr} python3-pyqt5.qt{webengine,quick,opengl,sql} libqt5sql5-sqlite
-----
-
Get the qutebrowser package from the
https://github.com/qutebrowser/qutebrowser/releases[release page] and download
the https://qutebrowser.org/python3-pypeg2_2.15.2-1_all.deb[PyPEG2 package].
+(If you are using debian testing you can just use the python3-pypeg2 package from the repos)
+
Install the packages:
----
-# dpkg -i python3-pypeg2_*_all.deb
-# dpkg -i qutebrowser_*_all.deb
+# apt install ./python3-pypeg2_*_all.deb
+# apt install ./qutebrowser_*_all.deb
----
Some additional hints:
@@ -66,7 +62,7 @@ Some additional hints:
`:help` command:
+
----
-# apt-get install --no-install-recommends asciidoc source-highlight
+# apt install --no-install-recommends asciidoc source-highlight
$ python3 scripts/asciidoc2html.py
----
@@ -76,7 +72,7 @@ $ python3 scripts/asciidoc2html.py
- If video or sound don't work with QtWebKit, try installing the gstreamer plugins:
+
----
-# apt-get install gstreamer1.0-plugins-{bad,base,good,ugly}
+# apt install gstreamer1.0-plugins-{bad,base,good,ugly}
----
On Fedora
From 161b96be1eeb4a64147df3784cdc21f49e1d68a6 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 13:10:00 +0200
Subject: [PATCH 74/99] Fix long line
---
qutebrowser/browser/commands.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 801ff290d..7f4b079c2 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -557,8 +557,8 @@ class CommandDispatcher:
tabbed_browser.tabopen(self._current_url())
self._tabbed_browser.close_tab(self._current_widget(), add_undo=False)
- @cmdutils.register(instance='command-dispatcher', hide=True, scope='window',
- deprecated='Use :tab-give instead!')
+ @cmdutils.register(instance='command-dispatcher', hide=True,
+ scope='window', deprecated='Use :tab-give instead!')
def tab_detach(self):
"""Deprecated way to detach a tab."""
self.tab_give()
From 4984c9d05cd05d031f01763001af5c56b382fe0c Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 14:57:41 +0200
Subject: [PATCH 75/99] Update docs
---
doc/help/settings.asciidoc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index 7678583b7..d9fddc2f3 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -105,6 +105,7 @@
|<>|When to show the autocompletion window.
|<>|Shrink the completion to be smaller than the configured size if there are no scrollbars.
|<>|How to format timestamps (e.g. for the history completion).
+|<>|Whether to execute the best-matching command on a partial match.
|<>|How many URLs to show in the web history.
|<>|Whether quitting the application requires a confirmation.
|<>|Whether support for the HTML 5 web application cache feature is enabled.
@@ -1391,6 +1392,14 @@ Type: <>
Default: +pass:[%Y-%m-%d]+
+[[completion.use_best_match]]
+=== completion.use_best_match
+Whether to execute the best-matching command on a partial match.
+
+Type: <>
+
+Default: +pass:[false]+
+
[[completion.web_history_max_items]]
=== completion.web_history_max_items
How many URLs to show in the web history.
From 12c959052452587a559bb55c717ced5321594474 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 15:01:37 +0200
Subject: [PATCH 76/99] Always use shortest match for completion.use_best_match
---
qutebrowser/commands/runners.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py
index 52c4ea613..fadb6c063 100644
--- a/qutebrowser/commands/runners.py
+++ b/qutebrowser/commands/runners.py
@@ -214,7 +214,8 @@ class CommandParser:
Return:
cmdstr modified to the matching completion or unmodified
"""
- matches = [cmd for cmd in cmdutils.cmd_dict if cmdstr in cmd]
+ matches = [cmd for cmd in sorted(cmdutils.cmd_dict, key=len)
+ if cmdstr in cmd]
if len(matches) == 1:
cmdstr = matches[0]
elif len(matches) > 1 and config.val.completion.use_best_match:
From 96bec9f9d7139264488dbaeb700dbed36986b5f6 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 15:33:50 +0200
Subject: [PATCH 77/99] Fix error code for "database is locked"
See #2930
---
qutebrowser/misc/sql.py | 4 ++--
tests/unit/misc/test_sql.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/misc/sql.py b/qutebrowser/misc/sql.py
index e04c3f6e3..f19de698f 100644
--- a/qutebrowser/misc/sql.py
+++ b/qutebrowser/misc/sql.py
@@ -68,9 +68,9 @@ class SqliteError(SqlError):
# https://github.com/qutebrowser/qutebrowser/issues/2930
# https://github.com/qutebrowser/qutebrowser/issues/3004
environmental_errors = [
+ '5', # SQLITE_BUSY ("database is locked")
'8', # SQLITE_READONLY
- '9', # SQLITE_LOCKED,
- '13', # SQLITE_FULL,
+ '13', # SQLITE_FULL
]
self.environmental = error.nativeErrorCode() in environmental_errors
diff --git a/tests/unit/misc/test_sql.py b/tests/unit/misc/test_sql.py
index fdd5c89c8..89c442b2b 100644
--- a/tests/unit/misc/test_sql.py
+++ b/tests/unit/misc/test_sql.py
@@ -39,7 +39,7 @@ def test_sqlerror():
class TestSqliteError:
@pytest.mark.parametrize('error_code, environmental', [
- ('9', True), # SQLITE_LOCKED
+ ('5', True), # SQLITE_BUSY
('19', False), # SQLITE_CONSTRAINT
])
def test_environmental(self, error_code, environmental):
From 5c6a821b1e9ab0569c0d4e0179dc52b67997e10e Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 15:35:17 +0200
Subject: [PATCH 78/99] Update changelog
---
doc/changelog.asciidoc | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index e0b4caf6d..665e7d013 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -47,6 +47,14 @@ Removed
- The long-deprecated `:prompt-yes`, `:prompt-no`, `:paste-primary` and `:paste`
commands have been removed.
+v1.0.3 (unreleased)
+-------------------
+
+Fixed
+~~~~~
+
+- Handle accessing a locked sqlite database gracefully
+
v1.0.2
------
From 95761c5023967625b0e4b28bc4b490fbfb7a5604 Mon Sep 17 00:00:00 2001
From: Jay Kamat
Date: Tue, 17 Oct 2017 10:36:37 -0400
Subject: [PATCH 79/99] Fix crashes on qute_pylint module when not running in
the root
Useful for editors that run from non-root directories for
integrations, but skips some tests. Shouldn't impact tests run normally.
---
.../dev/pylint_checkers/qute_pylint/config.py | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/scripts/dev/pylint_checkers/qute_pylint/config.py b/scripts/dev/pylint_checkers/qute_pylint/config.py
index df08e6833..3b29942e3 100644
--- a/scripts/dev/pylint_checkers/qute_pylint/config.py
+++ b/scripts/dev/pylint_checkers/qute_pylint/config.py
@@ -27,9 +27,11 @@ import yaml
import astroid
from pylint import interfaces, checkers
from pylint.checkers import utils
+from pathlib import Path
OPTIONS = None
+FAILED_LOAD = False
class ConfigChecker(checkers.BaseChecker):
@@ -44,6 +46,7 @@ class ConfigChecker(checkers.BaseChecker):
None),
}
priority = -1
+ printed_warning = False
@utils.check_messages('bad-config-option')
def visit_attribute(self, node):
@@ -58,6 +61,13 @@ class ConfigChecker(checkers.BaseChecker):
def _check_config(self, node, name):
"""Check that we're accessing proper config options."""
+ if FAILED_LOAD:
+ if not ConfigChecker.printed_warning:
+ print("[WARN] Could not find configdata.yml. Please run " +
+ "pylint from qutebrowser root.", file=sys.stderr)
+ print("Skipping some checks...", file=sys.stderr)
+ ConfigChecker.printed_warning = True
+ return
if name not in OPTIONS:
self.add_message('bad-config-option', node=node, args=name)
@@ -66,6 +76,11 @@ def register(linter):
"""Register this checker."""
linter.register_checker(ConfigChecker(linter))
global OPTIONS
- yaml_file = os.path.join('qutebrowser', 'config', 'configdata.yml')
- with open(yaml_file, 'r', encoding='utf-8') as f:
+ global FAILED_LOAD
+ yaml_file = Path('qutebrowser') / 'config' / 'configdata.yml'
+ if not yaml_file.exists():
+ OPTIONS = None
+ FAILED_LOAD = True
+ return
+ with yaml_file.open(mode='r', encoding='utf-8') as f:
OPTIONS = list(yaml.load(f))
From 5d11a1fd75dc1651ba3e58284e9a117d1c67c435 Mon Sep 17 00:00:00 2001
From: Jay Kamat
Date: Tue, 17 Oct 2017 11:19:37 -0400
Subject: [PATCH 80/99] Prevent :home from bypassing pinned tab warnings
Closes #3138
---
qutebrowser/browser/commands.py | 6 +++++-
tests/end2end/features/tabs.feature | 8 ++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 7f4b079c2..256894d49 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -353,6 +353,10 @@ class CommandDispatcher:
Return:
A list of URLs that can be opened.
"""
+ if isinstance(url, QUrl):
+ yield url
+ return
+
force_search = False
urllist = [u for u in url.split('\n') if u.strip()]
if (len(urllist) > 1 and not urlutils.is_url(urllist[0]) and
@@ -1210,7 +1214,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
def home(self):
"""Open main startpage in current tab."""
- self._current_widget().openurl(config.val.url.start_pages[0])
+ self.openurl(config.val.url.start_pages[0])
def _run_userscript(self, cmd, *args, verbose=False):
"""Run a userscript given as argument.
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
index 8a3c38775..c516bfaa7 100644
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -1197,6 +1197,14 @@ Feature: Tab management
And the following tabs should be open:
- data/numbers/1.txt (active) (pinned)
+ Scenario: :tab-pin open url
+ When I open data/numbers/1.txt
+ And I run :tab-pin
+ And I run :home
+ Then the message "Tab is pinned!" should be shown
+ And the following tabs should be open:
+ - data/numbers/1.txt (active) (pinned)
+
Scenario: Cloning a pinned tab
When I open data/numbers/1.txt
And I run :tab-pin
From 62b6d62cd7eddd115f0e23c049ee0c7977f33442 Mon Sep 17 00:00:00 2001
From: Jay Kamat
Date: Tue, 17 Oct 2017 14:22:18 -0400
Subject: [PATCH 81/99] Clean up sub-module import and unneeded +
---
scripts/dev/pylint_checkers/qute_pylint/config.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/scripts/dev/pylint_checkers/qute_pylint/config.py b/scripts/dev/pylint_checkers/qute_pylint/config.py
index 3b29942e3..5ad65cd00 100644
--- a/scripts/dev/pylint_checkers/qute_pylint/config.py
+++ b/scripts/dev/pylint_checkers/qute_pylint/config.py
@@ -20,14 +20,11 @@
"""Custom astroid checker for config calls."""
import sys
-import os
-import os.path
-
+import pathlib
import yaml
import astroid
from pylint import interfaces, checkers
from pylint.checkers import utils
-from pathlib import Path
OPTIONS = None
@@ -63,7 +60,7 @@ class ConfigChecker(checkers.BaseChecker):
"""Check that we're accessing proper config options."""
if FAILED_LOAD:
if not ConfigChecker.printed_warning:
- print("[WARN] Could not find configdata.yml. Please run " +
+ print("[WARN] Could not find configdata.yml. Please run "
"pylint from qutebrowser root.", file=sys.stderr)
print("Skipping some checks...", file=sys.stderr)
ConfigChecker.printed_warning = True
@@ -77,7 +74,7 @@ def register(linter):
linter.register_checker(ConfigChecker(linter))
global OPTIONS
global FAILED_LOAD
- yaml_file = Path('qutebrowser') / 'config' / 'configdata.yml'
+ yaml_file = pathlib.Path('qutebrowser') / 'config' / 'configdata.yml'
if not yaml_file.exists():
OPTIONS = None
FAILED_LOAD = True
From 807b7701d5c9b110a61bb31e8a10e0d0fcdf9337 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 21:11:14 +0200
Subject: [PATCH 82/99] Re-add blank line
---
scripts/dev/pylint_checkers/qute_pylint/config.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/dev/pylint_checkers/qute_pylint/config.py b/scripts/dev/pylint_checkers/qute_pylint/config.py
index 5ad65cd00..da7fbf32f 100644
--- a/scripts/dev/pylint_checkers/qute_pylint/config.py
+++ b/scripts/dev/pylint_checkers/qute_pylint/config.py
@@ -21,6 +21,7 @@
import sys
import pathlib
+
import yaml
import astroid
from pylint import interfaces, checkers
From 828ffd49797bf713d81e7e3d124ce91397c55c81 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 21:19:46 +0200
Subject: [PATCH 83/99] Update changelog
---
doc/changelog.asciidoc | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 665e7d013..8faf5452a 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -34,6 +34,7 @@ Fixed
~~~~~
- More consistent sizing for favicons with vertical tabs.
+- Using `:home` on pinned tabs is now prevented.
Deprecated
~~~~~~~~~~
From 9dc9bcaf39cb3560478bd9d71f73ba346516bd36 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Tue, 17 Oct 2017 22:37:14 +0200
Subject: [PATCH 84/99] Make standarddir work on HaikuOS
For some reason, it returns an empty DataLocation.
---
qutebrowser/utils/standarddir.py | 5 +++++
tests/unit/utils/test_standarddir.py | 14 ++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/qutebrowser/utils/standarddir.py b/qutebrowser/utils/standarddir.py
index d6ad7fc39..c5ee356c0 100644
--- a/qutebrowser/utils/standarddir.py
+++ b/qutebrowser/utils/standarddir.py
@@ -20,6 +20,7 @@
"""Utilities to get and initialize data/config paths."""
import os
+import sys
import shutil
import os.path
import contextlib
@@ -106,6 +107,10 @@ def _init_data(args):
if utils.is_windows:
app_data_path = _writable_location(QStandardPaths.AppDataLocation)
path = os.path.join(app_data_path, 'data')
+ elif sys.platform.startswith('haiku'):
+ # HaikuOS returns an empty value for AppDataLocation
+ config_path = _writable_location(QStandardPaths.ConfigLocation)
+ path = os.path.join(config_path, 'data')
else:
path = _writable_location(typ)
_create(path)
diff --git a/tests/unit/utils/test_standarddir.py b/tests/unit/utils/test_standarddir.py
index 20ea88645..1b9e473d1 100644
--- a/tests/unit/utils/test_standarddir.py
+++ b/tests/unit/utils/test_standarddir.py
@@ -103,6 +103,20 @@ def test_fake_windows(tmpdir, monkeypatch, what):
assert func() == str(tmpdir / APPNAME / what)
+def test_fake_haiku(tmpdir, monkeypatch):
+ """Test getting data dir on HaikuOS."""
+ locations = {
+ QStandardPaths.DataLocation: '',
+ QStandardPaths.ConfigLocation: str(tmpdir / 'config' / APPNAME),
+ }
+ monkeypatch.setattr(standarddir.QStandardPaths, 'writableLocation',
+ locations.get)
+ monkeypatch.setattr(standarddir.sys, 'platform', 'haiku1')
+
+ standarddir._init_data(args=None)
+ assert standarddir.data() == str(tmpdir / 'config' / APPNAME / 'data')
+
+
class TestWritableLocation:
"""Tests for _writable_location."""
From 354c3c8c9b3e75988b334c1526b654c3e7caf8d9 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Wed, 18 Oct 2017 09:02:39 +0200
Subject: [PATCH 85/99] Handle unknown filetypes with qute://help
---
doc/changelog.asciidoc | 1 +
qutebrowser/browser/qutescheme.py | 9 ++++++---
tests/unit/browser/test_qutescheme.py | 23 +++++++++++++++++++++++
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 8faf5452a..03eca9485 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -35,6 +35,7 @@ Fixed
- More consistent sizing for favicons with vertical tabs.
- Using `:home` on pinned tabs is now prevented.
+- Fix crash with unknown file types loaded via qute://help
Deprecated
~~~~~~~~~~
diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py
index b49520002..2498ea7f6 100644
--- a/qutebrowser/browser/qutescheme.py
+++ b/qutebrowser/browser/qutescheme.py
@@ -29,8 +29,9 @@ import os
import time
import urllib.parse
import textwrap
-import pkg_resources
+import mimetypes
+import pkg_resources
from PyQt5.QtCore import QUrlQuery, QUrl
import qutebrowser
@@ -323,8 +324,10 @@ def qute_help(url):
"scripts/asciidoc2html.py.")
path = 'html/doc/{}'.format(urlpath)
- if urlpath.endswith('.png'):
- return 'image/png', utils.read_file(path, binary=True)
+ if not urlpath.endswith('.html'):
+ mimetype, _encoding = mimetypes.guess_type(urlpath)
+ assert mimetype is not None, url
+ return mimetype, utils.read_file(path, binary=True)
try:
data = utils.read_file(path)
diff --git a/tests/unit/browser/test_qutescheme.py b/tests/unit/browser/test_qutescheme.py
index 02e0c484d..6fdaad83c 100644
--- a/tests/unit/browser/test_qutescheme.py
+++ b/tests/unit/browser/test_qutescheme.py
@@ -146,3 +146,26 @@ class TestHistoryHandler:
url = QUrl("qute://history/data?start_time={}".format(now))
_mimetype, data = benchmark(qutescheme.qute_history, url)
assert len(json.loads(data)) > 1
+
+
+class TestHelpHandler:
+
+ """Tests for qute://help."""
+
+ @pytest.fixture
+ def data_patcher(self, monkeypatch):
+ def _patch(path, data):
+ def _read_file(name, binary=False):
+ assert path == name
+ if binary:
+ return data
+ return data.decode('utf-8')
+
+ monkeypatch.setattr(qutescheme.utils, 'read_file', _read_file)
+ return _patch
+
+ def test_unknown_file_type(self, data_patcher):
+ data_patcher('html/doc/foo.bin', b'\xff')
+ mimetype, data = qutescheme.qute_help(QUrl('qute://help/foo.bin'))
+ assert mimetype == 'application/octet-stream'
+ assert data == b'\xff'
From 34787edf4ec5ae49b97a4e09bc00b5421a950a85 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Wed, 18 Oct 2017 10:46:12 +0200
Subject: [PATCH 86/99] Add Xresources to config recipes
[ci skip]
---
doc/help/configuring.asciidoc | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index 997e47246..e442b03a6 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -347,6 +347,26 @@ def bind_chained(key, *commands):
bind_chained('', 'clear-keychain', 'search')
----
+Reading colors from Xresources
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can use something like this to read colors from an `~/.Xresources` file:
+
+[source,python]
+----
+def read_xresources(prefix):
+ props = {}
+ x = subprocess.run(['xrdb', '-query'], stdout=subprocess.PIPE)
+ lines = x.stdout.decode().split('\n')
+ for line in filter(lambda l : l.startswith(prefix), lines):
+ prop, _, value = line.partition(':\t')
+ props[prop] = value
+ return props
+
+xresources = read_xresources('*')
+c.colors.statusbar.normal.bg = xresources['*background']
+----
+
Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^
From 5a9042ab3efb9e69f6b11a341373c302a688578b Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Wed, 18 Oct 2017 13:53:26 +0200
Subject: [PATCH 87/99] Add a config.source() method
---
doc/changelog.asciidoc | 1 +
doc/help/configuring.asciidoc | 3 +++
qutebrowser/config/configfiles.py | 9 ++++++++
tests/unit/config/test_configfiles.py | 32 +++++++++++++++++++++++++++
4 files changed, 45 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 03eca9485..99b3ef11b 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -29,6 +29,7 @@ Added
command in the completion.
- New `:tab-give` and `:tab-take` commands, to give tabs to another window, or
take them from another window.
+- New `config.source(...)` method for `config.py` to source another file.
Fixed
~~~~~
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index e442b03a6..af555beb3 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -238,6 +238,9 @@ that via `import utils` as well.
While it's in some cases possible to import code from the qutebrowser
installation, doing so is unsupported and discouraged.
+To read config data from a different file with `c` and `config` available, you
+can use `config.source('otherfile.py')` in your `config.py`.
+
Getting the config directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py
index e1a10848e..605c7372d 100644
--- a/qutebrowser/config/configfiles.py
+++ b/qutebrowser/config/configfiles.py
@@ -259,6 +259,15 @@ class ConfigAPI:
with self._handle_error('unbinding', key):
self._keyconfig.unbind(key, mode=mode)
+ def source(self, filename):
+ if not os.path.isabs(filename):
+ filename = str(self.configdir / filename)
+
+ try:
+ read_config_py(filename)
+ except configexc.ConfigFileErrors as e:
+ self.errors += e.errors
+
class ConfigPyWriter:
diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py
index 9a2ff37ab..2159a6604 100644
--- a/tests/unit/config/test_configfiles.py
+++ b/tests/unit/config/test_configfiles.py
@@ -580,6 +580,38 @@ class TestConfigPy:
assert isinstance(error.exception, ZeroDivisionError)
assert error.traceback is not None
+ @pytest.mark.parametrize('location', ['abs', 'rel'])
+ def test_source(self, tmpdir, confpy, location):
+ if location == 'abs':
+ subfile = tmpdir / 'subfile.py'
+ arg = str(subfile)
+ else:
+ subfile = tmpdir / 'config' / 'subfile.py'
+ arg = 'subfile.py'
+
+ subfile.write_text("c.content.javascript.enabled = False",
+ encoding='utf-8')
+ confpy.write("config.source('{}')".format(arg))
+ confpy.read()
+
+ assert not config.instance._values['content.javascript.enabled']
+
+ def test_source_errors(self, tmpdir, confpy):
+ subfile = tmpdir / 'config' / 'subfile.py'
+ subfile.write_text("c.foo = 42", encoding='utf-8')
+ confpy.write("config.source('subfile.py')")
+ error = confpy.read(error=True)
+
+ assert error.text == "While setting 'foo'"
+ assert isinstance(error.exception, configexc.NoOptionError)
+
+ def test_source_not_found(self, confpy):
+ confpy.write("config.source('doesnotexist.py')")
+ error = confpy.read(error=True)
+
+ assert error.text == "Error while reading doesnotexist.py"
+ assert isinstance(error.exception, FileNotFoundError)
+
class TestConfigPyWriter:
From 378498bbd7767a2277ab6fba9e54899959a7c972 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Wed, 18 Oct 2017 14:06:54 +0200
Subject: [PATCH 88/99] Add a test for multiple config.source() errors
---
tests/unit/config/test_configfiles.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py
index 2159a6604..c0ba1f1ae 100644
--- a/tests/unit/config/test_configfiles.py
+++ b/tests/unit/config/test_configfiles.py
@@ -605,6 +605,20 @@ class TestConfigPy:
assert error.text == "While setting 'foo'"
assert isinstance(error.exception, configexc.NoOptionError)
+ def test_source_multiple_errors(self, tmpdir, confpy):
+ subfile = tmpdir / 'config' / 'subfile.py'
+ subfile.write_text("c.foo = 42", encoding='utf-8')
+ confpy.write("config.source('subfile.py')", "c.bar = 23")
+
+ with pytest.raises(configexc.ConfigFileErrors) as excinfo:
+ configfiles.read_config_py(confpy.filename)
+
+ errors = excinfo.value.errors
+ assert len(errors) == 2
+
+ for error in errors:
+ assert isinstance(error.exception, configexc.NoOptionError)
+
def test_source_not_found(self, confpy):
confpy.write("config.source('doesnotexist.py')")
error = confpy.read(error=True)
From 2bfa853847a66925650894cba0afea9b5ace08dc Mon Sep 17 00:00:00 2001
From: Martin Fraga
Date: Thu, 19 Oct 2017 01:44:10 -0700
Subject: [PATCH 89/99] Add keyhint radius configuration option
The radius for the keyhint dialog box should be configurable vi via
c.keyhint.radius. The default was set to 6px, which is the previous
hardcoded value.
---
qutebrowser/config/configdata.yml | 7 +++++++
qutebrowser/misc/keyhintwidget.py | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 3d296fcaa..e5870e3fc 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -978,6 +978,13 @@ keyhint.blacklist:
Globs are supported, so `;*` will blacklist all keychains starting with `;`.
Use `*` to disable keyhints.
+keyhint.radius:
+ type:
+ name: Int
+ minval: 0
+ default: 6
+ desc: The rounding radius for the edges of the keyhint dialog.
+
# emacs: '
keyhint.delay:
diff --git a/qutebrowser/misc/keyhintwidget.py b/qutebrowser/misc/keyhintwidget.py
index ce1f324e4..98dc8e275 100644
--- a/qutebrowser/misc/keyhintwidget.py
+++ b/qutebrowser/misc/keyhintwidget.py
@@ -54,9 +54,9 @@ class KeyHintView(QLabel):
background-color: {{ conf.colors.keyhint.bg }};
padding: 6px;
{% if conf.statusbar.position == 'top' %}
- border-bottom-right-radius: 6px;
+ border-bottom-right-radius: {{ conf.keyhint.radius }}px;
{% else %}
- border-top-right-radius: 6px;
+ border-top-right-radius: {{ conf.keyhint.radius }}px;
{% endif %}
}
"""
From 455b90ecad1006281e2ebc0393f57de80aef4291 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 07:14:32 +0200
Subject: [PATCH 90/99] Log which dictionaries have been found
See #3166
---
qutebrowser/browser/webengine/webenginesettings.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py
index 47be9ffed..b74356727 100644
--- a/qutebrowser/browser/webengine/webenginesettings.py
+++ b/qutebrowser/browser/webengine/webenginesettings.py
@@ -36,7 +36,8 @@ from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import spell
from qutebrowser.config import config, websettings
-from qutebrowser.utils import utils, standarddir, javascript, qtutils, message
+from qutebrowser.utils import (utils, standarddir, javascript, qtutils, message,
+ log)
# The default QWebEngineProfile
default_profile = None
@@ -145,6 +146,7 @@ class DictionaryLanguageSetter(DefaultProfileSetter):
raise ValueError("'settings' may not be set with "
"DictionaryLanguageSetter!")
filenames = [self._find_installed(code) for code in value]
+ log.config.debug("Found dicts: {}".format(filenames))
super()._set([f for f in filenames if f], settings)
From fd8e5e30c62908bb7c5d9dc1c1eff488efa54fdc Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 07:36:51 +0200
Subject: [PATCH 91/99] Re-add scroll filtering and disable it for mark/scroll
tests
See #2233
---
qutebrowser/browser/webengine/webenginetab.py | 7 +++++--
qutebrowser/qutebrowser.py | 3 ++-
tests/end2end/features/test_marks_bdd.py | 9 +++++++++
tests/end2end/features/test_scroll_bdd.py | 9 +++++++++
4 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index a5a15e0db..1e625d93c 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -293,6 +293,7 @@ class WebEngineScroller(browsertab.AbstractScroller):
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
+ self._args = objreg.get('args')
self._pos_perc = (0, 0)
self._pos_px = QPoint()
self._at_bottom = False
@@ -333,9 +334,11 @@ class WebEngineScroller(browsertab.AbstractScroller):
perc_y = min(100, round(100 / dy * jsret['px']['y']))
self._at_bottom = math.ceil(jsret['px']['y']) >= dy
- self._pos_perc = perc_x, perc_y
- self.perc_changed.emit(*self._pos_perc)
+ if (self._pos_perc != (perc_x, perc_y) or
+ 'no-scroll-filtering' in self._args.debug_flags):
+ self._pos_perc = perc_x, perc_y
+ self.perc_changed.emit(*self._pos_perc)
js_code = javascript.assemble('scroll', 'pos')
self._tab.run_js_async(js_code, update_pos_cb)
diff --git a/qutebrowser/qutebrowser.py b/qutebrowser/qutebrowser.py
index 1b1cfb013..ad53f45ca 100644
--- a/qutebrowser/qutebrowser.py
+++ b/qutebrowser/qutebrowser.py
@@ -159,7 +159,8 @@ def debug_flag_error(flag):
debug-exit: Turn on debugging of late exit.
pdb-postmortem: Drop into pdb on exceptions.
"""
- valid_flags = ['debug-exit', 'pdb-postmortem', 'no-sql-history']
+ valid_flags = ['debug-exit', 'pdb-postmortem', 'no-sql-history',
+ 'no-scroll-filtering']
if flag in valid_flags:
return flag
diff --git a/tests/end2end/features/test_marks_bdd.py b/tests/end2end/features/test_marks_bdd.py
index 5b8e352dd..5d31298ff 100644
--- a/tests/end2end/features/test_marks_bdd.py
+++ b/tests/end2end/features/test_marks_bdd.py
@@ -17,10 +17,19 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see .
+import pytest
+
import pytest_bdd as bdd
bdd.scenarios('marks.feature')
+@pytest.fixture(autouse=True)
+def turn_on_scroll_logging(quteproc):
+ """Make sure all scrolling changes are logged."""
+ quteproc.send_cmd(":debug-pyeval -q objreg.get('args')."
+ "debug_flags.append('no-scroll-filtering')")
+
+
@bdd.then(bdd.parsers.parse("the page should be scrolled to {x} {y}"))
def check_y(request, quteproc, x, y):
data = quteproc.get_session()
diff --git a/tests/end2end/features/test_scroll_bdd.py b/tests/end2end/features/test_scroll_bdd.py
index 69199ebf3..966d5c9bb 100644
--- a/tests/end2end/features/test_scroll_bdd.py
+++ b/tests/end2end/features/test_scroll_bdd.py
@@ -17,5 +17,14 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see .
+import pytest
+
import pytest_bdd as bdd
bdd.scenarios('scroll.feature')
+
+
+@pytest.fixture(autouse=True)
+def turn_on_scroll_logging(quteproc):
+ """Make sure all scrolling changes are logged."""
+ quteproc.send_cmd(":debug-pyeval -q objreg.get('args')."
+ "debug_flags.append('no-scroll-filtering')")
From 280dddda6b5e078eaf89d5ed8599f60857ff9349 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 08:07:10 +0200
Subject: [PATCH 92/99] Set backend in TestRectOnView.test_zoomed
---
tests/unit/browser/webkit/test_webkitelem.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tests/unit/browser/webkit/test_webkitelem.py b/tests/unit/browser/webkit/test_webkitelem.py
index 871241a04..3174d7281 100644
--- a/tests/unit/browser/webkit/test_webkitelem.py
+++ b/tests/unit/browser/webkit/test_webkitelem.py
@@ -31,6 +31,8 @@ QWebElement = pytest.importorskip('PyQt5.QtWebKit').QWebElement
from qutebrowser.browser import webelem
from qutebrowser.browser.webkit import webkitelem
+from qutebrowser.misc import objects
+from qutebrowser.utils import usertypes
def get_webelem(geometry=None, frame=None, *, null=False, style=None,
@@ -715,8 +717,10 @@ class TestRectOnView:
@pytest.mark.parametrize('js_rect', [None, {}])
@pytest.mark.parametrize('zoom_text_only', [True, False])
- def test_zoomed(self, stubs, config_stub, js_rect, zoom_text_only):
+ def test_zoomed(self, stubs, config_stub, js_rect, monkeypatch,
+ zoom_text_only):
"""Make sure the coordinates are adjusted when zoomed."""
+ monkeypatch.setattr(objects, 'backend', usertypes.Backend.QtWebKit)
config_stub.val.zoom.text_only = zoom_text_only
geometry = QRect(10, 10, 4, 4)
frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100), zoom=0.5)
From dd927ded6ba3b03d9450c8e375b25651f67f90bf Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 08:25:43 +0200
Subject: [PATCH 93/99] Only update tab/window title on scroll if needed
This way, if {scroll_pos} is not in the window/tab title template,
we don't redraw anything unnecessarily.
See #2233
---
qutebrowser/mainwindow/tabbedbrowser.py | 19 ++++++++++++-----
qutebrowser/mainwindow/tabwidget.py | 28 ++++++++++++++++---------
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py
index 0571d7e34..a280df650 100644
--- a/qutebrowser/mainwindow/tabbedbrowser.py
+++ b/qutebrowser/mainwindow/tabbedbrowser.py
@@ -173,8 +173,18 @@ class TabbedBrowser(tabwidget.TabWidget):
widgets.append(widget)
return widgets
- def _update_window_title(self):
- """Change the window title to match the current tab."""
+ def _update_window_title(self, field=None):
+ """Change the window title to match the current tab.
+
+ Args:
+ idx: The tab index to update.
+ field: A field name which was updated. If given, the title
+ is only set if the given field is in the template.
+ """
+ title_format = config.val.window.title_format
+ if field is not None and ('{' + field + '}') not in title_format:
+ return
+
idx = self.currentIndex()
if idx == -1:
# (e.g. last tab removed)
@@ -183,7 +193,6 @@ class TabbedBrowser(tabwidget.TabWidget):
fields = self.get_tab_fields(idx)
fields['id'] = self._win_id
- title_format = config.val.window.title_format
title = title_format.format(**fields)
self.window().setWindowTitle(title)
@@ -696,8 +705,8 @@ class TabbedBrowser(tabwidget.TabWidget):
log.webview.debug("Not updating scroll position because index is "
"-1")
return
- self._update_window_title()
- self._update_tab_title(idx)
+ self._update_window_title('scroll_pos')
+ self._update_tab_title(idx, 'scroll_pos')
def _on_renderer_process_terminated(self, tab, status, code):
"""Show an error when a renderer process terminated."""
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py
index 56cb922f8..03c9929e0 100644
--- a/qutebrowser/mainwindow/tabwidget.py
+++ b/qutebrowser/mainwindow/tabwidget.py
@@ -121,21 +121,29 @@ class TabWidget(QTabWidget):
"""Get the tab title user data."""
return self.tabBar().page_title(idx)
- def _update_tab_title(self, idx):
- """Update the tab text for the given tab."""
+ def _update_tab_title(self, idx, field=None):
+ """Update the tab text for the given tab.
+
+ Args:
+ idx: The tab index to update.
+ field: A field name which was updated. If given, the title
+ is only set if the given field is in the template.
+ """
tab = self.widget(idx)
+ if tab.data.pinned:
+ fmt = config.val.tabs.title.format_pinned
+ else:
+ fmt = config.val.tabs.title.format
+
+ if (field is not None and
+ (fmt is None or ('{' + field + '}') not in fmt)):
+ return
+
fields = self.get_tab_fields(idx)
fields['title'] = fields['title'].replace('&', '&&')
fields['index'] = idx + 1
- fmt = config.val.tabs.title.format
- fmt_pinned = config.val.tabs.title.format_pinned
-
- if tab.data.pinned:
- title = '' if fmt_pinned is None else fmt_pinned.format(**fields)
- else:
- title = '' if fmt is None else fmt.format(**fields)
-
+ title = '' if fmt is None else fmt.format(**fields)
self.tabBar().setTabText(idx, title)
def get_tab_fields(self, idx):
From 8504d41db3fa30c392da9b0813e9c6791f546b2a Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 08:58:28 +0200
Subject: [PATCH 94/99] Use Qt API for QtWebEngine scrolling
See #2233
Fixes #2822
---
qutebrowser/browser/webengine/webenginetab.py | 50 ++++++++-----------
qutebrowser/javascript/scroll.js | 27 ----------
2 files changed, 20 insertions(+), 57 deletions(-)
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index 1e625d93c..2decf3599 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -24,7 +24,7 @@ import functools
import html as html_utils
import sip
-from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QUrl, QTimer
+from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QPointF, QUrl, QTimer
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtNetwork import QAuthenticator
from PyQt5.QtWidgets import QApplication
@@ -308,40 +308,30 @@ class WebEngineScroller(browsertab.AbstractScroller):
for _ in range(min(count, 5000)):
self._tab.key_press(key, modifier)
- @pyqtSlot()
- def _update_pos(self):
+ @pyqtSlot(QPointF)
+ def _update_pos(self, pos):
"""Update the scroll position attributes when it changed."""
- def update_pos_cb(jsret):
- """Callback after getting scroll position via JS."""
- if jsret is None:
- # This can happen when the callback would get called after
- # shutting down a tab
- return
- log.webview.vdebug(jsret)
- assert isinstance(jsret, dict), jsret
- self._pos_px = QPoint(jsret['px']['x'], jsret['px']['y'])
+ self._pos_px = pos.toPoint()
+ contents_size = self._widget.page().contentsSize()
- dx = jsret['scroll']['width'] - jsret['inner']['width']
- if dx == 0:
- perc_x = 0
- else:
- perc_x = min(100, round(100 / dx * jsret['px']['x']))
+ scrollable_x = contents_size.width() - self._widget.width()
+ if scrollable_x == 0:
+ perc_x = 0
+ else:
+ perc_x = min(100, round(100 / scrollable_x * pos.x()))
- dy = jsret['scroll']['height'] - jsret['inner']['height']
- if dy == 0:
- perc_y = 0
- else:
- perc_y = min(100, round(100 / dy * jsret['px']['y']))
+ scrollable_y = contents_size.height() - self._widget.height()
+ if scrollable_y == 0:
+ perc_y = 0
+ else:
+ perc_y = min(100, round(100 / scrollable_y * pos.y()))
- self._at_bottom = math.ceil(jsret['px']['y']) >= dy
+ self._at_bottom = math.ceil(pos.y()) >= scrollable_y
- if (self._pos_perc != (perc_x, perc_y) or
- 'no-scroll-filtering' in self._args.debug_flags):
- self._pos_perc = perc_x, perc_y
- self.perc_changed.emit(*self._pos_perc)
-
- js_code = javascript.assemble('scroll', 'pos')
- self._tab.run_js_async(js_code, update_pos_cb)
+ if (self._pos_perc != (perc_x, perc_y) or
+ 'no-scroll-filtering' in self._args.debug_flags):
+ self._pos_perc = perc_x, perc_y
+ self.perc_changed.emit(*self._pos_perc)
def pos_px(self):
return self._pos_px
diff --git a/qutebrowser/javascript/scroll.js b/qutebrowser/javascript/scroll.js
index 35f412783..188320f11 100644
--- a/qutebrowser/javascript/scroll.js
+++ b/qutebrowser/javascript/scroll.js
@@ -71,32 +71,5 @@ window._qutebrowser.scroll = (function() {
window.scrollBy(dx, dy);
};
- funcs.pos = function() {
- var pos = {
- "px": {"x": window.scrollX, "y": window.scrollY},
- "scroll": {
- "width": Math.max(
- document.body.scrollWidth,
- document.body.offsetWidth,
- document.documentElement.scrollWidth,
- document.documentElement.offsetWidth
- ),
- "height": Math.max(
- document.body.scrollHeight,
- document.body.offsetHeight,
- document.documentElement.scrollHeight,
- document.documentElement.offsetHeight
- ),
- },
- "inner": {
- "width": window.innerWidth,
- "height": window.innerHeight,
- },
- };
-
- // console.log(JSON.stringify(pos));
- return pos;
- };
-
return funcs;
})();
From c3e9343a6d73d1660f5d92989d84d1702477cc38 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 08:59:27 +0200
Subject: [PATCH 95/99] Update changelog for scrolling improvements
See #2233, #2822
---
doc/changelog.asciidoc | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 99b3ef11b..a7fe6cb96 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -37,6 +37,7 @@ Fixed
- More consistent sizing for favicons with vertical tabs.
- Using `:home` on pinned tabs is now prevented.
- Fix crash with unknown file types loaded via qute://help
+- Scrolling performance improvements
Deprecated
~~~~~~~~~~
From 5fe6e60ffdd045b5fb4cac184290516a2c76235b Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 09:12:23 +0200
Subject: [PATCH 96/99] Fix lint
---
qutebrowser/browser/webengine/webenginesettings.py | 4 ++--
qutebrowser/config/configfiles.py | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py
index b74356727..12503a7c0 100644
--- a/qutebrowser/browser/webengine/webenginesettings.py
+++ b/qutebrowser/browser/webengine/webenginesettings.py
@@ -36,8 +36,8 @@ from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import spell
from qutebrowser.config import config, websettings
-from qutebrowser.utils import (utils, standarddir, javascript, qtutils, message,
- log)
+from qutebrowser.utils import (utils, standarddir, javascript, qtutils,
+ message, log)
# The default QWebEngineProfile
default_profile = None
diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py
index 605c7372d..1c6ebff13 100644
--- a/qutebrowser/config/configfiles.py
+++ b/qutebrowser/config/configfiles.py
@@ -260,6 +260,7 @@ class ConfigAPI:
self._keyconfig.unbind(key, mode=mode)
def source(self, filename):
+ """Read the given config file from disk."""
if not os.path.isabs(filename):
filename = str(self.configdir / filename)
From 3dc06aad24b1be667d2841d552a54efeaef8bb3d Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 09:15:22 +0200
Subject: [PATCH 97/99] Update changelog
---
doc/changelog.asciidoc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index a7fe6cb96..435a8f979 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -30,6 +30,8 @@ Added
- New `:tab-give` and `:tab-take` commands, to give tabs to another window, or
take them from another window.
- New `config.source(...)` method for `config.py` to source another file.
+- New `keyhint.radius` option to configure the edge rounding for the key hint
+ widget.
Fixed
~~~~~
From 589e9b71533621d979fbbca89773d0c0afc67253 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 10:05:42 +0200
Subject: [PATCH 98/99] Fix string escaping in config.source test
---
tests/unit/config/test_configfiles.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py
index c0ba1f1ae..d1ddf9f2b 100644
--- a/tests/unit/config/test_configfiles.py
+++ b/tests/unit/config/test_configfiles.py
@@ -591,7 +591,7 @@ class TestConfigPy:
subfile.write_text("c.content.javascript.enabled = False",
encoding='utf-8')
- confpy.write("config.source('{}')".format(arg))
+ confpy.write("config.source({!r})".format(arg))
confpy.read()
assert not config.instance._values['content.javascript.enabled']
From 4c2aeb01a8562608589f2135c024eec7d3185be7 Mon Sep 17 00:00:00 2001
From: Florian Bruhin
Date: Fri, 20 Oct 2017 12:47:48 +0200
Subject: [PATCH 99/99] Update docs
---
doc/help/settings.asciidoc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index d9fddc2f3..eda28c955 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -209,6 +209,7 @@
|<>|Enable Spatial Navigation.
|<>|Keychains that shouldn't be shown in the keyhint dialog.
|<>|Time from pressing a key to seeing the keyhint dialog (ms).
+|<>|The rounding radius for the edges of the keyhint dialog.
|<>|Time (in ms) to show messages in the statusbar for.
|<>|Show messages in unfocused windows.
|<>|How to open links in an existing instance if a new one is launched.
@@ -2414,6 +2415,14 @@ Type: <>
Default: +pass:[500]+
+[[keyhint.radius]]
+=== keyhint.radius
+The rounding radius for the edges of the keyhint dialog.
+
+Type: <>
+
+Default: +pass:[6]+
+
[[messages.timeout]]
=== messages.timeout
Time (in ms) to show messages in the statusbar for.