Merge remote-tracking branch 'upstream/master' into jay/max-tab
This commit is contained in:
commit
14e55eae49
@ -54,7 +54,7 @@ no-docstring-rgx=(^_|^main$)
|
|||||||
|
|
||||||
[FORMAT]
|
[FORMAT]
|
||||||
max-line-length=79
|
max-line-length=79
|
||||||
ignore-long-lines=(<?https?://|^# Copyright 201\d)
|
ignore-long-lines=(<?https?://|^# Copyright 201\d|link:)
|
||||||
expected-line-ending-format=LF
|
expected-line-ending-format=LF
|
||||||
|
|
||||||
[VARIABLES]
|
[VARIABLES]
|
||||||
|
@ -32,6 +32,8 @@ Added
|
|||||||
QtWebEngine.
|
QtWebEngine.
|
||||||
* Opening a PDF file now doesn't start a second request anymore.
|
* Opening a PDF file now doesn't start a second request anymore.
|
||||||
* Opening PDFs on https:// sites now works properly.
|
* Opening PDFs on https:// sites now works properly.
|
||||||
|
* New `--pdfjs` flag for `prompt-open-download`, so PDFs can be opened in
|
||||||
|
PDF.js with `<Ctrl-P>` in the download prompt.
|
||||||
- New `qt.process_model` setting which can be used to change Chromium's process
|
- New `qt.process_model` setting which can be used to change Chromium's process
|
||||||
model.
|
model.
|
||||||
- New `qt.low_end_device_mode` setting which turns on Chromium's low-end device
|
- New `qt.low_end_device_mode` setting which turns on Chromium's low-end device
|
||||||
@ -68,6 +70,9 @@ Changed
|
|||||||
patterns instead of globs.
|
patterns instead of globs.
|
||||||
- In passthrough mode, Ctrl + Mousewheel now also gets passed through to the
|
- In passthrough mode, Ctrl + Mousewheel now also gets passed through to the
|
||||||
page instead of zooming.
|
page instead of zooming.
|
||||||
|
- Editing text in an external editor now simulates a JS "input" event, which
|
||||||
|
improves compatibility with websites reacting via JS to input.
|
||||||
|
- The `qute://settings` page is now properly sorted on Python 3.5.
|
||||||
|
|
||||||
Fixed
|
Fixed
|
||||||
~~~~~
|
~~~~~
|
||||||
|
@ -88,7 +88,7 @@ git format-patch origin/master <1>
|
|||||||
Running qutebrowser
|
Running qutebrowser
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
After link:install.html#tox[installing qutebrowser via tox], you can run
|
After link:install{outfilesuffix}#tox[installing qutebrowser via tox], you can run
|
||||||
`.venv/bin/qutebrowser --debug --temp-basedir` to test your changes with debug
|
`.venv/bin/qutebrowser --debug --temp-basedir` to test your changes with debug
|
||||||
logging enabled and without affecting existing running instances.
|
logging enabled and without affecting existing running instances.
|
||||||
|
|
||||||
|
@ -315,5 +315,5 @@ My issue is not listed.::
|
|||||||
https://github.com/qutebrowser/qutebrowser/issues[the issue tracker] or
|
https://github.com/qutebrowser/qutebrowser/issues[the issue tracker] or
|
||||||
using the `:report` command.
|
using the `:report` command.
|
||||||
If you are reporting a segfault, make sure you read the
|
If you are reporting a segfault, make sure you read the
|
||||||
link:doc/stacktrace.html[guide] on how to report them with all needed
|
link:stacktrace{outfilesuffix}[guide] on how to report them with all needed
|
||||||
information.
|
information.
|
||||||
|
@ -758,11 +758,11 @@ This tries to automatically click on typical _Previous Page_ or _Next Page_ link
|
|||||||
- `up`: Go up a level in the current URL.
|
- `up`: Go up a level in the current URL.
|
||||||
- `increment`: Increment the last number in the URL.
|
- `increment`: Increment the last number in the URL.
|
||||||
Uses the
|
Uses the
|
||||||
link:settings.html#url.incdec_segments[url.incdec_segments]
|
link:settings{outsuffix}#url.incdec_segments[url.incdec_segments]
|
||||||
config option.
|
config option.
|
||||||
- `decrement`: Decrement the last number in the URL.
|
- `decrement`: Decrement the last number in the URL.
|
||||||
Uses the
|
Uses the
|
||||||
link:settings.html#url.incdec_segments[url.incdec_segments]
|
link:settings{outsuffix}#url.incdec_segments[url.incdec_segments]
|
||||||
config option.
|
config option.
|
||||||
|
|
||||||
|
|
||||||
@ -1666,7 +1666,7 @@ Shift the focus of the prompt file completion menu to another item.
|
|||||||
|
|
||||||
[[prompt-open-download]]
|
[[prompt-open-download]]
|
||||||
=== prompt-open-download
|
=== prompt-open-download
|
||||||
Syntax: +:prompt-open-download ['cmdline']+
|
Syntax: +:prompt-open-download [*--pdfjs*] ['cmdline']+
|
||||||
|
|
||||||
Immediately open a download.
|
Immediately open a download.
|
||||||
|
|
||||||
@ -1678,6 +1678,9 @@ If no specific command is given, this will use the system's default application
|
|||||||
cmdline.
|
cmdline.
|
||||||
|
|
||||||
|
|
||||||
|
==== optional arguments
|
||||||
|
* +*-p*+, +*--pdfjs*+: Open the download via PDF.js.
|
||||||
|
|
||||||
==== note
|
==== note
|
||||||
* This command does not split arguments after the last argument and handles quotes literally.
|
* This command does not split arguments after the last argument and handles quotes literally.
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ If you want to customize many settings, you can open the link:qute://settings[]
|
|||||||
page by running `:set` without any arguments, where all settings are listed and
|
page by running `:set` without any arguments, where all settings are listed and
|
||||||
customizable.
|
customizable.
|
||||||
|
|
||||||
Using the link:commands.html#set[`:set`] command and command completion, you
|
Using the link:commands{outfilesuffix}#set[`:set`] command and command completion, you
|
||||||
can quickly set settings interactively, for example `:set tabs.position left`.
|
can quickly set settings interactively, for example `:set tabs.position left`.
|
||||||
|
|
||||||
Some settings are also customizable for a given
|
Some settings are also customizable for a given
|
||||||
@ -53,8 +53,8 @@ https://developer.chrome.com/apps/match_patterns[URL pattern] by doing e.g.
|
|||||||
|
|
||||||
To get more help about a setting, use e.g. `:help tabs.position`.
|
To get more help about a setting, use e.g. `:help tabs.position`.
|
||||||
|
|
||||||
To bind and unbind keys, you can use the link:commands.html#bind[`:bind`] and
|
To bind and unbind keys, you can use the link:commands{outfilesuffix}#bind[`:bind`] and
|
||||||
link:commands.html#unbind[`:unbind`] commands:
|
link:commands{outfilesuffix}#unbind[`:unbind`] commands:
|
||||||
|
|
||||||
- Binding the key chain `,v` to the `:spawn mpv {url}` command:
|
- Binding the key chain `,v` to the `:spawn mpv {url}` command:
|
||||||
`:bind ,v spawn mpv {url}`
|
`:bind ,v spawn mpv {url}`
|
||||||
@ -67,9 +67,9 @@ See the help pages linked above (or `:help :bind`, `:help :unbind`) for more
|
|||||||
information.
|
information.
|
||||||
|
|
||||||
Other useful commands for config manipulation are
|
Other useful commands for config manipulation are
|
||||||
link:commands.html#config-unset[`:config-unset`] to reset a value to its default,
|
link:commands{outfilesuffix}#config-unset[`:config-unset`] to reset a value to its default,
|
||||||
link:commands.html#config-clear[`:config-clear`] to reset the entire configuration,
|
link:commands{outfilesuffix}#config-clear[`:config-clear`] to reset the entire configuration,
|
||||||
and link:commands.html#config-cycle[`:config-cycle`] to cycle a setting between
|
and link:commands{outfilesuffix}#config-cycle[`:config-cycle`] to cycle a setting between
|
||||||
different values.
|
different values.
|
||||||
|
|
||||||
[[configpy]]
|
[[configpy]]
|
||||||
@ -111,7 +111,7 @@ Note that qutebrowser does some Python magic so it's able to warn you about
|
|||||||
mistyped config settings. As an example, if you do `c.tabs.possition = "left"`,
|
mistyped config settings. As an example, if you do `c.tabs.possition = "left"`,
|
||||||
you'll get an error when starting.
|
you'll get an error when starting.
|
||||||
|
|
||||||
See the link:settings.html[settings help page] for all available settings. The
|
See the link:settings{outfilesuffix}[settings help page] for all available settings. The
|
||||||
accepted values depend on the type of the option. Commonly used are:
|
accepted values depend on the type of the option. Commonly used are:
|
||||||
|
|
||||||
- Strings: `c.tabs.position = "left"`
|
- Strings: `c.tabs.position = "left"`
|
||||||
@ -187,7 +187,7 @@ preferred to use the `config.bind` command. Doing so ensures the commands are
|
|||||||
valid and normalizes different expressions which map to the same key.
|
valid and normalizes different expressions which map to the same key.
|
||||||
|
|
||||||
For details on how to specify keys and the available modes, see the
|
For details on how to specify keys and the available modes, see the
|
||||||
link:settings.html#bindings.commands[documentation] for the `bindings.commands`
|
link:settings{outfilesuffix}#bindings.commands[documentation] for the `bindings.commands`
|
||||||
setting.
|
setting.
|
||||||
|
|
||||||
To bind a key:
|
To bind a key:
|
||||||
|
@ -6,14 +6,14 @@ Documentation
|
|||||||
|
|
||||||
The following help pages are currently available:
|
The following help pages are currently available:
|
||||||
|
|
||||||
* link:../quickstart.html[Quick start guide]
|
* link:../quickstart{outfilesuffix}[Quick start guide]
|
||||||
* link:../faq.html[Frequently asked questions]
|
* link:../faq{outfilesuffix}[Frequently asked questions]
|
||||||
* link:../changelog.html[Change Log]
|
* link:../changelog{outfilesuffix}[Change Log]
|
||||||
* link:commands.html[Documentation of commands]
|
* link:commands{outfilesuffix}[Documentation of commands]
|
||||||
* link:configuring.html[Configuring qutebrowser]
|
* link:configuring{outfilesuffix}[Configuring qutebrowser]
|
||||||
* link:settings.html[Documentation of settings]
|
* link:settings{outfilesuffix}[Documentation of settings]
|
||||||
* link:../userscripts.html[How to write userscripts]
|
* link:../userscripts{outfilesuffix}[How to write userscripts]
|
||||||
* link:../contributing.html[Contributing to qutebrowser]
|
* link:../contributing{outfilesuffix}[Contributing to qutebrowser]
|
||||||
|
|
||||||
Getting help
|
Getting help
|
||||||
------------
|
------------
|
||||||
|
@ -660,6 +660,7 @@ Default:
|
|||||||
* +pass:[<Ctrl-F>]+: +pass:[rl-forward-char]+
|
* +pass:[<Ctrl-F>]+: +pass:[rl-forward-char]+
|
||||||
* +pass:[<Ctrl-H>]+: +pass:[rl-backward-delete-char]+
|
* +pass:[<Ctrl-H>]+: +pass:[rl-backward-delete-char]+
|
||||||
* +pass:[<Ctrl-K>]+: +pass:[rl-kill-line]+
|
* +pass:[<Ctrl-K>]+: +pass:[rl-kill-line]+
|
||||||
|
* +pass:[<Ctrl-P>]+: +pass:[prompt-open-download --pdfjs]+
|
||||||
* +pass:[<Ctrl-U>]+: +pass:[rl-unix-line-discard]+
|
* +pass:[<Ctrl-U>]+: +pass:[rl-unix-line-discard]+
|
||||||
* +pass:[<Ctrl-W>]+: +pass:[rl-unix-word-rubout]+
|
* +pass:[<Ctrl-W>]+: +pass:[rl-unix-word-rubout]+
|
||||||
* +pass:[<Ctrl-X>]+: +pass:[prompt-open-download]+
|
* +pass:[<Ctrl-X>]+: +pass:[prompt-open-download]+
|
||||||
|
@ -31,7 +31,7 @@ pytest-cov==2.6.0
|
|||||||
pytest-faulthandler==1.5.0
|
pytest-faulthandler==1.5.0
|
||||||
pytest-instafail==0.4.0
|
pytest-instafail==0.4.0
|
||||||
pytest-mock==1.10.0
|
pytest-mock==1.10.0
|
||||||
pytest-qt==3.1.0
|
pytest-qt==3.2.0
|
||||||
pytest-repeat==0.7.0
|
pytest-repeat==0.7.0
|
||||||
pytest-rerunfailures==4.1
|
pytest-rerunfailures==4.1
|
||||||
pytest-travis-fold==1.3.0
|
pytest-travis-fold==1.3.0
|
||||||
|
@ -612,11 +612,11 @@ class CommandDispatcher:
|
|||||||
- `up`: Go up a level in the current URL.
|
- `up`: Go up a level in the current URL.
|
||||||
- `increment`: Increment the last number in the URL.
|
- `increment`: Increment the last number in the URL.
|
||||||
Uses the
|
Uses the
|
||||||
link:settings.html#url.incdec_segments[url.incdec_segments]
|
link:settings{outsuffix}#url.incdec_segments[url.incdec_segments]
|
||||||
config option.
|
config option.
|
||||||
- `decrement`: Decrement the last number in the URL.
|
- `decrement`: Decrement the last number in the URL.
|
||||||
Uses the
|
Uses the
|
||||||
link:settings.html#url.incdec_segments[url.incdec_segments]
|
link:settings{outsuffix}#url.incdec_segments[url.incdec_segments]
|
||||||
config option.
|
config option.
|
||||||
|
|
||||||
tab: Open in a new tab.
|
tab: Open in a new tab.
|
||||||
@ -1659,6 +1659,8 @@ class CommandDispatcher:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
elem.set_value(text)
|
elem.set_value(text)
|
||||||
|
# Kick off js handlers to trick them into thinking there was input.
|
||||||
|
elem.dispatch_event("input", bubbles=True)
|
||||||
except webelem.OrphanedError:
|
except webelem.OrphanedError:
|
||||||
message.error('Edited element vanished')
|
message.error('Edited element vanished')
|
||||||
ed.backup()
|
ed.backup()
|
||||||
|
@ -99,10 +99,10 @@ def _generate_pdfjs_script(filename):
|
|||||||
}
|
}
|
||||||
|
|
||||||
const viewer = window.PDFView || window.PDFViewerApplication;
|
const viewer = window.PDFView || window.PDFViewerApplication;
|
||||||
viewer.open("{{ url }}");
|
viewer.open({{ url }});
|
||||||
});
|
});
|
||||||
""").render(
|
""").render(
|
||||||
url=javascript.string_escape(url.toString(QUrl.FullyEncoded)),
|
url=javascript.to_js(url.toString(QUrl.FullyEncoded)),
|
||||||
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70420
|
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70420
|
||||||
disable_create_object_url=(
|
disable_create_object_url=(
|
||||||
not qtutils.version_check('5.12') and
|
not qtutils.version_check('5.12') and
|
||||||
|
@ -139,6 +139,18 @@ class AbstractWebElement(collections.abc.MutableMapping):
|
|||||||
"""Set the element value."""
|
"""Set the element value."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def dispatch_event(self, event, bubbles=False,
|
||||||
|
cancelable=False, composed=False):
|
||||||
|
"""Dispatch an event to the element.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bubbles: Whether this event should bubble.
|
||||||
|
cancelable: Whether this event can be cancelled.
|
||||||
|
composed: Whether the event will trigger listeners outside of a
|
||||||
|
shadow root.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def insert_text(self, text):
|
def insert_text(self, text):
|
||||||
"""Insert the given text into the element."""
|
"""Insert the given text into the element."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -135,6 +135,10 @@ class WebEngineElement(webelem.AbstractWebElement):
|
|||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
self._js_call('set_value', value)
|
self._js_call('set_value', value)
|
||||||
|
|
||||||
|
def dispatch_event(self, event, bubbles=False,
|
||||||
|
cancelable=False, composed=False):
|
||||||
|
self._js_call('dispatch_event', event, bubbles, cancelable, composed)
|
||||||
|
|
||||||
def caret_position(self):
|
def caret_position(self):
|
||||||
"""Get the text caret position for the current element.
|
"""Get the text caret position for the current element.
|
||||||
|
|
||||||
|
@ -125,8 +125,20 @@ class WebKitElement(webelem.AbstractWebElement):
|
|||||||
self._elem.setPlainText(value)
|
self._elem.setPlainText(value)
|
||||||
else:
|
else:
|
||||||
log.webelem.debug("Filling {!r} via javascript.".format(self))
|
log.webelem.debug("Filling {!r} via javascript.".format(self))
|
||||||
value = javascript.string_escape(value)
|
value = javascript.to_js(value)
|
||||||
self._elem.evaluateJavaScript("this.value='{}'".format(value))
|
self._elem.evaluateJavaScript("this.value={}".format(value))
|
||||||
|
|
||||||
|
def dispatch_event(self, event, bubbles=False,
|
||||||
|
cancelable=False, composed=False):
|
||||||
|
self._check_vanished()
|
||||||
|
log.webelem.debug("Firing event on {!r} via javascript.".format(self))
|
||||||
|
self._elem.evaluateJavaScript(
|
||||||
|
"this.dispatchEvent(new Event({}, "
|
||||||
|
"{{'bubbles': {}, 'cancelable': {}, 'composed': {}}}))"
|
||||||
|
.format(javascript.to_js(event),
|
||||||
|
javascript.to_js(bubbles),
|
||||||
|
javascript.to_js(cancelable),
|
||||||
|
javascript.to_js(composed)))
|
||||||
|
|
||||||
def caret_position(self):
|
def caret_position(self):
|
||||||
"""Get the text caret position for the current element."""
|
"""Get the text caret position for the current element."""
|
||||||
@ -142,11 +154,11 @@ class WebKitElement(webelem.AbstractWebElement):
|
|||||||
raise webelem.Error("Element is not editable!")
|
raise webelem.Error("Element is not editable!")
|
||||||
log.webelem.debug("Inserting text into element {!r}".format(self))
|
log.webelem.debug("Inserting text into element {!r}".format(self))
|
||||||
self._elem.evaluateJavaScript("""
|
self._elem.evaluateJavaScript("""
|
||||||
var text = "{}";
|
var text = {};
|
||||||
var event = document.createEvent("TextEvent");
|
var event = document.createEvent("TextEvent");
|
||||||
event.initTextEvent("textInput", true, true, null, text);
|
event.initTextEvent("textInput", true, true, null, text);
|
||||||
this.dispatchEvent(event);
|
this.dispatchEvent(event);
|
||||||
""".format(javascript.string_escape(text)))
|
""".format(javascript.to_js(text)))
|
||||||
|
|
||||||
def _parent(self):
|
def _parent(self):
|
||||||
"""Get the parent element of this element."""
|
"""Get the parent element of this element."""
|
||||||
|
@ -2627,6 +2627,7 @@ bindings.default:
|
|||||||
prompt:
|
prompt:
|
||||||
<Return>: prompt-accept
|
<Return>: prompt-accept
|
||||||
<Ctrl-X>: prompt-open-download
|
<Ctrl-X>: prompt-open-download
|
||||||
|
<Ctrl-P>: prompt-open-download --pdfjs
|
||||||
<Shift-Tab>: prompt-item-focus prev
|
<Shift-Tab>: prompt-item-focus prev
|
||||||
<Up>: prompt-item-focus prev
|
<Up>: prompt-item-focus prev
|
||||||
<Tab>: prompt-item-focus next
|
<Tab>: prompt-item-focus next
|
||||||
|
@ -34,7 +34,7 @@ input { width: 98%; }
|
|||||||
<th>Setting</th>
|
<th>Setting</th>
|
||||||
<th>Value</th>
|
<th>Value</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for option in configdata.DATA.values() if not option.no_autoconfig %}
|
{% for option in configdata.DATA.values()|sort(attribute='name') if not option.no_autoconfig %}
|
||||||
<tr>
|
<tr>
|
||||||
<!-- FIXME: convert to string properly -->
|
<!-- FIXME: convert to string properly -->
|
||||||
<td class="setting">{{ option.name }} (Current: {{ confget(option.name) | string |truncate(100) }})
|
<td class="setting">{{ option.name }} (Current: {{ confget(option.name) | string |truncate(100) }})
|
||||||
|
@ -59,3 +59,4 @@ rules:
|
|||||||
multiline-ternary: ["error", "always-multiline"]
|
multiline-ternary: ["error", "always-multiline"]
|
||||||
max-lines-per-function: "off"
|
max-lines-per-function: "off"
|
||||||
require-unicode-regexp: "off"
|
require-unicode-regexp: "off"
|
||||||
|
max-params: "off"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable max-len, max-statements, complexity,
|
/* eslint-disable max-len, max-statements, complexity,
|
||||||
max-params, default-case, valid-jsdoc */
|
default-case, valid-jsdoc */
|
||||||
|
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -362,6 +362,15 @@ window._qutebrowser.webelem = (function() {
|
|||||||
document.execCommand("insertText", false, text);
|
document.execCommand("insertText", false, text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
funcs.dispatch_event = (id, event, bubbles = false,
|
||||||
|
cancelable = false, composed = false) => {
|
||||||
|
const elem = elements[id];
|
||||||
|
elem.dispatchEvent(
|
||||||
|
new Event(event, {"bubbles": bubbles,
|
||||||
|
"cancelable": cancelable,
|
||||||
|
"composed": composed}));
|
||||||
|
};
|
||||||
|
|
||||||
funcs.set_attribute = (id, name, value) => {
|
funcs.set_attribute = (id, name, value) => {
|
||||||
elements[id].setAttribute(name, value);
|
elements[id].setAttribute(name, value);
|
||||||
};
|
};
|
||||||
|
@ -391,7 +391,7 @@ class PromptContainer(QWidget):
|
|||||||
|
|
||||||
@cmdutils.register(instance='prompt-container', scope='window',
|
@cmdutils.register(instance='prompt-container', scope='window',
|
||||||
modes=[usertypes.KeyMode.prompt], maxsplit=0)
|
modes=[usertypes.KeyMode.prompt], maxsplit=0)
|
||||||
def prompt_open_download(self, cmdline: str = None):
|
def prompt_open_download(self, cmdline: str = None, pdfjs=False):
|
||||||
"""Immediately open a download.
|
"""Immediately open a download.
|
||||||
|
|
||||||
If no specific command is given, this will use the system's default
|
If no specific command is given, this will use the system's default
|
||||||
@ -402,9 +402,10 @@ class PromptContainer(QWidget):
|
|||||||
is expanded to the temporary file name. If no `{}` is
|
is expanded to the temporary file name. If no `{}` is
|
||||||
present, the filename is automatically appended to the
|
present, the filename is automatically appended to the
|
||||||
cmdline.
|
cmdline.
|
||||||
|
pdfjs: Open the download via PDF.js.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._prompt.download_open(cmdline)
|
self._prompt.download_open(cmdline, pdfjs=pdfjs)
|
||||||
except UnsupportedOperationError:
|
except UnsupportedOperationError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -537,8 +538,10 @@ class _BasePrompt(QWidget):
|
|||||||
def accept(self, value=None):
|
def accept(self, value=None):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def download_open(self, _cmdline):
|
def download_open(self, cmdline, pdfjs):
|
||||||
"""Open the download directly if this is a download prompt."""
|
"""Open the download directly if this is a download prompt."""
|
||||||
|
utils.unused(cmdline)
|
||||||
|
utils.unused(pdfjs)
|
||||||
raise UnsupportedOperationError
|
raise UnsupportedOperationError
|
||||||
|
|
||||||
def item_focus(self, _which):
|
def item_focus(self, _which):
|
||||||
@ -757,8 +760,13 @@ class DownloadFilenamePrompt(FilenamePrompt):
|
|||||||
self.question.answer = downloads.FileDownloadTarget(answer)
|
self.question.answer = downloads.FileDownloadTarget(answer)
|
||||||
return done
|
return done
|
||||||
|
|
||||||
def download_open(self, cmdline):
|
def download_open(self, cmdline, pdfjs):
|
||||||
self.question.answer = downloads.OpenFileDownloadTarget(cmdline)
|
if pdfjs:
|
||||||
|
target = downloads.PDFJSDownloadTarget()
|
||||||
|
else:
|
||||||
|
target = downloads.OpenFileDownloadTarget(cmdline)
|
||||||
|
|
||||||
|
self.question.answer = target
|
||||||
self.question.done()
|
self.question.done()
|
||||||
message.global_bridge.prompt_done.emit(self.KEY_MODE)
|
message.global_bridge.prompt_done.emit(self.KEY_MODE)
|
||||||
|
|
||||||
@ -767,6 +775,7 @@ class DownloadFilenamePrompt(FilenamePrompt):
|
|||||||
('prompt-accept', 'Accept'),
|
('prompt-accept', 'Accept'),
|
||||||
('leave-mode', 'Abort'),
|
('leave-mode', 'Abort'),
|
||||||
('prompt-open-download', "Open download"),
|
('prompt-open-download', "Open download"),
|
||||||
|
('prompt-open-download --pdfjs', "Open download via PDF.js"),
|
||||||
('prompt-yank', "Yank URL"),
|
('prompt-yank', "Yank URL"),
|
||||||
]
|
]
|
||||||
return cmds
|
return cmds
|
||||||
|
@ -385,13 +385,14 @@ class TabBar(QTabBar):
|
|||||||
if option.startswith('colors.tabs.'):
|
if option.startswith('colors.tabs.'):
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
# Clear _minimum_tab_size_hint_helper cache when appropriate
|
# Clear tab size caches when appropriate
|
||||||
if option in ["tabs.indicator.padding",
|
if option in ["tabs.indicator.padding",
|
||||||
"tabs.padding",
|
"tabs.padding",
|
||||||
"tabs.indicator.width",
|
"tabs.indicator.width",
|
||||||
"tabs.min_width",
|
"tabs.min_width",
|
||||||
"tabs.pinned.shrink"]:
|
"tabs.pinned.shrink"]:
|
||||||
self._minimum_tab_size_hint_helper.cache_clear()
|
self._minimum_tab_size_hint_helper.cache_clear()
|
||||||
|
self._minimum_tab_height.cache_clear()
|
||||||
|
|
||||||
def _on_show_switching_delay_changed(self):
|
def _on_show_switching_delay_changed(self):
|
||||||
"""Set timer interval when tabs.show_switching_delay got changed."""
|
"""Set timer interval when tabs.show_switching_delay got changed."""
|
||||||
@ -468,6 +469,7 @@ class TabBar(QTabBar):
|
|||||||
self._set_icon_size()
|
self._set_icon_size()
|
||||||
# clear tab size cache
|
# clear tab size cache
|
||||||
self._minimum_tab_size_hint_helper.cache_clear()
|
self._minimum_tab_size_hint_helper.cache_clear()
|
||||||
|
self._minimum_tab_height.cache_clear()
|
||||||
|
|
||||||
def _set_icon_size(self):
|
def _set_icon_size(self):
|
||||||
"""Set the tab bar favicon size."""
|
"""Set the tab bar favicon size."""
|
||||||
@ -555,8 +557,7 @@ class TabBar(QTabBar):
|
|||||||
# Only add padding if indicator exists
|
# Only add padding if indicator exists
|
||||||
if indicator_width != 0:
|
if indicator_width != 0:
|
||||||
padding_h += indicator_padding.left + indicator_padding.right
|
padding_h += indicator_padding.left + indicator_padding.right
|
||||||
padding_v = padding.top + padding.bottom
|
height = self._minimum_tab_height()
|
||||||
height = self.fontMetrics().height() + padding_v
|
|
||||||
width = (text_width + icon_width +
|
width = (text_width + icon_width +
|
||||||
padding_h + indicator_width)
|
padding_h + indicator_width)
|
||||||
min_width = config.val.tabs.min_width
|
min_width = config.val.tabs.min_width
|
||||||
@ -565,6 +566,11 @@ class TabBar(QTabBar):
|
|||||||
width = max(min_width, width)
|
width = max(min_width, width)
|
||||||
return QSize(width, height)
|
return QSize(width, height)
|
||||||
|
|
||||||
|
@functools.lru_cache(maxsize=1)
|
||||||
|
def _minimum_tab_height(self):
|
||||||
|
padding = config.cache['tabs.padding']
|
||||||
|
return self.fontMetrics().height() + padding.top + padding.bottom
|
||||||
|
|
||||||
def _tab_pinned(self, index: int) -> bool:
|
def _tab_pinned(self, index: int) -> bool:
|
||||||
"""Return True if tab is pinned."""
|
"""Return True if tab is pinned."""
|
||||||
if not 0 <= index < self.count():
|
if not 0 <= index < self.count():
|
||||||
@ -589,8 +595,7 @@ class TabBar(QTabBar):
|
|||||||
# want to ensure it's valid in this special case.
|
# want to ensure it's valid in this special case.
|
||||||
return QSize()
|
return QSize()
|
||||||
|
|
||||||
minimum_size = self.minimumTabSizeHint(index)
|
height = self._minimum_tab_height()
|
||||||
height = minimum_size.height()
|
|
||||||
if self.vertical:
|
if self.vertical:
|
||||||
confwidth = str(config.cache['tabs.width'])
|
confwidth = str(config.cache['tabs.width'])
|
||||||
if confwidth.endswith('%'):
|
if confwidth.endswith('%'):
|
||||||
@ -600,7 +605,7 @@ class TabBar(QTabBar):
|
|||||||
width = main_window.width() * perc / 100
|
width = main_window.width() * perc / 100
|
||||||
else:
|
else:
|
||||||
width = int(confwidth)
|
width = int(confwidth)
|
||||||
size = QSize(max(minimum_size.width(), width), height)
|
size = QSize(width, height)
|
||||||
else:
|
else:
|
||||||
if config.cache['tabs.pinned.shrink'] and self._tab_pinned(index):
|
if config.cache['tabs.pinned.shrink'] and self._tab_pinned(index):
|
||||||
# Give pinned tabs the minimum size they need to display their
|
# Give pinned tabs the minimum size they need to display their
|
||||||
@ -614,8 +619,9 @@ class TabBar(QTabBar):
|
|||||||
if max_width > 0:
|
if max_width > 0:
|
||||||
width = min(max_width, width)
|
width = min(max_width, width)
|
||||||
|
|
||||||
# If we don't have enough space, we return the minimum size
|
# If for some reason (tests, bugs) self.width() gives 0, use a
|
||||||
width = max(width, minimum_size.width())
|
# sane min of 10 px
|
||||||
|
width = max(width, 10)
|
||||||
size = QSize(width, height)
|
size = QSize(width, height)
|
||||||
qtutils.ensure_valid(size)
|
qtutils.ensure_valid(size)
|
||||||
return size
|
return size
|
||||||
|
@ -49,7 +49,7 @@ def string_escape(text):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def _convert_js_arg(arg):
|
def to_js(arg):
|
||||||
"""Convert the given argument so it's the equivalent in JS."""
|
"""Convert the given argument so it's the equivalent in JS."""
|
||||||
if arg is None:
|
if arg is None:
|
||||||
return 'undefined'
|
return 'undefined'
|
||||||
@ -60,7 +60,7 @@ def _convert_js_arg(arg):
|
|||||||
elif isinstance(arg, (int, float)):
|
elif isinstance(arg, (int, float)):
|
||||||
return str(arg)
|
return str(arg)
|
||||||
elif isinstance(arg, list):
|
elif isinstance(arg, list):
|
||||||
return '[{}]'.format(', '.join(_convert_js_arg(e) for e in arg))
|
return '[{}]'.format(', '.join(to_js(e) for e in arg))
|
||||||
else:
|
else:
|
||||||
raise TypeError("Don't know how to handle {!r} of type {}!".format(
|
raise TypeError("Don't know how to handle {!r} of type {}!".format(
|
||||||
arg, type(arg).__name__))
|
arg, type(arg).__name__))
|
||||||
@ -68,7 +68,7 @@ def _convert_js_arg(arg):
|
|||||||
|
|
||||||
def assemble(module, function, *args):
|
def assemble(module, function, *args):
|
||||||
"""Assemble a javascript file and a function call."""
|
"""Assemble a javascript file and a function call."""
|
||||||
js_args = ', '.join(_convert_js_arg(arg) for arg in args)
|
js_args = ', '.join(to_js(arg) for arg in args)
|
||||||
if module == 'window':
|
if module == 'window':
|
||||||
parts = ['window', function]
|
parts = ['window', function]
|
||||||
else:
|
else:
|
||||||
|
@ -315,8 +315,8 @@ def _chromium_version():
|
|||||||
Quick reference:
|
Quick reference:
|
||||||
|
|
||||||
Qt 5.7: Chromium 49
|
Qt 5.7: Chromium 49
|
||||||
49.0.2623.111 (2016-03-02)
|
49.0.2623.111 (2016-03-31)
|
||||||
5.7.1: Security fixes up to 54.0.2840.87 (2016-10-19)
|
5.7.1: Security fixes up to 54.0.2840.87 (2016-11-01)
|
||||||
|
|
||||||
Qt 5.8: Chromium 53
|
Qt 5.8: Chromium 53
|
||||||
53.0.2785.148 (2016-08-31)
|
53.0.2785.148 (2016-08-31)
|
||||||
@ -324,20 +324,21 @@ def _chromium_version():
|
|||||||
|
|
||||||
Qt 5.9: Chromium 56
|
Qt 5.9: Chromium 56
|
||||||
(LTS) 56.0.2924.122 (2017-01-25)
|
(LTS) 56.0.2924.122 (2017-01-25)
|
||||||
5.9.6: Security fixes up to 66.0.3359.170 (2018-04-17)
|
5.9.6: Security fixes up to 66.0.3359.170 (2018-05-10)
|
||||||
|
|
||||||
Qt 5.10: Chromium 61
|
Qt 5.10: Chromium 61
|
||||||
61.0.3163.140 (2017-09-05)
|
61.0.3163.140 (2017-09-05)
|
||||||
5.10.1: Security fixes up to 64.0.3282.140 (2018-01-24)
|
5.10.1: Security fixes up to 64.0.3282.140 (2018-02-01)
|
||||||
|
|
||||||
Qt 5.11: Chromium 65
|
Qt 5.11: Chromium 65
|
||||||
65.0.3325.151 (.1: .230) (2018-03-06)
|
65.0.3325.151 (.1: .230) (2018-03-06)
|
||||||
5.11.1: Security fixes up to 67.0.3396.87 (2018-05-29)
|
5.11.2: Security fixes up to 68.0.3440.75 (2018-07-24)
|
||||||
|
|
||||||
Qt 5.12: Chromium 69
|
Qt 5.12: Chromium 69
|
||||||
current 5.12 branch: 69.0.3497.70 (2018-09-11)
|
current 5.12 branch: 69.0.3497.70 (2018-09-11)
|
||||||
|
|
||||||
Also see https://www.chromium.org/developers/calendar
|
Also see https://www.chromium.org/developers/calendar
|
||||||
|
and https://chromereleases.googleblog.com/
|
||||||
"""
|
"""
|
||||||
if QWebEngineProfile is None:
|
if QWebEngineProfile is None:
|
||||||
# This should never happen
|
# This should never happen
|
||||||
|
@ -42,7 +42,6 @@ from PyQt5.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
|
|||||||
from PyQt5.QtNetwork import QNetworkCookieJar
|
from PyQt5.QtNetwork import QNetworkCookieJar
|
||||||
|
|
||||||
import helpers.stubs as stubsmod
|
import helpers.stubs as stubsmod
|
||||||
import helpers.utils
|
|
||||||
from qutebrowser.config import (config, configdata, configtypes, configexc,
|
from qutebrowser.config import (config, configdata, configtypes, configexc,
|
||||||
configfiles, configcache)
|
configfiles, configcache)
|
||||||
from qutebrowser.utils import objreg, standarddir, utils, usertypes
|
from qutebrowser.utils import objreg, standarddir, utils, usertypes
|
||||||
|
@ -27,8 +27,6 @@ import contextlib
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal
|
|
||||||
|
|
||||||
from qutebrowser.utils import qtutils
|
from qutebrowser.utils import qtutils
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import pytest
|
|||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
from qutebrowser.utils import usertypes
|
from qutebrowser.utils import usertypes
|
||||||
from helpers import utils
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -298,7 +297,7 @@ class TestSearch:
|
|||||||
|
|
||||||
with qtbot.wait_callback() as callback:
|
with qtbot.wait_callback() as callback:
|
||||||
web_tab.search.search('fiv', result_cb=callback)
|
web_tab.search.search('fiv', result_cb=callback)
|
||||||
assert callback.args == [True]
|
callback.assert_called_with(True)
|
||||||
|
|
||||||
mode_manager.enter(usertypes.KeyMode.caret)
|
mode_manager.enter(usertypes.KeyMode.caret)
|
||||||
caret.move_to_end_of_line()
|
caret.move_to_end_of_line()
|
||||||
@ -312,11 +311,11 @@ class TestSearch:
|
|||||||
|
|
||||||
with qtbot.wait_callback() as callback:
|
with qtbot.wait_callback() as callback:
|
||||||
web_tab.search.search('w', result_cb=callback)
|
web_tab.search.search('w', result_cb=callback)
|
||||||
assert callback.args == [True]
|
callback.assert_called_with(True)
|
||||||
|
|
||||||
with qtbot.wait_callback() as callback:
|
with qtbot.wait_callback() as callback:
|
||||||
web_tab.search.next_result(result_cb=callback)
|
web_tab.search.next_result(result_cb=callback)
|
||||||
assert callback.args == [True]
|
callback.assert_called_with(True)
|
||||||
|
|
||||||
mode_manager.enter(usertypes.KeyMode.caret)
|
mode_manager.enter(usertypes.KeyMode.caret)
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ def test_generate_pdfjs_page(available, snippet, monkeypatch):
|
|||||||
|
|
||||||
|
|
||||||
# Note that we got double protection, once because we use QUrl.FullyEncoded and
|
# Note that we got double protection, once because we use QUrl.FullyEncoded and
|
||||||
# because we use qutebrowser.utils.javascript.string_escape. Characters
|
# because we use qutebrowser.utils.javascript.to_js. Characters like " are
|
||||||
# like " are already replaced by QUrl.
|
# already replaced by QUrl.
|
||||||
@pytest.mark.parametrize('filename, expected', [
|
@pytest.mark.parametrize('filename, expected', [
|
||||||
('foo.bar', "foo.bar"),
|
('foo.bar', "foo.bar"),
|
||||||
('foo"bar', "foo%22bar"),
|
('foo"bar', "foo%22bar"),
|
||||||
|
@ -409,8 +409,8 @@ class TestWebKitElement:
|
|||||||
assert elem.value() == 'js'
|
assert elem.value() == 'js'
|
||||||
|
|
||||||
@pytest.mark.parametrize('editable, value, uses_js, arg', [
|
@pytest.mark.parametrize('editable, value, uses_js, arg', [
|
||||||
('false', 'foo', True, "this.value='foo'"),
|
('false', 'foo', True, 'this.value="foo"'),
|
||||||
('false', "foo'bar", True, r"this.value='foo\'bar'"),
|
('false', "foo'bar", True, r'this.value="foo\'bar"'),
|
||||||
('true', 'foo', False, 'foo'),
|
('true', 'foo', False, 'foo'),
|
||||||
])
|
])
|
||||||
def test_set_value(self, editable, value, uses_js, arg):
|
def test_set_value(self, editable, value, uses_js, arg):
|
||||||
|
@ -27,7 +27,6 @@ import jinja2
|
|||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
import helpers.utils
|
|
||||||
from qutebrowser.utils import utils
|
from qutebrowser.utils import utils
|
||||||
|
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ class JSTester:
|
|||||||
"""
|
"""
|
||||||
with self.qtbot.wait_callback() as callback:
|
with self.qtbot.wait_callback() as callback:
|
||||||
self.tab.run_js_async(source, callback, world=world)
|
self.tab.run_js_async(source, callback, world=world)
|
||||||
assert callback.args == [expected]
|
callback.assert_called_with(expected)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import helpers.utils
|
|
||||||
|
|
||||||
QWebSettings = pytest.importorskip("PyQt5.QtWebKit").QWebSettings
|
QWebSettings = pytest.importorskip("PyQt5.QtWebKit").QWebSettings
|
||||||
QWebPage = pytest.importorskip("PyQt5.QtWebKitWidgets").QWebPage
|
QWebPage = pytest.importorskip("PyQt5.QtWebKitWidgets").QWebPage
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ class CaretTester:
|
|||||||
|
|
||||||
with self._qtbot.wait_callback() as callback:
|
with self._qtbot.wait_callback() as callback:
|
||||||
self.js.tab.caret.selection(lambda text: callback(text.rstrip()))
|
self.js.tab.caret.selection(lambda text: callback(text.rstrip()))
|
||||||
assert callback.args == ['MARKER']
|
callback.assert_called_with('MARKER')
|
||||||
|
|
||||||
def check_scrolled(self):
|
def check_scrolled(self):
|
||||||
"""Check if the page is scrolled down."""
|
"""Check if the page is scrolled down."""
|
||||||
|
@ -62,9 +62,9 @@ class StylesheetTester:
|
|||||||
"""Check whether the css in ELEMENT is set to VALUE."""
|
"""Check whether the css in ELEMENT is set to VALUE."""
|
||||||
self.js.run("console.log({document});"
|
self.js.run("console.log({document});"
|
||||||
"window.getComputedStyle({document}, null)"
|
"window.getComputedStyle({document}, null)"
|
||||||
".getPropertyValue('{prop}');".format(
|
".getPropertyValue({prop});".format(
|
||||||
document=document_element,
|
document=document_element,
|
||||||
prop=javascript.string_escape(css_style)),
|
prop=javascript.to_js(css_style)),
|
||||||
value)
|
value)
|
||||||
|
|
||||||
def check_eq(self, one, two, true=True):
|
def check_eq(self, one, two, true=True):
|
||||||
|
@ -240,7 +240,7 @@ class TestWindowIsolation:
|
|||||||
|
|
||||||
with qtbot.wait_callback() as callback:
|
with qtbot.wait_callback() as callback:
|
||||||
page.runJavaScript(setup.test_script, callback)
|
page.runJavaScript(setup.test_script, callback)
|
||||||
assert callback.args == [setup.expected]
|
callback.assert_called_with(setup.expected)
|
||||||
|
|
||||||
# The JSCore in 602.1 doesn't fully support Proxy.
|
# The JSCore in 602.1 doesn't fully support Proxy.
|
||||||
@pytest.mark.qtwebkit6021_skip
|
@pytest.mark.qtwebkit6021_skip
|
||||||
|
@ -78,4 +78,4 @@ def test_simple_js_webengine(qtbot, webengineview, qapp,
|
|||||||
with qtbot.wait_callback() as callback:
|
with qtbot.wait_callback() as callback:
|
||||||
page.runJavaScript('1 + 1', world, callback)
|
page.runJavaScript('1 + 1', world, callback)
|
||||||
|
|
||||||
assert callback.args == [expected]
|
callback.assert_called_with(expected)
|
||||||
|
@ -86,12 +86,12 @@ class TestStringEscape:
|
|||||||
(True, 'true'),
|
(True, 'true'),
|
||||||
([23, True, 'x'], '[23, true, "x"]'),
|
([23, True, 'x'], '[23, true, "x"]'),
|
||||||
])
|
])
|
||||||
def test_convert_js_arg(arg, expected):
|
def test_to_js(arg, expected):
|
||||||
if expected is TypeError:
|
if expected is TypeError:
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
javascript._convert_js_arg(arg)
|
javascript.to_js(arg)
|
||||||
else:
|
else:
|
||||||
assert javascript._convert_js_arg(arg) == expected
|
assert javascript.to_js(arg) == expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('base, expected_base', [
|
@pytest.mark.parametrize('base, expected_base', [
|
||||||
|
Loading…
Reference in New Issue
Block a user