Merge branch 'master' of https://github.com/qutebrowser/qutebrowser into stylesheet-fix
This commit is contained in:
commit
bc29ff60b3
13
.travis.yml
13
.travis.yml
@ -68,16 +68,3 @@ after_success:
|
|||||||
|
|
||||||
after_failure:
|
after_failure:
|
||||||
- bash scripts/dev/ci/travis_backtrace.sh
|
- bash scripts/dev/ci/travis_backtrace.sh
|
||||||
|
|
||||||
notifications:
|
|
||||||
webhooks:
|
|
||||||
- https://buildtimetrend.herokuapp.com/travis
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- "chat.freenode.net#qutebrowser-dev"
|
|
||||||
on_success: always
|
|
||||||
on_failure: always
|
|
||||||
skip_join: true
|
|
||||||
template:
|
|
||||||
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
|
|
||||||
- "%{compare_url} - %{build_url}"
|
|
||||||
|
@ -13,7 +13,7 @@ include qutebrowser/utils/testfile
|
|||||||
include qutebrowser/git-commit-id
|
include qutebrowser/git-commit-id
|
||||||
include LICENSE doc/* README.asciidoc
|
include LICENSE doc/* README.asciidoc
|
||||||
include misc/qutebrowser.desktop
|
include misc/qutebrowser.desktop
|
||||||
include misc/qutebrowser.appdata.xml
|
include misc/org.qutebrowser.qutebrowser.appdata.xml
|
||||||
include misc/Makefile
|
include misc/Makefile
|
||||||
include requirements.txt
|
include requirements.txt
|
||||||
include tox.ini
|
include tox.ini
|
||||||
|
@ -25,6 +25,7 @@ Added
|
|||||||
opened from a page should stack on each other or not.
|
opened from a page should stack on each other or not.
|
||||||
- New `completion.open_categories` setting which allows to configure which
|
- New `completion.open_categories` setting which allows to configure which
|
||||||
categories are shown in the `:open` completion, and how they are ordered.
|
categories are shown in the `:open` completion, and how they are ordered.
|
||||||
|
- New `tabs.pinned.frozen` setting to allow/deny navigating in pinned tabs.
|
||||||
- New config manipulation commands:
|
- New config manipulation commands:
|
||||||
* `:config-dict-add` and `:config-list-add` to a new element to a dict/list
|
* `:config-dict-add` and `:config-list-add` to a new element to a dict/list
|
||||||
setting.
|
setting.
|
||||||
@ -53,6 +54,11 @@ Changed
|
|||||||
- Various small performance improvements for hints and the completion.
|
- Various small performance improvements for hints and the completion.
|
||||||
- The Wayland check for QtWebEngine is now disabled on Qt >= 5.11.2, as those
|
- The Wayland check for QtWebEngine is now disabled on Qt >= 5.11.2, as those
|
||||||
versions should work without any issues.
|
versions should work without any issues.
|
||||||
|
- The JavaScript `console` object is now available in PAC files.
|
||||||
|
- The metainfo file `qutebrowser.appdata.xml` is now renamed to
|
||||||
|
`org.qutebrowser.qutebrowser.appdata.xml`.
|
||||||
|
- The `qute-pass` userscript now understands domains in gpg filenames
|
||||||
|
in addition to directory names.
|
||||||
|
|
||||||
Fixed
|
Fixed
|
||||||
~~~~~
|
~~~~~
|
||||||
@ -67,9 +73,13 @@ Fixed
|
|||||||
`content.cookies.accept = no-3rdparty` from working properly on some pages
|
`content.cookies.accept = no-3rdparty` from working properly on some pages
|
||||||
like GMail. However, the default for `content.cookies.accept` is still `all`
|
like GMail. However, the default for `content.cookies.accept` is still `all`
|
||||||
to be in line with what other browsers do.
|
to be in line with what other browsers do.
|
||||||
- `:navigate` not incrementing in anchors or queries or anchors.
|
- `:navigate` not incrementing in anchors or queries.
|
||||||
- Crash when trying to use a proxy requiring authentication with QtWebKit.
|
- Crash when trying to use a proxy requiring authentication with QtWebKit.
|
||||||
- Slashes in search terms are now percent-escaped.
|
- Slashes in search terms are now percent-escaped.
|
||||||
|
- When `scrolling.bar = True` was set in versions before v1.5.0, this now
|
||||||
|
correctly gets migrated to `always` instead of `when-searching`.
|
||||||
|
- Completion highlighting now works again on Qt 5.11.3 and 5.12.1.
|
||||||
|
- The outdated header `X-Do-Not-Track` is no longer sent.
|
||||||
|
|
||||||
v1.5.2
|
v1.5.2
|
||||||
------
|
------
|
||||||
|
@ -211,9 +211,10 @@ Why does J move to the next (right) tab, and K to the previous (left) one?::
|
|||||||
|
|
||||||
What's the difference between insert and passthrough mode?::
|
What's the difference between insert and passthrough mode?::
|
||||||
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
|
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
|
||||||
open an editor) while passthrough mode only has escape bound. It might also
|
open an editor) while passthrough mode only has shift+escape bound. This is
|
||||||
be useful to rebind escape to something else in passthrough mode only, to be
|
because shift+escape is unlikely to be a useful binding to be passed to a
|
||||||
able to send an escape keypress to the website.
|
webpage. However, any other keys may be assigned to leaving passthrough mode
|
||||||
|
instead of shift+escape should this be desired.
|
||||||
|
|
||||||
Why does it take longer to open a URL in qutebrowser than in chromium?::
|
Why does it take longer to open a URL in qutebrowser than in chromium?::
|
||||||
When opening a URL in an existing instance, the normal qutebrowser
|
When opening a URL in an existing instance, the normal qutebrowser
|
||||||
|
@ -396,6 +396,7 @@ Pre-built colorschemes
|
|||||||
- A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager].
|
- A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager].
|
||||||
- Two implementations of the https://github.com/arcticicestudio/nord[Nord] colorscheme for qutebrowser exist: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon]
|
- Two implementations of the https://github.com/arcticicestudio/nord[Nord] colorscheme for qutebrowser exist: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon]
|
||||||
- https://github.com/evannagle/qutebrowser-dracula-theme[Dracula]
|
- https://github.com/evannagle/qutebrowser-dracula-theme[Dracula]
|
||||||
|
- https://github.com/jjzmajic/qutewal[Pywal theme]
|
||||||
|
|
||||||
Avoiding flake8 errors
|
Avoiding flake8 errors
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -261,6 +261,7 @@
|
|||||||
|<<tabs.new_position.stacking,tabs.new_position.stacking>>|Stack related tabs on top of each other when opened consecutively.
|
|<<tabs.new_position.stacking,tabs.new_position.stacking>>|Stack related tabs on top of each other when opened consecutively.
|
||||||
|<<tabs.new_position.unrelated,tabs.new_position.unrelated>>|Position of new tabs which are not opened from another tab.
|
|<<tabs.new_position.unrelated,tabs.new_position.unrelated>>|Position of new tabs which are not opened from another tab.
|
||||||
|<<tabs.padding,tabs.padding>>|Padding (in pixels) around text for tabs.
|
|<<tabs.padding,tabs.padding>>|Padding (in pixels) around text for tabs.
|
||||||
|
|<<tabs.pinned.frozen,tabs.pinned.frozen>>|Force pinned tabs to stay at fixed URL.
|
||||||
|<<tabs.pinned.shrink,tabs.pinned.shrink>>|Shrink pinned tabs down to their contents.
|
|<<tabs.pinned.shrink,tabs.pinned.shrink>>|Shrink pinned tabs down to their contents.
|
||||||
|<<tabs.position,tabs.position>>|Position of the tab bar.
|
|<<tabs.position,tabs.position>>|Position of the tab bar.
|
||||||
|<<tabs.select_on_remove,tabs.select_on_remove>>|Which tab to select when the focused tab is removed.
|
|<<tabs.select_on_remove,tabs.select_on_remove>>|Which tab to select when the focused tab is removed.
|
||||||
@ -3307,6 +3308,14 @@ Default:
|
|||||||
- +pass:[right]+: +pass:[5]+
|
- +pass:[right]+: +pass:[5]+
|
||||||
- +pass:[top]+: +pass:[0]+
|
- +pass:[top]+: +pass:[0]+
|
||||||
|
|
||||||
|
[[tabs.pinned.frozen]]
|
||||||
|
=== tabs.pinned.frozen
|
||||||
|
Force pinned tabs to stay at fixed URL.
|
||||||
|
|
||||||
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[tabs.pinned.shrink]]
|
[[tabs.pinned.shrink]]
|
||||||
=== tabs.pinned.shrink
|
=== tabs.pinned.shrink
|
||||||
Shrink pinned tabs down to their contents.
|
Shrink pinned tabs down to their contents.
|
||||||
|
@ -102,18 +102,12 @@ $ python3 scripts/asciidoc2html.py
|
|||||||
On Fedora
|
On Fedora
|
||||||
---------
|
---------
|
||||||
|
|
||||||
NOTE: Fedora's packages used to be outdated for a long time, but are
|
|
||||||
now (November 2017) maintained and up-to-date again.
|
|
||||||
|
|
||||||
qutebrowser is available in the official repositories:
|
qutebrowser is available in the official repositories:
|
||||||
|
|
||||||
-----
|
-----
|
||||||
# dnf install qutebrowser
|
# dnf install qutebrowser
|
||||||
-----
|
-----
|
||||||
|
|
||||||
However, note that Fedora 25/26 won't be updated to qutebrowser v1.0, so you
|
|
||||||
might want to <<tox,install qutebrowser via tox>> instead there.
|
|
||||||
|
|
||||||
Additional hints
|
Additional hints
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ doc/qutebrowser.1.html:
|
|||||||
|
|
||||||
install: doc/qutebrowser.1.html
|
install: doc/qutebrowser.1.html
|
||||||
$(PYTHON) setup.py install --prefix="$(PREFIX)" --optimize=1 $(SETUPTOOLSOPTS)
|
$(PYTHON) setup.py install --prefix="$(PREFIX)" --optimize=1 $(SETUPTOOLSOPTS)
|
||||||
install -Dm644 misc/qutebrowser.appdata.xml \
|
install -Dm644 misc/org.qutebrowser.qutebrowser.appdata.xml \
|
||||||
"$(DESTDIR)$(DATADIR)/metainfo/qutebrowser.appdata.xml"
|
"$(DESTDIR)$(DATADIR)/metainfo/org.qutebrowser.qutebrowser.appdata.xml"
|
||||||
install -Dm644 doc/qutebrowser.1 \
|
install -Dm644 doc/qutebrowser.1 \
|
||||||
"$(DESTDIR)$(MANDIR)/man1/qutebrowser.1"
|
"$(DESTDIR)$(MANDIR)/man1/qutebrowser.1"
|
||||||
install -Dm644 misc/qutebrowser.desktop \
|
install -Dm644 misc/qutebrowser.desktop \
|
||||||
|
@ -11,7 +11,7 @@ flake8-deprecated==1.3
|
|||||||
flake8-docstrings==1.3.0
|
flake8-docstrings==1.3.0
|
||||||
flake8-future-import==0.4.5
|
flake8-future-import==0.4.5
|
||||||
flake8-mock==0.3
|
flake8-mock==0.3
|
||||||
flake8-per-file-ignores==0.6
|
flake8-per-file-ignores==0.7
|
||||||
flake8-polyfill==1.0.2
|
flake8-polyfill==1.0.2
|
||||||
flake8-string-format==0.2.3
|
flake8-string-format==0.2.3
|
||||||
flake8-tidy-imports==1.1.0
|
flake8-tidy-imports==1.1.0
|
||||||
|
@ -16,6 +16,6 @@ pytz==2018.7
|
|||||||
requests==2.21.0
|
requests==2.21.0
|
||||||
six==1.12.0
|
six==1.12.0
|
||||||
snowballstemmer==1.2.1
|
snowballstemmer==1.2.1
|
||||||
Sphinx==1.8.2
|
Sphinx==1.8.3
|
||||||
sphinxcontrib-websupport==1.1.0
|
sphinxcontrib-websupport==1.1.0
|
||||||
urllib3==1.24.1
|
urllib3==1.24.1
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
atomicwrites==1.2.1
|
atomicwrites==1.2.1
|
||||||
attrs==18.2.0
|
attrs==18.2.0
|
||||||
backports.functools-lru-cache==1.5
|
backports.functools-lru-cache==1.5
|
||||||
beautifulsoup4==4.6.3
|
beautifulsoup4==4.7.0
|
||||||
cheroot==6.5.2
|
cheroot==6.5.3
|
||||||
Click==7.0
|
Click==7.0
|
||||||
# colorama==0.4.1
|
# colorama==0.4.1
|
||||||
coverage==4.5.2
|
coverage==4.5.2
|
||||||
@ -12,12 +12,12 @@ EasyProcess==0.2.5
|
|||||||
Flask==1.0.2
|
Flask==1.0.2
|
||||||
glob2==0.6
|
glob2==0.6
|
||||||
hunter==2.1.0
|
hunter==2.1.0
|
||||||
hypothesis==3.84.5
|
hypothesis==3.85.2
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
# Jinja2==2.10
|
# Jinja2==2.10
|
||||||
Mako==1.0.7
|
Mako==1.0.7
|
||||||
# MarkupSafe==1.1.0
|
# MarkupSafe==1.1.0
|
||||||
more-itertools==4.3.0
|
more-itertools==5.0.0
|
||||||
parse==1.9.0
|
parse==1.9.0
|
||||||
parse-type==0.4.2
|
parse-type==0.4.2
|
||||||
pluggy==0.8.0
|
pluggy==0.8.0
|
||||||
|
@ -64,6 +64,7 @@ die() {
|
|||||||
javascript_escape() {
|
javascript_escape() {
|
||||||
# print the first argument in an escaped way, such that it can safely
|
# print the first argument in an escaped way, such that it can safely
|
||||||
# be used within javascripts double quotes
|
# be used within javascripts double quotes
|
||||||
|
# shellcheck disable=SC2001
|
||||||
sed "s,[\\\\'\"],\\\\&,g" <<< "$1"
|
sed "s,[\\\\'\"],\\\\&,g" <<< "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +112,7 @@ simplify_url() {
|
|||||||
# are found:
|
# are found:
|
||||||
no_entries_found() {
|
no_entries_found() {
|
||||||
while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do
|
while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do
|
||||||
|
# shellcheck disable=SC2001
|
||||||
shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url")
|
shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url")
|
||||||
if [ "$shorter_simple_url" = "$simple_url" ] ; then
|
if [ "$shorter_simple_url" = "$simple_url" ] ; then
|
||||||
# if no dot, then even remove the top level domain
|
# if no dot, then even remove the top level domain
|
||||||
|
@ -97,13 +97,19 @@ def qute_command(command):
|
|||||||
def find_pass_candidates(domain, password_store_path):
|
def find_pass_candidates(domain, password_store_path):
|
||||||
candidates = []
|
candidates = []
|
||||||
for path, directories, file_names in os.walk(password_store_path, followlinks=True):
|
for path, directories, file_names in os.walk(password_store_path, followlinks=True):
|
||||||
if directories or domain not in path.split(os.path.sep):
|
secrets = fnmatch.filter(file_names, '*.gpg')
|
||||||
|
if not secrets:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Strip password store path prefix to get the relative pass path
|
# Strip password store path prefix to get the relative pass path
|
||||||
pass_path = path[len(password_store_path) + 1:]
|
pass_path = path[len(password_store_path) + 1:]
|
||||||
secrets = fnmatch.filter(file_names, '*.gpg')
|
split_path = pass_path.split(os.path.sep)
|
||||||
candidates.extend(os.path.join(pass_path, os.path.splitext(secret)[0]) for secret in secrets)
|
for secret in secrets:
|
||||||
|
secret_base = os.path.splitext(secret)[0]
|
||||||
|
if domain not in (split_path + [secret_base]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
candidates.append(os.path.join(pass_path, secret_base))
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ get_selection() {
|
|||||||
# https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font
|
# https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font
|
||||||
[[ -s $confdir/dmenu/font ]] && read -r font < "$confdir"/dmenu/font
|
[[ -s $confdir/dmenu/font ]] && read -r font < "$confdir"/dmenu/font
|
||||||
|
|
||||||
[[ $font ]] && opts+=(-fn "$font")
|
[[ -n $font ]] && opts+=(-fn "$font")
|
||||||
|
|
||||||
# shellcheck source=/dev/null
|
# shellcheck source=/dev/null
|
||||||
[[ -s $optsfile ]] && source "$optsfile"
|
[[ -s $optsfile ]] && source "$optsfile"
|
||||||
@ -46,7 +46,7 @@ url=$(get_selection)
|
|||||||
url=${url/*http/http}
|
url=${url/*http/http}
|
||||||
|
|
||||||
# If no selection is made, exit (escape pressed, e.g.)
|
# If no selection is made, exit (escape pressed, e.g.)
|
||||||
[[ ! $url ]] && exit 0
|
[[ -z $url ]] && exit 0
|
||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;;
|
open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;;
|
||||||
|
@ -64,6 +64,7 @@ qt_log_ignore =
|
|||||||
^QSettings::value: Empty key passed
|
^QSettings::value: Empty key passed
|
||||||
^Icon theme ".*" not found
|
^Icon theme ".*" not found
|
||||||
^Error receiving trust for a CA certificate
|
^Error receiving trust for a CA certificate
|
||||||
|
^QBackingStore::endPaint\(\) called with active painter on backingstore paint device
|
||||||
xfail_strict = true
|
xfail_strict = true
|
||||||
filterwarnings =
|
filterwarnings =
|
||||||
error
|
error
|
||||||
|
@ -943,6 +943,10 @@ class AbstractTab(QWidget):
|
|||||||
evt.posted = True
|
evt.posted = True
|
||||||
QApplication.postEvent(recipient, evt)
|
QApplication.postEvent(recipient, evt)
|
||||||
|
|
||||||
|
def navigation_blocked(self) -> bool:
|
||||||
|
"""Test if navigation is allowed on the current tab."""
|
||||||
|
return self.data.pinned and config.val.tabs.pinned.frozen
|
||||||
|
|
||||||
@pyqtSlot(QUrl)
|
@pyqtSlot(QUrl)
|
||||||
def _on_before_load_started(self, url: QUrl) -> None:
|
def _on_before_load_started(self, url: QUrl) -> None:
|
||||||
"""Adjust the title if we are going to visit a URL soon."""
|
"""Adjust the title if we are going to visit a URL soon."""
|
||||||
|
@ -316,7 +316,7 @@ class CommandDispatcher:
|
|||||||
else:
|
else:
|
||||||
# Explicit count with a tab that doesn't exist.
|
# Explicit count with a tab that doesn't exist.
|
||||||
return
|
return
|
||||||
elif curtab.data.pinned:
|
elif curtab.navigation_blocked():
|
||||||
message.info("Tab is pinned!")
|
message.info("Tab is pinned!")
|
||||||
else:
|
else:
|
||||||
curtab.load_url(cur_url)
|
curtab.load_url(cur_url)
|
||||||
|
@ -180,6 +180,8 @@ class PACResolver:
|
|||||||
"""
|
"""
|
||||||
self._engine = QJSEngine()
|
self._engine = QJSEngine()
|
||||||
|
|
||||||
|
self._engine.installExtensions(QJSEngine.ConsoleExtension)
|
||||||
|
|
||||||
self._ctx = _PACContext(self._engine)
|
self._ctx = _PACContext(self._engine)
|
||||||
self._engine.globalObject().setProperty(
|
self._engine.globalObject().setProperty(
|
||||||
"PAC", self._engine.newQObject(self._ctx))
|
"PAC", self._engine.newQObject(self._ctx))
|
||||||
|
@ -42,7 +42,6 @@ def custom_headers(url):
|
|||||||
if dnt_config is not None:
|
if dnt_config is not None:
|
||||||
dnt = b'1' if dnt_config else b'0'
|
dnt = b'1' if dnt_config else b'0'
|
||||||
headers[b'DNT'] = dnt
|
headers[b'DNT'] = dnt
|
||||||
headers[b'X-Do-Not-Track'] = dnt
|
|
||||||
|
|
||||||
conf_headers = config.instance.get('content.headers.custom', url=url)
|
conf_headers = config.instance.get('content.headers.custom', url=url)
|
||||||
for header, value in conf_headers.items():
|
for header, value in conf_headers.items():
|
||||||
|
@ -22,6 +22,11 @@
|
|||||||
from PyQt5.QtCore import QBuffer, QIODevice, QUrl
|
from PyQt5.QtCore import QBuffer, QIODevice, QUrl
|
||||||
from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler,
|
from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler,
|
||||||
QWebEngineUrlRequestJob)
|
QWebEngineUrlRequestJob)
|
||||||
|
try:
|
||||||
|
from PyQt5.QtWebEngineCore import QWebEngineUrlScheme # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
# Added in Qt 5.12
|
||||||
|
QWebEngineUrlScheme = None
|
||||||
|
|
||||||
from qutebrowser.browser import qutescheme
|
from qutebrowser.browser import qutescheme
|
||||||
from qutebrowser.utils import log, qtutils
|
from qutebrowser.utils import log, qtutils
|
||||||
@ -33,8 +38,12 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
|
|||||||
|
|
||||||
def install(self, profile):
|
def install(self, profile):
|
||||||
"""Install the handler for qute:// URLs on the given profile."""
|
"""Install the handler for qute:// URLs on the given profile."""
|
||||||
|
if QWebEngineUrlScheme is not None:
|
||||||
|
assert QWebEngineUrlScheme.schemeByName(b'qute') is not None
|
||||||
|
|
||||||
profile.installUrlSchemeHandler(b'qute', self)
|
profile.installUrlSchemeHandler(b'qute', self)
|
||||||
if qtutils.version_check('5.11', compiled=False):
|
if (qtutils.version_check('5.11', compiled=False) and
|
||||||
|
not qtutils.version_check('5.12', compiled=False)):
|
||||||
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378
|
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378
|
||||||
profile.installUrlSchemeHandler(b'chrome-error', self)
|
profile.installUrlSchemeHandler(b'chrome-error', self)
|
||||||
profile.installUrlSchemeHandler(b'chrome-extension', self)
|
profile.installUrlSchemeHandler(b'chrome-extension', self)
|
||||||
@ -130,3 +139,16 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
|
|||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
buf.close()
|
buf.close()
|
||||||
job.reply(mimetype.encode('ascii'), buf)
|
job.reply(mimetype.encode('ascii'), buf)
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Register the qute:// scheme.
|
||||||
|
|
||||||
|
Note this needs to be called early, before constructing any QtWebEngine
|
||||||
|
classes.
|
||||||
|
"""
|
||||||
|
if QWebEngineUrlScheme is not None:
|
||||||
|
scheme = QWebEngineUrlScheme(b'qute')
|
||||||
|
scheme.setFlags(QWebEngineUrlScheme.LocalScheme |
|
||||||
|
QWebEngineUrlScheme.LocalAccessAllowed)
|
||||||
|
QWebEngineUrlScheme.registerScheme(scheme)
|
||||||
|
@ -30,7 +30,7 @@ from PyQt5.QtGui import QFont
|
|||||||
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
|
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
|
||||||
QWebEnginePage)
|
QWebEnginePage)
|
||||||
|
|
||||||
from qutebrowser.browser.webengine import spell
|
from qutebrowser.browser.webengine import spell, webenginequtescheme
|
||||||
from qutebrowser.config import config, websettings
|
from qutebrowser.config import config, websettings
|
||||||
from qutebrowser.config.websettings import AttributeInfo as Attr
|
from qutebrowser.config.websettings import AttributeInfo as Attr
|
||||||
from qutebrowser.utils import utils, standarddir, qtutils, message, log
|
from qutebrowser.utils import utils, standarddir, qtutils, message, log
|
||||||
@ -298,6 +298,7 @@ def init(args):
|
|||||||
not hasattr(QWebEnginePage, 'setInspectedPage')): # only Qt < 5.11
|
not hasattr(QWebEnginePage, 'setInspectedPage')): # only Qt < 5.11
|
||||||
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
|
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
|
||||||
|
|
||||||
|
webenginequtescheme.init()
|
||||||
spell.init()
|
spell.init()
|
||||||
|
|
||||||
_init_profiles()
|
_init_profiles()
|
||||||
|
@ -212,11 +212,11 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
view = self.parent()
|
view = self.parent()
|
||||||
pattern = view.pattern
|
pattern = view.pattern
|
||||||
columns_to_filter = index.model().columns_to_filter(index)
|
columns_to_filter = index.model().columns_to_filter(index)
|
||||||
self._doc.setPlainText(self._opt.text)
|
|
||||||
if index.column() in columns_to_filter and pattern:
|
if index.column() in columns_to_filter and pattern:
|
||||||
pat = re.escape(pattern).replace(r'\ ', r'|')
|
pat = re.escape(pattern).replace(r'\ ', r'|')
|
||||||
_Highlighter(self._doc, pat,
|
_Highlighter(self._doc, pat,
|
||||||
config.val.colors.completion.match.fg)
|
config.val.colors.completion.match.fg)
|
||||||
|
self._doc.setPlainText(self._opt.text)
|
||||||
else:
|
else:
|
||||||
self._doc.setHtml(
|
self._doc.setHtml(
|
||||||
'<span style="font: {};">{}</span>'.format(
|
'<span style="font: {};">{}</span>'.format(
|
||||||
|
@ -118,7 +118,7 @@ def printpage(tab: apitypes.Tab,
|
|||||||
@cmdutils.argument('tab', value=cmdutils.Value.cur_tab)
|
@cmdutils.argument('tab', value=cmdutils.Value.cur_tab)
|
||||||
def home(tab: apitypes.Tab) -> None:
|
def home(tab: apitypes.Tab) -> None:
|
||||||
"""Open main startpage in current tab."""
|
"""Open main startpage in current tab."""
|
||||||
if tab.data.pinned:
|
if tab.navigation_blocked():
|
||||||
message.info("Tab is pinned!")
|
message.info("Tab is pinned!")
|
||||||
else:
|
else:
|
||||||
tab.load_url(config.val.url.start_pages[0])
|
tab.load_url(config.val.url.start_pages[0])
|
||||||
|
@ -46,7 +46,9 @@ class ConfigCache:
|
|||||||
self._cache[attr] = config.instance.get(attr)
|
self._cache[attr] = config.instance.get(attr)
|
||||||
|
|
||||||
def __getitem__(self, attr: str) -> typing.Any:
|
def __getitem__(self, attr: str) -> typing.Any:
|
||||||
if attr not in self._cache:
|
try:
|
||||||
|
return self._cache[attr]
|
||||||
|
except KeyError:
|
||||||
assert not config.instance.get_opt(attr).supports_pattern
|
assert not config.instance.get_opt(attr).supports_pattern
|
||||||
self._cache[attr] = config.instance.get(attr)
|
self._cache[attr] = config.instance.get(attr)
|
||||||
return self._cache[attr]
|
return self._cache[attr]
|
||||||
|
@ -1768,6 +1768,11 @@ tabs.pinned.shrink:
|
|||||||
type: Bool
|
type: Bool
|
||||||
desc: Shrink pinned tabs down to their contents.
|
desc: Shrink pinned tabs down to their contents.
|
||||||
|
|
||||||
|
tabs.pinned.frozen:
|
||||||
|
type: Bool
|
||||||
|
default: True
|
||||||
|
desc: Force pinned tabs to stay at fixed URL.
|
||||||
|
|
||||||
tabs.wrap:
|
tabs.wrap:
|
||||||
default: true
|
default: true
|
||||||
type: Bool
|
type: Bool
|
||||||
|
@ -308,7 +308,7 @@ class YamlConfig(QObject):
|
|||||||
|
|
||||||
self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never')
|
self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never')
|
||||||
self._migrate_bool(settings, 'scrolling.bar',
|
self._migrate_bool(settings, 'scrolling.bar',
|
||||||
'when-searching', 'never')
|
'always', 'when-searching')
|
||||||
self._migrate_bool(settings, 'qt.force_software_rendering',
|
self._migrate_bool(settings, 'qt.force_software_rendering',
|
||||||
'software-opengl', 'none')
|
'software-opengl', 'none')
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ EOF
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ $DOCKER ]]; then
|
if [[ -n $DOCKER ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
elif [[ $TRAVIS_OS_NAME == osx ]]; then
|
elif [[ $TRAVIS_OS_NAME == osx ]]; then
|
||||||
# Disable App Nap
|
# Disable App Nap
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [[ $DOCKER ]]; then
|
if [[ -n $DOCKER ]]; then
|
||||||
docker run \
|
docker run \
|
||||||
--privileged \
|
--privileged \
|
||||||
-v "$PWD:/outside" \
|
-v "$PWD:/outside" \
|
||||||
|
@ -93,7 +93,7 @@ Feature: Downloading things from a website.
|
|||||||
Then no crash should happen
|
Then no crash should happen
|
||||||
|
|
||||||
# https://github.com/qutebrowser/qutebrowser/issues/4240
|
# https://github.com/qutebrowser/qutebrowser/issues/4240
|
||||||
@qt!=5.11.2
|
@qt<5.11.2
|
||||||
Scenario: Downloading with SSL errors (issue 1413)
|
Scenario: Downloading with SSL errors (issue 1413)
|
||||||
When SSL is supported
|
When SSL is supported
|
||||||
And I clear SSL errors
|
And I clear SSL errors
|
||||||
|
@ -331,19 +331,16 @@ Feature: Various utility commands.
|
|||||||
When I set content.headers.do_not_track to true
|
When I set content.headers.do_not_track to true
|
||||||
And I open headers
|
And I open headers
|
||||||
Then the header Dnt should be set to 1
|
Then the header Dnt should be set to 1
|
||||||
And the header X-Do-Not-Track should be set to 1
|
|
||||||
|
|
||||||
Scenario: DNT header (off)
|
Scenario: DNT header (off)
|
||||||
When I set content.headers.do_not_track to false
|
When I set content.headers.do_not_track to false
|
||||||
And I open headers
|
And I open headers
|
||||||
Then the header Dnt should be set to 0
|
Then the header Dnt should be set to 0
|
||||||
And the header X-Do-Not-Track should be set to 0
|
|
||||||
|
|
||||||
Scenario: DNT header (unset)
|
Scenario: DNT header (unset)
|
||||||
When I set content.headers.do_not_track to <empty>
|
When I set content.headers.do_not_track to <empty>
|
||||||
And I open headers
|
And I open headers
|
||||||
Then the header Dnt should be set to <unset>
|
Then the header Dnt should be set to <unset>
|
||||||
And the header X-Do-Not-Track should be set to <unset>
|
|
||||||
|
|
||||||
Scenario: Accept-Language header
|
Scenario: Accept-Language header
|
||||||
When I set content.headers.accept_language to en,de
|
When I set content.headers.accept_language to en,de
|
||||||
|
@ -1289,6 +1289,14 @@ Feature: Tab management
|
|||||||
And the following tabs should be open:
|
And the following tabs should be open:
|
||||||
- data/numbers/1.txt (active) (pinned)
|
- data/numbers/1.txt (active) (pinned)
|
||||||
|
|
||||||
|
Scenario: :tab-pin open url with tabs.pinned.frozen = false
|
||||||
|
When I set tabs.pinned.frozen to false
|
||||||
|
And I open data/numbers/1.txt
|
||||||
|
And I run :tab-pin
|
||||||
|
And I open data/numbers/2.txt
|
||||||
|
Then the following tabs should be open:
|
||||||
|
- data/numbers/2.txt (active) (pinned)
|
||||||
|
|
||||||
Scenario: :home on a pinned tab
|
Scenario: :home on a pinned tab
|
||||||
When I open data/numbers/1.txt
|
When I open data/numbers/1.txt
|
||||||
And I run :tab-pin
|
And I run :tab-pin
|
||||||
@ -1297,6 +1305,16 @@ Feature: Tab management
|
|||||||
And the following tabs should be open:
|
And the following tabs should be open:
|
||||||
- data/numbers/1.txt (active) (pinned)
|
- data/numbers/1.txt (active) (pinned)
|
||||||
|
|
||||||
|
Scenario: :home on a pinned tab with tabs.pinned.frozen = false
|
||||||
|
When I set url.start_pages to ["http://localhost:(port)/data/numbers/2.txt"]
|
||||||
|
And I set tabs.pinned.frozen to false
|
||||||
|
And I open data/numbers/1.txt
|
||||||
|
And I run :tab-pin
|
||||||
|
And I run :home
|
||||||
|
Then data/numbers/2.txt should be loaded
|
||||||
|
And the following tabs should be open:
|
||||||
|
- data/numbers/2.txt (active) (pinned)
|
||||||
|
|
||||||
Scenario: Cloning a pinned tab
|
Scenario: Cloning a pinned tab
|
||||||
When I open data/numbers/1.txt
|
When I open data/numbers/1.txt
|
||||||
And I run :tab-pin
|
And I run :tab-pin
|
||||||
|
@ -26,18 +26,15 @@ from qutebrowser.browser import shared
|
|||||||
|
|
||||||
@pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [
|
@pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [
|
||||||
# DNT
|
# DNT
|
||||||
(True, None, {}, {b'DNT': b'1', b'X-Do-Not-Track': b'1'}),
|
(True, None, {}, {b'DNT': b'1'}),
|
||||||
(False, None, {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0'}),
|
(False, None, {}, {b'DNT': b'0'}),
|
||||||
(None, None, {}, {}),
|
(None, None, {}, {}),
|
||||||
# Accept-Language
|
# Accept-Language
|
||||||
(False, 'de, en', {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0',
|
(False, 'de, en', {}, {b'DNT': b'0', b'Accept-Language': b'de, en'}),
|
||||||
b'Accept-Language': b'de, en'}),
|
|
||||||
# Custom headers
|
# Custom headers
|
||||||
(False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Do-Not-Track': b'0',
|
(False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Qute': b'yes'}),
|
||||||
b'X-Qute': b'yes'}),
|
|
||||||
# Mixed
|
# Mixed
|
||||||
(False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0',
|
(False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0',
|
||||||
b'X-Do-Not-Track': b'0',
|
|
||||||
b'Accept-Language': b'de, en',
|
b'Accept-Language': b'de, en',
|
||||||
b'X-Qute': b'yes'}),
|
b'X-Qute': b'yes'}),
|
||||||
])
|
])
|
||||||
|
@ -205,6 +205,20 @@ def test_secret_url(url, has_secret, from_file):
|
|||||||
res.resolve(QNetworkProxyQuery(QUrl(url)), from_file=from_file)
|
res.resolve(QNetworkProxyQuery(QUrl(url)), from_file=from_file)
|
||||||
|
|
||||||
|
|
||||||
|
def test_logging(qtlog):
|
||||||
|
"""Make sure console.log() works for PAC files."""
|
||||||
|
test_str = """
|
||||||
|
function FindProxyForURL(domain, host) {
|
||||||
|
console.log("logging test");
|
||||||
|
return "DIRECT";
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
res = pac.PACResolver(test_str)
|
||||||
|
res.resolve(QNetworkProxyQuery(QUrl("https://example.com/test")))
|
||||||
|
assert len(qtlog.records) == 1
|
||||||
|
assert qtlog.records[0].message == 'logging test'
|
||||||
|
|
||||||
|
|
||||||
def fetcher_test(test_str):
|
def fetcher_test(test_str):
|
||||||
class PACHandler(http.server.BaseHTTPRequestHandler):
|
class PACHandler(http.server.BaseHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
@ -20,7 +20,8 @@ from unittest import mock
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QTextDocument
|
from PyQt5.QtGui import QTextDocument, QColor
|
||||||
|
from PyQt5.QtWidgets import QTextEdit
|
||||||
|
|
||||||
from qutebrowser.completion import completiondelegate
|
from qutebrowser.completion import completiondelegate
|
||||||
|
|
||||||
@ -50,3 +51,24 @@ def test_highlight(pat, txt, segments):
|
|||||||
highlighter.setFormat.assert_has_calls([
|
highlighter.setFormat.assert_has_calls([
|
||||||
mock.call(s[0], s[1], mock.ANY) for s in segments
|
mock.call(s[0], s[1], mock.ANY) for s in segments
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_highlighted(qtbot):
|
||||||
|
"""Make sure highlighting works.
|
||||||
|
|
||||||
|
Note that with Qt 5.11.3 and > 5.12.1 we need to call setPlainText *after*
|
||||||
|
creating the highlighter for highlighting to work. Ideally, we'd test
|
||||||
|
whether CompletionItemDelegate._get_textdoc() works properly, but testing
|
||||||
|
that is kind of hard, so we just test it in isolation here.
|
||||||
|
"""
|
||||||
|
doc = QTextDocument()
|
||||||
|
completiondelegate._Highlighter(doc, 'Hello', Qt.red)
|
||||||
|
doc.setPlainText('Hello World')
|
||||||
|
|
||||||
|
# Needed so the highlighting actually works.
|
||||||
|
edit = QTextEdit()
|
||||||
|
qtbot.addWidget(edit)
|
||||||
|
edit.setDocument(doc)
|
||||||
|
|
||||||
|
colors = [f.foreground().color() for f in doc.allFormats()]
|
||||||
|
assert QColor('red') in colors
|
||||||
|
@ -50,3 +50,17 @@ def test_configcache_get_after_set(config_stub):
|
|||||||
assert not config.cache['auto_save.session']
|
assert not config.cache['auto_save.session']
|
||||||
config_stub.val.auto_save.session = True
|
config_stub.val.auto_save.session = True
|
||||||
assert config.cache['auto_save.session']
|
assert config.cache['auto_save.session']
|
||||||
|
|
||||||
|
|
||||||
|
def test_configcache_naive_benchmark(config_stub, benchmark):
|
||||||
|
def _run_bench():
|
||||||
|
for _i in range(10000):
|
||||||
|
# pylint: disable=pointless-statement
|
||||||
|
config.cache['tabs.padding']
|
||||||
|
config.cache['tabs.indicator.width']
|
||||||
|
config.cache['tabs.indicator.padding']
|
||||||
|
config.cache['tabs.min_width']
|
||||||
|
config.cache['tabs.max_width']
|
||||||
|
config.cache['tabs.pinned.shrink']
|
||||||
|
# pylint: enable=pointless-statement
|
||||||
|
benchmark(_run_bench)
|
||||||
|
@ -250,36 +250,28 @@ class TestYaml:
|
|||||||
data = autoconfig.read()
|
data = autoconfig.read()
|
||||||
assert data['content.webrtc_ip_handling_policy']['global'] == expected
|
assert data['content.webrtc_ip_handling_policy']['global'] == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('show, expected', [
|
@pytest.mark.parametrize('setting, old, new', [
|
||||||
(True, 'always'),
|
('tabs.favicons.show', True, 'always'),
|
||||||
(False, 'never'),
|
('tabs.favicons.show', False, 'never'),
|
||||||
('always', 'always'),
|
('tabs.favicons.show', 'always', 'always'),
|
||||||
('never', 'never'),
|
|
||||||
('pinned', 'pinned'),
|
('scrolling.bar', True, 'always'),
|
||||||
|
('scrolling.bar', False, 'when-searching'),
|
||||||
|
('scrolling.bar', 'always', 'always'),
|
||||||
|
|
||||||
|
('qt.force_software_rendering', True, 'software-opengl'),
|
||||||
|
('qt.force_software_rendering', False, 'none'),
|
||||||
|
('qt.force_software_rendering', 'chromium', 'chromium'),
|
||||||
])
|
])
|
||||||
def test_tabs_favicons_show(self, yaml, autoconfig, show, expected):
|
def test_bool_migrations(self, yaml, autoconfig, setting, old, new):
|
||||||
"""Tests for migration of tabs.favicons.show."""
|
"""Tests for migration of former boolean settings."""
|
||||||
autoconfig.write({'tabs.favicons.show': {'global': show}})
|
autoconfig.write({setting: {'global': old}})
|
||||||
|
|
||||||
yaml.load()
|
yaml.load()
|
||||||
yaml._save()
|
yaml._save()
|
||||||
|
|
||||||
data = autoconfig.read()
|
data = autoconfig.read()
|
||||||
assert data['tabs.favicons.show']['global'] == expected
|
assert data[setting]['global'] == new
|
||||||
|
|
||||||
@pytest.mark.parametrize('force, expected', [
|
|
||||||
(True, 'software-opengl'),
|
|
||||||
(False, 'none'),
|
|
||||||
('chromium', 'chromium'),
|
|
||||||
])
|
|
||||||
def test_force_software_rendering(self, yaml, autoconfig, force, expected):
|
|
||||||
autoconfig.write({'qt.force_software_rendering': {'global': force}})
|
|
||||||
|
|
||||||
yaml.load()
|
|
||||||
yaml._save()
|
|
||||||
|
|
||||||
data = autoconfig.read()
|
|
||||||
assert data['qt.force_software_rendering']['global'] == expected
|
|
||||||
|
|
||||||
def test_renamed_key_unknown_target(self, monkeypatch, yaml,
|
def test_renamed_key_unknown_target(self, monkeypatch, yaml,
|
||||||
autoconfig):
|
autoconfig):
|
||||||
|
Loading…
Reference in New Issue
Block a user