Compare commits

...

2382 Commits

Author SHA1 Message Date
Florian Bruhin
469445e816 Release v0.10.0 2017-02-25 21:47:56 +01:00
Florian Bruhin
48ea8d7002 Edit changelog for v0.10.0 2017-02-25 21:43:30 +01:00
Florian Bruhin
9b58a4523d Add v0.10.0 default config 2017-02-25 21:32:19 +01:00
Florian Bruhin
93eab09574 Add a mkvenv-pypi environment to tox.ini 2017-02-25 18:17:32 +01:00
Florian Bruhin
f1ecb21d3d Merge branch 'danfis-session-save-only-active-window' 2017-02-25 17:56:27 +01:00
Florian Bruhin
d771f1f89e Update docs 2017-02-25 17:56:15 +01:00
Florian Bruhin
fc2250b3b2 Merge branch 'session-save-only-active-window' of https://github.com/danfis/qutebrowser into danfis-session-save-only-active-window 2017-02-25 17:55:42 +01:00
Florian Bruhin
1bd9b4cd40 Merge branch 'kiryl-master' 2017-02-25 17:53:47 +01:00
Florian Bruhin
d6e4344f65 Update authors 2017-02-25 17:53:39 +01:00
Florian Bruhin
9656449545 Merge branch 'master' of https://github.com/kiryl/qutebrowser into kiryl-master 2017-02-25 17:53:05 +01:00
Florian Bruhin
392809c423 Merge branch 'imransobir-newbmarkstyle' 2017-02-25 17:48:03 +01:00
Florian Bruhin
b3ff5e3a7f Update authors 2017-02-25 17:47:54 +01:00
Florian Bruhin
496b70697b Merge branch 'newbmarkstyle' of https://github.com/imransobir/qutebrowser into imransobir-newbmarkstyle 2017-02-25 17:46:21 +01:00
Florian Bruhin
4f1d582187 Update changelog 2017-02-25 17:27:34 +01:00
Florian Bruhin
b5d4de17a7 Merge branch 'pkill-nine-upstream-master-jseval-file' 2017-02-25 17:26:59 +01:00
Florian Bruhin
40152d1827 Update docs 2017-02-25 17:26:49 +01:00
Florian Bruhin
1eab108323 Merge branch 'upstream-master-jseval-file' of https://github.com/pkill-nine/qutebrowser into pkill-nine-upstream-master-jseval-file 2017-02-25 17:26:12 +01:00
Florian Bruhin
3cc32e0b6a Fix lint 2017-02-25 17:24:27 +01:00
pkill9
6cb48ba2b6 Adds a --file flag to :jseval 2017-02-25 13:11:53 +00:00
Florian Bruhin
48c9a4061b Also fix ACE hinting for QtWebKit 2017-02-24 18:36:15 +01:00
Florian Bruhin
16b259a390 Update pip requirements 2017-02-24 15:19:39 +01:00
Florian Bruhin
23183bd918 Fix hinting in ACE editors 2017-02-24 15:12:35 +01:00
Florian Bruhin
02c913238b Fix test_webkitelem 2017-02-24 13:51:45 +01:00
Florian Bruhin
3feb4211fe Don't show hints for opacity: 0 elements
Fixes #2347
2017-02-24 09:13:25 +01:00
Florian Bruhin
e832105dd5 Treat the Jupyter input line as editable 2017-02-23 17:43:22 +01:00
Imran Sobir
34abad27c4 Use jinja filter to set default title. 2017-02-23 19:29:49 +05:00
Imran Sobir
4b643f0b74 Extract common styling from bookmarks, history. 2017-02-23 19:23:18 +05:00
Florian Bruhin
fa3bb9a5c8 Update pip requirements 2017-02-23 09:57:53 +01:00
Florian Bruhin
06c4a100cc Fix QtWebKit-NG private-browsing tests 2017-02-23 08:15:18 +01:00
Florian Bruhin
ce3c0a0f55 Mark more private-browsing tests as xfail with QtWebKit-NG 2017-02-23 08:13:40 +01:00
Florian Bruhin
26923baa4a Set NSSupportsAutomaticGraphicsSwitching in Info.plist
This should make it possible to use AirPlay with qutebrowser.
See https://bugreports.qt.io/browse/QTBUG-54053
2017-02-23 07:50:37 +01:00
Florian Bruhin
91d3326a9e Show a warning when using private-browsing with QtWebKit-NG 2017-02-23 06:49:09 +01:00
Florian Bruhin
6004bfa72f Don't lose warnings shown in early init phases 2017-02-23 06:48:58 +01:00
Florian Bruhin
cd2c547b6b Don't show error if no autosave session exists 2017-02-22 23:17:59 +01:00
Florian Bruhin
c33544fbc9 Regenerate cheatsheet pngs 2017-02-22 17:14:37 +01:00
Daniel Fiser
81a24bdbef Fixed test of :session-save --only-active-window 2017-02-22 17:04:57 +01:00
Florian Bruhin
1dabd2b917 Fixes for cheatsheet
- Inkscape 96dpi changes
- Make a key light grey which is now used
- Fix lr -> gr typo
2017-02-22 16:53:40 +01:00
Daniel Fiser
76bb11c6aa Added test for :session-save --only-active-window 2017-02-22 14:16:46 +01:00
Daniel Fiser
6e1ac8be78 Fixed indentation of SessionManager.save() arguments. 2017-02-22 10:37:55 +01:00
Daniel Fiser
bb5825e043 session-save: in case of --only-active-window, the win-id is determined in session_save(). 2017-02-22 10:22:30 +01:00
Daniel Fiser
bb74b2703f session-save: doc generated from docstring. 2017-02-22 09:59:29 +01:00
Florian Bruhin
f952da16be Merge branch 'kiryl-pac+file' 2017-02-22 07:42:57 +01:00
Florian Bruhin
a32f57b705 Update docs 2017-02-22 07:42:45 +01:00
Florian Bruhin
5379138c17 Merge branch 'pac+file' of https://github.com/kiryl/qutebrowser into kiryl-pac+file 2017-02-22 07:35:06 +01:00
Florian Bruhin
e8443241df Allow input -> mouse-zoom-divider to be 0 2017-02-22 05:15:57 +01:00
Florian Bruhin
77f475991d tests: Ignore CreatePlatformSocket() errors 2017-02-21 20:52:46 +01:00
Florian Bruhin
5a87c9b6cb Re-add missing import 2017-02-21 19:44:15 +01:00
Florian Bruhin
b69d66e437 Actually check for Qt 5.7.1 2017-02-21 19:28:22 +01:00
Florian Bruhin
71f7b01ea7 Bring back PyQt (but not Qt) 5.7.0 support with QtWebEngine
This was originally removed in a86170f45, however Debian testing (Stretch) comes
with Qt 5.7.1, but PyQt 5.7.
2017-02-21 19:25:18 +01:00
Florian Bruhin
a179d6a738 Improve earlyinit Qt/PyQt version messages 2017-02-21 19:15:22 +01:00
Kirill A. Shutemov
ac3c8bb319 pac_utils.js: remove excessive escaping
Looks like the implementation was derived from Mozilla's
nsProxyAutoConfig.js, which is evaluated twice. It requires double
escaping.

In our case excessive escaping is harmful.

In particular it makes ip-matching regexp in isInNet() invalid and makes
it really slow as we go to dnsResolve() all the time, even when it's not
needed.

Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
2017-02-21 15:23:27 +03:00
Imran Sobir
7cb384aaf3 Update qute:bookmarks design. 2017-02-21 16:02:03 +05:00
Kirill A. Shutemov
de088c18b9 Allow pac+file proxy scheme to load PAC file from local filesystem
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
2017-02-21 12:57:18 +03:00
Kirill A. Shutemov
13213724b0 PAC: fix isPlainHostName()
Fix isPlainHostName() implementation and add test-case for it.

Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
2017-02-21 12:16:46 +03:00
Florian Bruhin
9b07a9f77f Update OS X install instructions
Fixes #2219
2017-02-21 08:11:11 +01:00
Florian Bruhin
25f217552c Remove unused import 2017-02-21 06:17:17 +01:00
Florian Bruhin
1708b38d7b Add SessionManager.{save,delete}_autosave 2017-02-20 07:43:41 +01:00
Florian Bruhin
2c03ad34ad Merge branch 'cosminadrianpopescu-session-autosave' 2017-02-20 06:46:26 +01:00
Florian Bruhin
1a1edf3c86 Update docs 2017-02-20 06:45:15 +01:00
Florian Bruhin
ee25e900f8 Add error handling for autosave session 2017-02-20 06:44:23 +01:00
Florian Bruhin
cafff3e1b6 Merge branch 'session-autosave' of https://github.com/cosminadrianpopescu/qutebrowser into cosminadrianpopescu-session-autosave 2017-02-20 06:30:34 +01:00
Florian Bruhin
2c87b4f979 Another try at frozen pytest_benchmark 2017-02-19 21:33:49 +01:00
Florian Bruhin
09371be081 Update authors 2017-02-19 20:54:12 +01:00
Florian Bruhin
7ae85b7628 Mention how to build the website in CONTRIBUTING 2017-02-19 20:53:19 +01:00
Julie Engel
65cfb4ecfe make paths relative 2017-02-19 20:50:16 +01:00
Florian Bruhin
eb4d699be3 Add missing click_target arg to _click_editable 2017-02-19 20:46:43 +01:00
Florian Bruhin
ecf6e02ead Merge branch 'EliteTK-navigate-fix' 2017-02-19 20:24:04 +01:00
Florian Bruhin
53ec3e8a43 Update docs 2017-02-19 20:23:54 +01:00
Florian Bruhin
389501deb9 Merge branch 'navigate-fix' of https://github.com/EliteTK/qutebrowser into EliteTK-navigate-fix 2017-02-19 20:22:27 +01:00
Florian Bruhin
a34bc929ac Fix handling of pytest-benchmark for frozen tests 2017-02-19 20:11:46 +01:00
Florian Bruhin
f772ccb203 QtWebEngine: Fall back to events for hints if JS is broken
*cough* musl *cough*
2017-02-19 20:03:27 +01:00
Florian Bruhin
a8b27eb271 Fix lint 2017-02-19 19:44:50 +01:00
Florian Bruhin
9a638b2dba Patch OS X .app to work with QtWebEngine 2017-02-19 15:41:20 +01:00
Florian Bruhin
5b4b226186 Add Qt library/data paths to version info 2017-02-19 14:02:40 +01:00
Tomasz Kramkowski
1fcba72958 tests navigate: Add tests for rel attributes with nofollow
Add two extra tests for checking navigation on pages with rel "next" and
"prev" links which are also rel "nofollow" to test for the correct
functionality of navigating pages with rel "next" and "prev" links with
multiple rel attributes.
2017-02-19 12:32:19 +00:00
Tomasz Kramkowski
5b7090e402 browser/navigate: _find_nextprev allow for space sep rel attribs
The _find_nextprev function of browser/navigate.py only checks to see if
the rell attribute equals 'prev', 'previous', or 'next'. This patch
changes this to check for a set intersection between {'prev',
'previous'} or {'next'} and the set of the space separated list of the
rel attribute.
2017-02-19 12:31:09 +00:00
Florian Bruhin
01db59ff36 Handle all uerscript errors when hinting with userscript-target 2017-02-19 13:15:15 +01:00
Florian Bruhin
00a8e79311 PyInstaller env: Remove link_pyqt call 2017-02-19 13:05:58 +01:00
Florian Bruhin
687f288453 Update PyInstaller env
We now use PyQt5 from PyPI and apply xoviat's patch for PyQt.
2017-02-19 12:58:58 +01:00
Florian Bruhin
0b94f2ed8c Fix pytest-benchmark package name 2017-02-18 00:46:55 +01:00
Florian Bruhin
4e74fff5e8 Test/lint fixes 2017-02-18 00:10:13 +01:00
Florian Bruhin
410b56447a Temporarily set JavascriptCanOpenWindows for hints
This partially reverts ba21fb3784.
Fixes #2311.
2017-02-17 22:08:46 +01:00
Florian Bruhin
399b02a367 Fix subtle issue in hint bdd tests
- We need to clean open tabs to avoid reusing target=_blank child tabs
- We don't check the active tab with target=_blank anymore
- Remove some weird :tab-close
2017-02-17 22:07:59 +01:00
Florian Bruhin
ac9b0e5c59 bdd: Allow checking open tabs without (active) 2017-02-17 22:07:23 +01:00
Florian Bruhin
6ac7e61e0e Add testcase for #2311 2017-02-17 21:32:40 +01:00
Florian Bruhin
a767e33f15 Re-add title setting code 2017-02-17 15:52:12 +01:00
Florian Bruhin
dcdfc116a4 Fix indent 2017-02-17 15:52:05 +01:00
Florian Bruhin
0deb422cfd Remove unused imports 2017-02-17 15:44:25 +01:00
Florian Bruhin
b5dd69f4a6 Add some logging for clicking 2017-02-17 15:43:25 +01:00
Florian Bruhin
006378923e Skip geolocation tests on Qt 5.8
https://bugreports.qt.io/browse/QTBUG-58985
2017-02-17 14:45:36 +01:00
Florian Bruhin
a86170f45d Drop PyQt < 5.7.1 support for QtWebEngine 2017-02-17 14:42:57 +01:00
Florian Bruhin
7a4a34c374 Fix WebEngineElement.click on Qt 5.6 2017-02-17 14:32:45 +01:00
Florian Bruhin
f718b66c48 Disable mhtml tests for Qt 5.6 2017-02-17 14:32:38 +01:00
Florian Bruhin
abded2470a Reenable PyQt 5.6 PyPI tests
To avoid segfaults we need to hardcode the sip version.
We also need to write a Qt.conf as it was missing with PyQt 5.6 and QtWebEngine
can't find its resources.
2017-02-17 12:00:16 +01:00
Florian Bruhin
79d22f2505 travis: Don't install libpython3.4-dev for PyPI PyQt 2017-02-17 07:02:57 +01:00
Florian Bruhin
7596409962 Add PyQt 5.8 PyPI test envs 2017-02-17 07:02:13 +01:00
Florian Bruhin
ba21fb3784 webengine: Use _click_href for hinting target=_blank links
Fixes #2311
2017-02-17 06:57:31 +01:00
Florian Bruhin
40e1337e03 Adjust WebEngineEleement _js_dict in remove_blank_target
Otherwise, when checking later if the element has target=_blank set, we still
think it is.

This is not perfect as remove_blank_target also removes it from sub-elements,
but it's a good start.
2017-02-17 06:56:12 +01:00
Florian Bruhin
3de2bfb277 Handle renderer process not starting at all 2017-02-13 11:23:29 +01:00
Florian Bruhin
2b76cca2b2 Improve earlyinit error messages 2017-02-12 21:19:58 +01:00
Florian Bruhin
7c701dc697 Disable coverage checks for webkitelem.py 2017-02-12 02:26:46 +01:00
Florian Bruhin
d60e365e3c Don't use _click_js for target=_blank links
Fixes #2311
2017-02-12 01:06:56 +01:00
Florian Bruhin
a4f04db848 Cap scroll count to 5000
Fixes #1694
2017-02-11 22:26:37 +01:00
Florian Bruhin
b73cda22de Fix lint 2017-02-11 21:17:16 +01:00
Florian Bruhin
bd8ead2279 Detect rel-attributes on <a> elements for :navigate 2017-02-11 20:48:48 +01:00
Florian Bruhin
760f016285 Merge branch 'imransobir-master' 2017-02-11 20:40:59 +01:00
Florian Bruhin
66cbb8aa31 Fix lint 2017-02-11 17:22:35 +01:00
Florian Bruhin
9c712929f5 Update docs 2017-02-11 17:08:09 +01:00
Florian Bruhin
b15ae97444 Get timestamp of curr_date instead of today 2017-02-11 17:06:51 +01:00
Florian Bruhin
c3153273f5 Merge branch 'master' of https://github.com/imransobir/qutebrowser into imransobir-master 2017-02-11 17:05:57 +01:00
Imran Sobir
37c3b79b9b Add :history command. 2017-02-10 17:47:20 +05:00
Florian Bruhin
46752a2c24 Add some performance improvements for qute:history 2017-02-10 11:39:08 +05:00
Florian Bruhin
f063d4be6f Add a benchmark for qute:history 2017-02-10 11:39:07 +05:00
Florian Bruhin
46c02bf5ae Refactor qute:history unittests 2017-02-10 11:39:07 +05:00
Florian Bruhin
6e85b73897 travis: Use archlinux-webengine image for QtWebEngine 2017-02-09 23:58:06 +01:00
Florian Bruhin
98e1603abb Don't make SSL resolve errors fail tests 2017-02-09 15:19:26 +01:00
Imran Sobir
9001ec079c Align history time to the right. 2017-02-09 18:37:33 +05:00
Imran Sobir
100f90d9b3 Fix pylint errors. 2017-02-09 18:28:10 +05:00
Imran Sobir
d21585f603 Add rel=prev, rel=next to pagination links. 2017-02-09 18:11:17 +05:00
Florian Bruhin
ccf4966eac travis: Re-add accidentally removed PyPI PyQt builds 2017-02-09 13:43:16 +01:00
Florian Bruhin
97982df1cb Adjust history unittest 2017-02-09 13:40:44 +01:00
Florian Bruhin
85d8d45e19 Ask for confirmation with :history-clear 2017-02-09 13:20:00 +01:00
Imran Sobir
a15aa9eade Hide next links to future. 2017-02-09 17:18:57 +05:00
Imran Sobir
920fb81377 Use pytest's tmpdir fixture. 2017-02-09 16:39:21 +05:00
Imran Sobir
49271b7ce1 Generate and cleanup fake web-history in own fixture. 2017-02-09 16:32:59 +05:00
Imran Sobir
4eccfd5396 Style fixes. 2017-02-09 15:51:00 +05:00
Imran Sobir
828b0c00b5 Rename test_qutehistory.py to test_qutescheme.py. 2017-02-09 15:39:50 +05:00
Florian Bruhin
92c3ec6435 Remove PyPI envs from .appveyor.yml too 2017-02-09 01:57:23 +01:00
Florian Bruhin
c0c636c3eb Revert OS X / Windows changes for PyPI packages 2017-02-09 00:50:38 +01:00
Florian Bruhin
601110761d Fix test_history.test_init without QtWebKIt 2017-02-09 00:50:38 +01:00
Florian Bruhin
16ecc043f7 Run unittests with QUTE_BDD_WEBENGINE 2017-02-09 00:50:38 +01:00
Florian Bruhin
4506575638 Try PyPI envs on Appveyor 2017-02-09 00:50:38 +01:00
Florian Bruhin
314ba53014 travis: Don't run check_pyqt on OS X for PyPI jobs 2017-02-09 00:50:37 +01:00
Florian Bruhin
5d2b32956b travis: Install geoclue for PyPI tests 2017-02-09 00:50:37 +01:00
Florian Bruhin
cb704f149a Remove py35-pyqt56 on Travis
It just segfaults, even locally...
2017-02-09 00:50:37 +01:00
Florian Bruhin
708c96f3ce Fix handling of @qt>= BDD tags 2017-02-09 00:50:37 +01:00
Florian Bruhin
0d271eba87 Mark tests using special URLs as Qt >= 5.8 2017-02-09 00:50:37 +01:00
Florian Bruhin
a3caba53d5 Allow single-dot version tags in BDD tests 2017-02-09 00:50:37 +01:00
Florian Bruhin
01719408bc Update CONTRIBUTING 2017-02-09 00:50:37 +01:00
Florian Bruhin
00c743b3e8 Relax complex mhtml check for QtWebEngine
Turns out the output differs between QtWebEngine versions, probably because it
dumps its parsed files. Let's just do a sanity check for the complex file
instead.
2017-02-09 00:50:37 +01:00
Florian Bruhin
8779a1367e Fix test collection without QtWebKit 2017-02-09 00:50:37 +01:00
Florian Bruhin
ce3e24163e Add test environments using PyQt from PyPI
Fixes #2083
2017-02-09 00:50:37 +01:00
Florian Bruhin
038a517c5a Add test for QtWebKit-NG in test_version 2017-02-08 23:46:37 +01:00
Florian Bruhin
859974fa99 Don't crash without hint context in HintManager._start_cb 2017-02-08 22:49:25 +01:00
Florian Bruhin
b5ab3adc8c Fix sip.assign check 2017-02-08 22:27:49 +01:00
Florian Bruhin
0897e8e5ad Add pdfjs path for pdf.js in AUR 2017-02-08 22:17:34 +01:00
Florian Bruhin
3adcfddfff Handle LookupError when reading adblock zips 2017-02-08 22:17:30 +01:00
Florian Bruhin
4d08dc5ddb Point out QtWebKit-NG in version info 2017-02-08 18:34:50 +01:00
Florian Bruhin
df35c9138b Filter out uninteresting elements early in TabBarStyle
Otherwise we call _tab_layout on something which is not a QStyleOptionTab, which
might cause AttributeErrors. In a crash report I couldn't reproduce, it got
called with a QStyleOptionMenuItem when right-clicking on the page.
2017-02-08 16:53:03 +01:00
Florian Bruhin
af40439f4a tests: Ignore more QPainter::end warnings 2017-02-08 15:27:45 +01:00
Florian Bruhin
ac2fd4a36f Skip special URL tests with QtWebKit 2017-02-08 13:04:38 +01:00
Florian Bruhin
36e2cc9628 Fix broken "if" when closing tab.
Combining the "add_undo" with "tab.url().isValid()" was a mistake as the "else"
meant something else then...
2017-02-08 12:45:09 +01:00
Imran Sobir
0ab7fd4581 Restore original save-manager, web-history at end of test. 2017-02-08 16:18:33 +05:00
Florian Bruhin
6ae7960d9a Fix lint 2017-02-08 12:14:24 +01:00
Florian Bruhin
2501eed5f5 Re-add tab.deleteLater() call
This got removed in 1af951fd62 but
tab.layout().unwrap() only deletes the underlying widget, not the tab itself.
2017-02-08 12:12:36 +01:00
Florian Bruhin
0130866e89 Only do mhtml import in DownloadManager.get_mhtml
We also import qtnetworkdownloads on QtWebEngine without QtWebKit available, so
we can't be sure we can import mhtml.
2017-02-08 12:03:32 +01:00
Florian Bruhin
8226afd167 Hide more SSL warnings 2017-02-08 12:01:30 +01:00
Florian Bruhin
7c08444c37 Refuse to serialize chrome:// and view-source:// tabs
Fixes #2289
2017-02-08 11:40:00 +01:00
Florian Bruhin
580648da32 Allow to open chrome:// URLs in BDD tests 2017-02-08 11:32:14 +01:00
Florian Bruhin
1af951fd62 Work around crashes when opening URL after renderer crash
Fixes #2290
2017-02-08 10:56:44 +01:00
Florian Bruhin
2469d01ce7 Add renderer_process_terminated signal to tab API 2017-02-08 10:55:05 +01:00
Florian Bruhin
2227c037f0 Log ignored lines in end2end tests 2017-02-08 09:45:12 +01:00
Florian Bruhin
208ee04bdc Add simple tests for QtWebEngine renderer crash/kill 2017-02-08 09:41:55 +01:00
Imran Sobir
ec0e95969e Add unit tests for qute://history. 2017-02-08 13:28:04 +05:00
Florian Bruhin
87d1a2c7a3 Fix lint 2017-02-08 09:14:54 +01:00
Florian Bruhin
12ed226ce6 Set COLUM_WIDTHS for :help completion
Fixes #2287
2017-02-08 09:11:58 +01:00
Florian Bruhin
c4a74c7a34 Make sure completion column widths never get negative
I discovered this because of #2287 but it doesn't actually change anything
there. When we don't have a third column, subtract the scrollbar width from the
second one.
2017-02-08 09:10:40 +01:00
Florian Bruhin
ccb6594e07 Ignore QPainter warning in tests
This happens on Debian Jessie from time to time.
2017-02-08 00:58:41 +01:00
Florian Bruhin
02198c4f65 Also check for QtWebKitWidgets in earlyinit 2017-02-08 00:57:47 +01:00
Florian Bruhin
8b9b49f180 Fix message on renderer process crash 2017-02-08 00:41:17 +01:00
Florian Bruhin
7bb8c854bf tests: Make user-agent download hinting more reliable 2017-02-07 23:33:37 +01:00
Florian Bruhin
c198f3a6a3 Adjust descriptions and dependencies
See #1571
2017-02-07 23:27:44 +01:00
Florian Bruhin
4b79280ade tests: Use number hint mode to select download
Other screen sizes will give us other letter hints.
2017-02-07 23:23:59 +01:00
Florian Bruhin
ed67f93d2a Fix spelling 2017-02-07 22:27:50 +01:00
Florian Bruhin
bdcd980572 Fix bdd "Then" collision 2017-02-07 22:27:32 +01:00
Florian Bruhin
3f1433dcf7 Merge branch 'webengine-mhtml' 2017-02-07 22:24:25 +01:00
Florian Bruhin
5981bdbedb Skip test failing on Travis
See #2288
2017-02-07 22:23:55 +01:00
Florian Bruhin
eb7064d083 Fix lint 2017-02-07 22:13:33 +01:00
Florian Bruhin
d13809089f Exclude socket notifier events during prompts
This helps with segfaults while the prompt is shown, like those which happened
during mhtml downloads with QtWebEngine.
2017-02-07 22:13:33 +01:00
Florian Bruhin
7aa0e900d7 Add mhtml support for QtWebEngine 2017-02-07 22:13:33 +01:00
Florian Bruhin
bae1f41599 Set user-agent for QtWebKit downloads
See #513
2017-02-07 22:00:03 +01:00
Imran Sobir
9a218256b7 Fix pylint complaints. 2017-02-07 19:25:01 +05:00
Imran Sobir
216cef8d9f Add basic end-to-end test for qute:history. 2017-02-07 16:18:00 +05:00
Imran Sobir
2c40be31a2 Prevent crash if invalid date is passed to qute:history. 2017-02-07 16:15:10 +05:00
Imran Sobir
be12b4cccf Use history item's url as title if no title. 2017-02-07 16:06:19 +05:00
Daniel Fiser
c092840c04 Add optional argument --only-active-window to :session-save.
The new optional argument --only-active-window makes :session-save to
save only the tabs in the currently active window.
2017-02-07 10:38:41 +01:00
Imran Sobir
f5e75ff870 Misc qute_history() fixes. 2017-02-07 11:56:51 +05:00
Imran Sobir
46a34a99f3 Use QUrlQuery to parse qute://history queries. 2017-02-07 11:22:04 +05:00
Florian Bruhin
e487fe441e Revert "Add a workaround to save cookies on exit"
This causes sqlite cookie errors from Chromium on shutdown...

See #2263
This reverts commit 8d55d093f2.
2017-02-06 22:16:39 +01:00
Florian Bruhin
2b6b18d7bf Fix lint 2017-02-06 21:33:08 +01:00
Florian Bruhin
df245dae48 Add support for general -> print-element-backgrounds with WebEngine 2017-02-06 21:08:32 +01:00
Florian Bruhin
a40db1735e Update QtWebEngine settings todo 2017-02-06 21:01:19 +01:00
Florian Bruhin
811bb84587 Clarify site-specific-quirks setting value 2017-02-06 20:43:25 +01:00
Florian Bruhin
8d55d093f2 Add a workaround to save cookies on exit
Fixes #2263
2017-02-06 20:43:23 +01:00
Florian Bruhin
b8b4611b4d Enable errors on renderer process crashes 2017-02-06 20:43:03 +01:00
Imran Sobir
748ec7e7a1 Add history page. 2017-02-07 00:04:32 +05:00
Florian Bruhin
52e3865367 Add support for the colors -> webpage.bg option with QtWebEngine 2017-02-06 17:18:36 +01:00
Florian Bruhin
29ffa3d134 Add a fullscreen notification overlay
From the spec:

  User agents should ensure, e.g. by means of an overlay, that the end user is
  aware something is displayed fullscreen. User agents should provide a means of
  exiting fullscreen that always works and advertise this to the user. This is
  to prevent a site from spoofing the end user by recreating the user agent or
  even operating system environment when fullscreen.

https://fullscreen.spec.whatwg.org/#security-and-privacy-considerations
2017-02-06 16:22:58 +01:00
Florian Bruhin
39508d984e Handle multiple commands in KeyConfigParser.get_reverse_bindings_for 2017-02-06 16:22:58 +01:00
Florian Bruhin
98e6ccf548 Add fullscreen support for QtWebEngine 2017-02-06 16:22:58 +01:00
Florian Bruhin
1209724f83 Fix lint 2017-02-06 13:42:31 +01:00
Florian Bruhin
dd9d6264c7 Fix search/replace fail 2017-02-06 13:09:39 +01:00
Florian Bruhin
89108be013 Clean up printing code in browser.commands 2017-02-06 12:54:13 +01:00
Florian Bruhin
c8913cbdc4 Fix QtWebEngine PDF printing 2017-02-06 12:49:02 +01:00
Florian Bruhin
69d8b23923 Fix test_unused 2017-02-06 12:47:27 +01:00
Florian Bruhin
4518afbde2 Add support for storage -> cache-size with QtWebEngine 2017-02-06 12:46:28 +01:00
Florian Bruhin
bd0b62ab80 Add support for content -> cookies-store with QtWebEngine 2017-02-06 10:47:03 +01:00
Florian Bruhin
4104056950 Split profile related stuff to webenginesettings._init_profile 2017-02-06 10:46:37 +01:00
Florian Bruhin
b1894ed7e0 Add a utils.unused() 2017-02-06 10:45:36 +01:00
Florian Bruhin
e65b70ba37 Update changelog 2017-02-06 09:52:41 +01:00
Florian Bruhin
2f4c185da0 Implement printing with QtWebEngine 2017-02-06 09:51:11 +01:00
Florian Bruhin
9a9fa3ab41 Merge branch 'webkit-ng-history' 2017-02-06 08:49:09 +01:00
Florian Bruhin
165c534f20 Update changelog 2017-02-06 08:48:58 +01:00
Florian Bruhin
4ee207b3cb Remove webkit.tabhistory from check_coverage
We can't easily check for both QtWebKit and -NG code in the same run.
2017-02-06 08:48:08 +01:00
Florian Bruhin
91bdc00410 Make tests work with QtWebKit-NG
Fixes #1571
2017-02-06 08:48:08 +01:00
Florian Bruhin
f0f97a5213 Add QtWebKit-NG test job to Travis 2017-02-06 08:48:08 +01:00
Florian Bruhin
99d1636878 Properly implement session support for QtWebKit-NG
See #1571
2017-02-06 08:48:08 +01:00
Florian Bruhin
dfbcb75313 First prototype of QtWebKit-NG history/session support 2017-02-06 08:48:08 +01:00
Florian Bruhin
348a50ad69 Fix inserting text with QtWebEngine
The insertText event doesn't seem to be available with newer Chromium releases,
which means this broke (probably with Qt 5.7.1).

Fixes #2183
Fixes #2217
2017-02-06 08:06:58 +01:00
Florian Bruhin
5e58764326 Fix lint 2017-02-05 19:52:59 +01:00
Florian Bruhin
129c1a0b1a Add missing comma 2017-02-05 19:09:31 +01:00
Florian Bruhin
3f332d3871 Remove @pyqtSlot annotation which breaks with LibreSSL
Fixes #2213
2017-02-05 19:08:44 +01:00
Florian Bruhin
84a8d395e3 Update changelog 2017-02-05 19:07:54 +01:00
Florian Bruhin
57793fb6d6 Handle hint keypress without a context.
Fixes #2098
2017-02-05 18:53:58 +01:00
Florian Bruhin
9b843f24eb Re-enable segfault reports for QtWebEngine
Fixes #2174
2017-02-05 18:50:17 +01:00
Florian Bruhin
2193551035 Simplify test_insert_mode
We already check whether insert mode was entered by listening for "contents: *",
and the copying part is unstable with QtWebEngine.
2017-02-05 18:44:39 +01:00
Florian Bruhin
f3b39c55a0 Fix lint 2017-02-05 18:42:34 +01:00
Florian Bruhin
2de0904b07 Fix lint 2017-02-05 17:21:33 +01:00
Florian Bruhin
bcfa84e9f1 Remove QtWebEngine auth test
This now acts differently depending on whether we have sip.assign or not, so
let's just drop this for simplicity.
2017-02-05 17:20:24 +01:00
Florian Bruhin
a5c68babc1 Add backend to version output 2017-02-05 17:16:47 +01:00
Florian Bruhin
b1a95a3930 Add automatic backend selection in earlyinit 2017-02-05 17:09:04 +01:00
Florian Bruhin
7fe86b196d Add missing import 2017-02-05 14:24:10 +01:00
Florian Bruhin
8c30e57356 Fix configtypes.py coverage 2017-02-05 14:22:21 +01:00
Florian Bruhin
febfa00dd5 travis: Use --no-xvfb on OS X 2017-02-05 12:58:37 +01:00
Florian Bruhin
a62062af27 Relax font validation in the config
Fixes #2256
2017-02-05 12:51:49 +01:00
Florian Bruhin
112e4a1dad Use sip.assign for QAuthenticator if available
Fixes #2171
2017-02-05 12:39:28 +01:00
Florian Bruhin
b40a1bfb83 Disable percent-decoding for QtWebEngine with Qt >= 5.8.1 2017-02-05 12:33:40 +01:00
Florian Bruhin
b3ffd9a63d Fix Appveyor badge
[ci skip]
2017-02-05 10:40:50 +01:00
Florian Bruhin
77f6b14db8 Fix doc generation for network -> proxy 2017-02-05 01:48:41 +01:00
Florian Bruhin
b9dece8d74 flake8: Ignore E722 2017-02-05 01:45:23 +01:00
Florian Bruhin
ae54648be8 Update get_coredumpctl_traces for newer Python versions 2017-02-05 01:43:17 +01:00
Florian Bruhin
fbde42b5fd Use Python 3.6 on OS X 2017-02-05 01:42:44 +01:00
Florian Bruhin
89f95be5e5 Various requirements updates 2017-02-05 01:30:39 +01:00
Florian Bruhin
8afc215c3d Update recompile_requirements for newer pips
pip now depends on (instead of vendoring) its dependencies, so we needed some
updates there to only install the affected packages once.

Fixes #2255
2017-02-05 01:29:21 +01:00
Florian Bruhin
288c484cdf Fix mhtml file 2017-02-05 00:29:54 +01:00
Florian Bruhin
4cf974796e Replace remaining mentions of The-Compiler/qutebrowser 2017-02-05 00:14:50 +01:00
Florian Bruhin
de50f30b9b Replace all GitHub links 2017-02-05 00:13:11 +01:00
Florian Bruhin
ba5ac6139a Update docs 2017-02-05 00:09:18 +01:00
Florian Bruhin
c4ba3fc93a Merge branch 'lucc-docs' 2017-02-05 00:08:07 +01:00
Florian Bruhin
0a0aa57754 Merge branch 'docs' of https://github.com/lucc/qutebrowser into lucc-docs 2017-02-05 00:07:36 +01:00
Florian Bruhin
cc2b085443 Uppercase word-hints with hints -> uppercase
Fixes #2278
2017-02-04 23:45:00 +01:00
Florian Bruhin
021b3645cc Don't stack zoom level messages
Fixes #1980
2017-02-04 23:42:55 +01:00
Florian Bruhin
2c46f8ecdb Fix zoom handling with QtWebKit 2017-02-04 23:30:12 +01:00
Lucas Hoffmann
92198f668b Update autogenerated files 2017-02-04 22:32:34 +01:00
Lucas Hoffmann
d874f68463 docs: Clarify hints.mode = number 2017-02-04 22:31:52 +01:00
Lucas Hoffmann
378e4f1bdd docs: Clarify behaviour of view-source 2017-02-04 22:31:52 +01:00
Florian Bruhin
385969e05f Fix editor.feature with QtWebEngine 2017-02-04 22:16:22 +01:00
Florian Bruhin
e8bbc1adf8 QtWebEngine: Fix insert mode checks with zoom
Fixes #2169
2017-02-04 22:12:41 +01:00
Florian Bruhin
6f0c8245e0 Fix test_insert_mode with QtWebEngine
We can't pretend to enter caret mode now
2017-02-04 22:06:35 +01:00
Florian Bruhin
f99bf661cc Fix lint 2017-02-04 21:59:39 +01:00
Florian Bruhin
d3f359e490 Disallow caret mode with QtWebEngine 2017-02-04 21:43:32 +01:00
Florian Bruhin
fd29528e4f Add proxy support for QtWebEngine with Qt >= 5.8
See #666
Fixes #2082
2017-02-04 21:39:22 +01:00
Florian Bruhin
b6e31d4172 Fix parametrizing 2017-02-04 19:03:59 +01:00
Florian Bruhin
b9ddea0e7a Merge branch 'rsteube-master' 2017-02-04 18:54:56 +01:00
Florian Bruhin
fb189f2539 Update docs 2017-02-04 18:53:02 +01:00
Florian Bruhin
f9c795b779 Merge branch 'master' of https://github.com/rsteube/qutebrowser into rsteube-master 2017-02-04 18:52:10 +01:00
Florian Bruhin
876414565c Merge branch 'Kingdread-issue-2204' 2017-02-04 18:43:00 +01:00
Florian Bruhin
7b0f4e0812 Use mock for open_file tests 2017-02-04 18:41:22 +01:00
Florian Bruhin
1f170b8746 Update changelog 2017-02-04 18:35:14 +01:00
Florian Bruhin
e01ac4c41f Merge branch 'issue-2204' of https://github.com/Kingdread/qutebrowser into Kingdread-issue-2204 2017-02-04 18:34:51 +01:00
Florian Bruhin
460389c30d Simplify some utilcmds tests 2017-02-04 18:26:12 +01:00
Florian Bruhin
21d2d04f45 Merge branch 'abbradar-more-pac' 2017-02-04 18:12:29 +01:00
Florian Bruhin
662859c133 Remove unnecessary inheritance on Python 3 2017-02-04 18:10:57 +01:00
Florian Bruhin
0cc7f845e6 Simplify test 2017-02-04 18:10:34 +01:00
Florian Bruhin
660e3915a1 Update docs 2017-02-04 18:08:53 +01:00
Florian Bruhin
4c14b2983b Merge branch 'more-pac' of https://github.com/abbradar/qutebrowser into abbradar-more-pac 2017-02-04 18:07:45 +01:00
Florian Bruhin
eb652b740a Merge branch 'Akselmo-patch-1' 2017-02-04 18:04:30 +01:00
Florian Bruhin
2792503010 Update authors 2017-02-04 18:04:23 +01:00
Florian Bruhin
eda4db475c Merge branch 'patch-1' of https://github.com/Akselmo/qutebrowser into Akselmo-patch-1 2017-02-04 18:04:12 +01:00
Florian Bruhin
bc20ae9efe Merge branch 'blyxxyz-ignore-invalid-register-keys' 2017-02-04 18:02:03 +01:00
Florian Bruhin
10ec240de1 Update changelog 2017-02-04 18:01:22 +01:00
Florian Bruhin
007065b63c Merge branch 'ignore-invalid-register-keys' of https://github.com/blyxxyz/qutebrowser into blyxxyz-ignore-invalid-register-keys 2017-02-04 17:55:07 +01:00
Florian Bruhin
f4989a3bb3 Merge branch 'blyxxyz-enter-mode-blacklist' 2017-02-04 17:53:03 +01:00
Florian Bruhin
97feef03fd Update changelog 2017-02-04 17:52:50 +01:00
Florian Bruhin
8cdf2f61c7 Merge branch 'enter-mode-blacklist' of https://github.com/blyxxyz/qutebrowser into blyxxyz-enter-mode-blacklist 2017-02-04 17:52:16 +01:00
Florian Bruhin
b988c9d1cb Merge branch 'blyxxyz-strip-mailto' 2017-02-04 17:49:41 +01:00
Florian Bruhin
1144060ab9 Update docs 2017-02-04 17:49:31 +01:00
Florian Bruhin
c1f2f0ac06 Merge branch 'strip-mailto' of https://github.com/blyxxyz/qutebrowser into blyxxyz-strip-mailto 2017-02-04 17:48:53 +01:00
Florian Bruhin
75eb547b3b Merge branch 'pkill-nine-upstream-master-cmdlinetext_userscript' 2017-02-04 17:43:58 +01:00
Florian Bruhin
22873f829c Update docs 2017-02-04 17:43:45 +01:00
Florian Bruhin
3e6fd27afd Merge branch 'upstream-master-cmdlinetext_userscript' of https://github.com/pkill-nine/qutebrowser into pkill-nine-upstream-master-cmdlinetext_userscript 2017-02-04 17:42:51 +01:00
Florian Bruhin
148b34a50b Fix remaining Qt 5.8 QtWebEngine test failures 2017-02-04 13:28:38 +01:00
Florian Bruhin
987cb236e8 Revert changes to WebEngineView.createWindow
We still need those to open tabs in the background when middle-clicked.

This was a regression introduced in 545539f28d.
Fixes #2276.
2017-02-04 11:52:59 +01:00
Florian Bruhin
6cd4105ea1 Fix long line 2017-02-04 00:11:48 +01:00
Florian Bruhin
66719c5ecc Fix lint 2017-02-03 23:55:14 +01:00
Florian Bruhin
7d1316fe03 Remove webelem.py from coverage check
These tests need a bigger overhaul to work with QtWebEngine and use actual web
elements.
2017-02-03 23:46:44 +01:00
Florian Bruhin
20f83316e0 Fix misc.feature with QtWebEngine
We need to make sure we don't leave any stale prompts open.
2017-02-03 23:41:33 +01:00
Florian Bruhin
1f7e9e6b59 Add a testcase for #1613 2017-02-03 23:32:56 +01:00
Florian Bruhin
4cf7a3d1f4 Update changelog
[ci skip]
2017-02-03 23:21:57 +01:00
Florian Bruhin
545539f28d Do more sophisticated clicking for hints with QtWebEngine
We now use click() or focus() in JS if possible, or manually follow links in a
href attribute.

While this probably introduces some new corner cases, it fixes a handful of
older ones:

- window.open() in JS can now be handled correctly as we don't need hacks in
  createWindow anymore.
- Focusing input fields with images now works - fixes #1613, #1879
- Hinting now works better on QtWebEngine with Qt 5.8 - fixes #2273

Also see #70.
2017-02-03 23:21:57 +01:00
Florian Bruhin
ba2f4fb1b9 Use event_target to filter out mouse events
Fixes #2262
2017-02-01 13:08:11 +01:00
Florian Bruhin
e5176e18bd tests: Fix QtWebEngine focus checking 2017-02-01 12:33:47 +01:00
Florian Bruhin
428e495935 Unconditionally disable test_tab
This now also causes segfaults with Qt 5.8, so something is definitely wrong
here...

See #1638 and #2261
2017-02-01 11:09:08 +01:00
pkill9
8ad28719ab Add "QUTE_COMMANDLINE_TEXT" environment variable for userscripts.
- Added "QUTE_COMMANDLINE_TEXT" environment variable for userscripts.
 - Updated documentation to include "QUTE_COMMANDLINE_TEXT" environment
variable for userscripts.
2017-02-01 09:29:05 +00:00
Florian Bruhin
72bdf69fe3 Fix long line 2017-02-01 09:51:50 +01:00
Florian Bruhin
bb46c01c50 Clear search text before closing QtWebEngine tab
See https://bugreports.qt.io/browse/QTBUG-58563 and #2261
2017-02-01 09:30:53 +01:00
Florian Bruhin
90f472bf59 Temporary fix for Qt 5.8 segfaults
See #2261
2017-01-29 22:56:53 +01:00
Florian Bruhin
95aeb86328 Update pdfjs version parsing
Fixes #2254
2017-01-27 09:19:10 +01:00
Florian Bruhin
0863c3277c Revert "Disable WebGL for tests"
This reverts commit 2934ffd4d9.
2017-01-25 08:45:18 +01:00
Florian Bruhin
7304db916c freeze.py: Remove pkg_resources._vendor packages
See https://github.com/pypa/setuptools/pull/933
2017-01-25 08:05:40 +01:00
Florian Bruhin
2934ffd4d9 Disable WebGL for tests
See #2250
2017-01-25 08:04:58 +01:00
Florian Bruhin
2a773a2c55 Enable WebGL by default 2017-01-24 23:55:12 +01:00
Florian Bruhin
43ae66dba4 freeze_tests: Add queue module for cheroot 2017-01-23 09:22:50 +01:00
Florian Bruhin
d9808aefed Switch from CherryPy to cheroot, take 2
This reverts commit 3584eabd6f.
This reverts commit 37dc99c26f.
2017-01-23 07:38:24 +01:00
Florian Bruhin
25ddbdb57c requirements: Update Pygments to 2.2.0 2017-01-22 23:28:29 +01:00
Florian Bruhin
a3c605fe54 pytest requirements: Update pytest to 3.0.6 2017-01-22 22:23:20 +01:00
Florian Bruhin
1a04e554fc pylint requirements: Update pylint to 1.6.5 2017-01-22 22:22:14 +01:00
Jan Verbeek
9845cbbd81 Remove mailto: scheme properly 2017-01-21 23:19:15 +01:00
Jan Verbeek
2700739a3a Strip mailto: when yanking a hint
Resolves #61.
2017-01-21 14:43:50 +01:00
Jan Verbeek
bd3c2f92fc Blacklist some modes for :enter-mode
This disallows using :enter-mode with modes that don't work properly
when entered that way. Fixes #1137.
2017-01-20 19:32:16 +01:00
Jan Verbeek
7e7cac2d48 Ignore non-register keys
Ignore all keys with an empty .text() return value, not just modifier
keys. You can still use unusual things like ß for registers, but
XF86WakeUp is out. Fixes #2125.
2017-01-20 17:34:33 +01:00
Florian Bruhin
3584eabd6f requirements: Filter CherryPy 9.0.0 2017-01-20 09:11:56 +01:00
Florian Bruhin
37dc99c26f Revert "Switch from CherryPy to cheroot"
This reverts commit 1ab2b3af83.

See https://github.com/cherrypy/cheroot/pull/2
2017-01-20 09:06:49 +01:00
Florian Bruhin
1ab2b3af83 Switch from CherryPy to cheroot
The WSGIServer got split off from CherryPy in a separate project
2017-01-20 08:07:55 +01:00
Florian Bruhin
79ef728af1 requirements: Update requests to 2.12.5 2017-01-18 15:07:47 +01:00
Florian Bruhin
8922fd68d0 requirements: Update coverage to 4.3.4 2017-01-18 08:51:57 +01:00
Florian Bruhin
b74bae2200 Hopefully fix download test on Windows 2017-01-18 08:51:03 +01:00
Florian Bruhin
b47f90d24f Really fix Python 3.6 deprecation warnings
Before, the module regexes didn't actually work properly, but we thought the
warnings were gone as they only were shown once because of __pycache__.

Now we instead don't filter by module, but simply hide those messages globally
during the earlyinit dependency import (which is the first import).
2017-01-18 08:40:57 +01:00
Florian Bruhin
d9389ff0a7 Various requirements updates 2017-01-17 08:31:23 +01:00
Cosmin Popescu
80372eb3f2 stop using the commands handler 2017-01-13 18:57:55 +01:00
Florian Bruhin
04dddc2475 Fix backslash escape 2017-01-13 18:25:34 +01:00
Florian Bruhin
22fb3c3042 tox: Switch to Python 3.6 2017-01-13 18:25:26 +01:00
Florian Bruhin
73f371a956 Release v0.9.1 2017-01-13 18:10:03 +01:00
Florian Bruhin
e887825aaa Update changelog 2017-01-13 18:07:56 +01:00
Florian Bruhin
cc4a8e53df Prevent using %2F as slash in a Content-Disposition header 2017-01-13 18:04:04 +01:00
Florian Bruhin
2f3e671578 Use a tmpdir subdir for download BDD tests 2017-01-13 17:59:03 +01:00
Daniel Schadt
07460832b6 fix open-file tests on windows
Windows filenames have backslashes, so we need to escape them, otherwise
shlex.split will delete them.

Also, we can't prodive our own executable on frozen tests.
2017-01-12 15:38:38 +01:00
Akselmo
db0ac07c15 Explanation about quickmarks and bookmarks to FAQ
I was too confused about what was the difference between quickmarks and bookmarks #2226 but I think I figured it out. Here's my proposal for the FAQ.

Now please bear with me if I'm doing something wrong, I'm new to Github and still learning things.
2017-01-11 20:12:42 +02:00
Daniel Schadt
ea56ded7fc fix TestOpenFile
pytest doesn't like test classes which define __init__, and pylint
doesn't like attributes defined outside __init__.

We can disable pylint's check, but we can't force pytest to accept our
test class...
2017-01-10 14:14:03 +01:00
Florian Bruhin
5ede2c6417 requirements: Update jinja to 2.9.4 2017-01-10 10:32:30 +01:00
Florian Bruhin
2b48ee14c4 test requirements: Update CherryPy to 8.8.0 2017-01-10 10:30:26 +01:00
Florian Bruhin
7711e07b0c flake8 requirements: Update pyflakes to 1.5.0 2017-01-10 10:29:01 +01:00
Florian Bruhin
2d364f43cf Ignore Python 3.6 warnings in dependencies 2017-01-08 22:38:54 +01:00
Florian Bruhin
2127fd2432 requirements: Update jinja2 to 2.9.2 2017-01-08 15:39:21 +01:00
Florian Bruhin
61e598552e eslint: Turn off prefer-destructuring 2017-01-08 15:36:51 +01:00
Florian Bruhin
a10a6bdfa2 Merge branch 'kevinwang-clear-keychain' 2017-01-07 21:29:45 +01:00
Florian Bruhin
90b17610ea Update authors 2017-01-07 21:29:37 +01:00
Florian Bruhin
420897eaf1 Merge branch 'clear-keychain' of https://github.com/kevinwang/qutebrowser into kevinwang-clear-keychain 2017-01-07 21:29:29 +01:00
Florian Bruhin
16c8c1b189 Document how webelem.js works 2017-01-07 12:21:22 +01:00
Kevin Wang
3a1ecad1f3 Clear keychain on <Ctrl-[> in addition to <Escape>. 2017-01-07 00:45:06 -05:00
Florian Bruhin
dd7b16c8c3 test requirements: Update click to 6.7 2017-01-06 23:54:15 +01:00
Daniel Schadt
bb135a00e6 fix lint 2017-01-06 13:53:05 +01:00
Daniel Schadt
2986f7b615 add tests for utils.open_file 2017-01-06 13:32:46 +01:00
Daniel Schadt
536c76848e add a test for opening mhtml downloads 2017-01-05 19:02:28 +01:00
Florian Bruhin
fa539acd79 test/vulture reqs: Update vulture to 0.12 2017-01-05 13:35:12 +01:00
Daniel Schadt
bd5274af5a fix tests 2017-01-04 17:59:53 +01:00
Daniel Schadt
69001111da actually use DownloadTarget for :download -m /path 2017-01-04 16:32:25 +01:00
Daniel Schadt
6497bb5ace break cicular imports in utils 2017-01-04 16:04:06 +01:00
Daniel Schadt
4fdd3cd761 deduplicate download opening code 2017-01-04 15:31:47 +01:00
Daniel Schadt
8c5ad7d46d use download prompt for mhtml downloads
Fixes #2204

We didn't previously use PromptMode.download for MHTML download prompts
to avoid dealing with thinks like "Open download", but the new download
prompt is just way better than the old, which justifies the extra work.

This means that MHTML downloads can now also be opened directly.
2017-01-04 15:18:56 +01:00
Nikolay Amiantov
aec002fa29 Add more tests for PAC 2017-01-03 13:47:13 +03:00
Nikolay Amiantov
19966a9b9f proxy_from_url: fix PACFetcher construction 2017-01-03 13:47:13 +03:00
rsteube
a716861bfa removed try/except from ripbang userscript 2017-01-02 21:53:04 +01:00
Florian Bruhin
48d4c9311a Various dependency updates 2017-01-02 20:16:51 +01:00
Florian Bruhin
f4081c8b87 Fix error position when the statusbar is invisible 2016-12-29 20:35:10 +01:00
Florian Bruhin
ea2eefccb1 requirements: Update Jinja2 to 2.8.1 2016-12-29 16:36:43 +01:00
Florian Bruhin
824ddb72a9 Update changelog 2016-12-29 00:40:20 +01:00
Florian Bruhin
52b5ef787a Merge branch 'fiete201-horizontal-scroll' 2016-12-29 00:39:26 +01:00
Florian Bruhin
45ed0b3a16 Update authors 2016-12-29 00:39:18 +01:00
Florian Bruhin
643cf3f578 Fix various small mouse scrolling issues 2016-12-29 00:38:52 +01:00
Florian Bruhin
ce71b59894 Merge branch 'horizontal-scroll' of https://github.com/fiete201/qutebrowser into fiete201-horizontal-scroll 2016-12-29 00:34:26 +01:00
Fritz Reichwald
f25c5dedd6 First try for horizontal scrolling with mouse 2016-12-29 00:21:42 +01:00
Florian Bruhin
9837c9f70b Release v0.9.0 2016-12-28 23:47:59 +01:00
Florian Bruhin
1c4a28e5a0 Add old config for 0.9.0 2016-12-28 23:47:09 +01:00
Florian Bruhin
9b5f7db03a Update changelog 2016-12-28 23:36:24 +01:00
Florian Bruhin
057e5c9807 Update authors 2016-12-28 23:33:52 +01:00
Florian Bruhin
e192e2795d Merge branch 'fiete201-jinja-error' 2016-12-28 23:31:40 +01:00
Florian Bruhin
cbb046b5a3 Update authors 2016-12-28 23:31:31 +01:00
Florian Bruhin
6d9362028f Merge branch 'jinja-error' of https://github.com/fiete201/qutebrowser into fiete201-jinja-error 2016-12-28 23:31:04 +01:00
Florian Bruhin
36bb8f5f5a Merge branch 'fiete201-unicode-error' 2016-12-28 23:04:27 +01:00
Florian Bruhin
25eabb4662 Update authors 2016-12-28 23:04:14 +01:00
Florian Bruhin
d9c8bd7fca Add a test for userscript unicode errors 2016-12-28 23:03:46 +01:00
Florian Bruhin
864b9870a5 Also catch UnicodeDecodeError on Windows 2016-12-28 23:03:37 +01:00
Florian Bruhin
9727d6c74f Improve error output 2016-12-28 23:03:30 +01:00
Florian Bruhin
cb530306a9 Merge branch 'unicode-error' of https://github.com/fiete201/qutebrowser into fiete201-unicode-error 2016-12-28 22:51:52 +01:00
Fritz Reichwald
ae736da5f7 Fix lint 2016-12-28 22:51:20 +01:00
Fritz Reichwald
8c3d461482 Fix test for logging 2016-12-28 22:35:03 +01:00
Fritz Reichwald
421fc7eca3 Remove icon from html_fallback 2016-12-28 22:23:05 +01:00
Fritz Reichwald
0bd3100de8 Fix test_not_found 2016-12-28 22:11:34 +01:00
Florian Bruhin
1ef69704e2 test/codecov requirements: Update coverage to 4.3.1 2016-12-28 17:43:46 +01:00
Florian Bruhin
473df00ae5 Update ace.js to 1.2.6 2016-12-28 17:39:01 +01:00
Fritz Reichwald
f38dda5f16 Fix html_fallback and logged error message 2016-12-28 02:23:35 +01:00
Florian Bruhin
ab784a82fd test/codecov requirements: Update coverage to 4.3 2016-12-28 00:19:17 +01:00
Fritz Reichwald
eb03f79978 Add error handling for UnicodeDecodeError 2016-12-27 22:51:30 +01:00
Florian Bruhin
9726cd7e22 test requirements: Update Werkzeug to 0.11.13 2016-12-27 21:12:49 +01:00
Florian Bruhin
ba702db94e test requirements: Update CherryPy to 8.6.0 2016-12-27 21:12:36 +01:00
Florian Bruhin
59f583aed3 Add python3-pyqt5.qtquick to INSTALL 2016-12-27 21:06:49 +01:00
Fritz Reichwald
07143dd433 Add html escape proper quotes and log call 2016-12-27 20:31:57 +01:00
Fritz Reichwald
004b0dc911 Add fallback for missing error.html 2016-12-27 17:54:06 +01:00
Florian Bruhin
a57c8f078f test requirements: Update CherryPy to 8.5.0 2016-12-26 16:53:03 +01:00
Florian Bruhin
45d2046b96 test requirements: Update Werkzeug to 0.11.12 2016-12-26 16:50:51 +01:00
rsteube
8169d1865a Added ripbang userscript 2016-12-25 17:50:24 +01:00
Florian Bruhin
59b378e29a Merge branch 'Kingdread-issue-2173' 2016-12-22 22:26:13 +01:00
Florian Bruhin
2d1d078430 Merge branch 'issue-2173' of https://github.com/Kingdread/qutebrowser into Kingdread-issue-2173 2016-12-22 22:24:19 +01:00
Florian Bruhin
71404a87b9 Fix lint 2016-12-22 15:14:35 +01:00
Florian Bruhin
89fe725a85 Add __init__.py 2016-12-22 14:26:35 +01:00
Florian Bruhin
0df2761b03 Update changelog 2016-12-22 14:26:15 +01:00
Daniel Schadt
4b7818589d make test independent of previous tests 2016-12-22 14:22:37 +01:00
Florian Bruhin
6c1b7dcca1 Move proxy/pac out of QtWebKit folder 2016-12-22 13:54:11 +01:00
Florian Bruhin
b220b5438f Add urlutils.proxy_for_url 2016-12-22 13:51:27 +01:00
Florian Bruhin
cd8d179813 Also xfail #2183 tests without Docker/Travis 2016-12-22 09:17:00 +01:00
Florian Bruhin
c1c184645d Merge branch 'abbradar-pac' 2016-12-22 09:13:04 +01:00
Florian Bruhin
a3d0ea7e01 Adjust skipped test 2016-12-22 09:04:23 +01:00
Florian Bruhin
470ef781eb Update docs 2016-12-22 08:55:56 +01:00
Florian Bruhin
c762fa6279 Revert "[DONOTMERGE] Re-run Codecov"
This reverts commit f0ccc7be14.
2016-12-22 08:55:43 +01:00
Florian Bruhin
5a89ee96d9 Merge branch 'pac' of https://github.com/abbradar/qutebrowser into abbradar-pac 2016-12-22 08:53:10 +01:00
Florian Bruhin
40c397ebaf test requirements: Update Flask to 0.12 2016-12-22 08:11:09 +01:00
Florian Bruhin
fce7cd47b4 Merge branch 'swalladge-master' 2016-12-22 07:02:47 +01:00
Florian Bruhin
8dc54bed93 Update docs 2016-12-22 07:02:28 +01:00
Florian Bruhin
235326d35e Merge branch 'master' of https://github.com/swalladge/qutebrowser into swalladge-master 2016-12-22 07:01:21 +01:00
Florian Bruhin
154748d56e test requirements: Update hypothesis to 3.6.1 2016-12-20 21:40:46 +01:00
Florian Bruhin
c7970eb2ee Xfail tests which fail on Docker/Travis
See #2183
2016-12-20 21:32:46 +01:00
Daniel Schadt
a24bcd4243 add a test for remembering the temp download dir 2016-12-20 15:57:00 +01:00
Daniel Schadt
f92c82ead1 downloads: don't remember dir for temp downloads
Fixes #2173
2016-12-20 14:52:39 +01:00
Samuel Walladge
0afa74a9de remove cat test 2016-12-20 20:48:56 +10:30
Samuel Walladge
a27d7cddb3 fix tests and add another 2016-12-20 20:13:22 +10:30
Samuel Walladge
3d8dedc48b add tests for default-open-dispatcher 2016-12-20 12:09:30 +10:30
Nikolay Amiantov
f0ccc7be14 [DONOTMERGE] Re-run Codecov 2016-12-19 12:42:32 +03:00
Florian Bruhin
135f99c467 test requirements: Update CherryPy to 8.1.3 2016-12-19 08:13:37 +01:00
Florian Bruhin
3f61c7871c pylint requirements: Update astroid to 1.4.9 2016-12-19 08:12:21 +01:00
Florian Bruhin
28ccd03acd tox/test requirements: Update py to 1.4.32 2016-12-19 08:11:05 +01:00
Samuel Walladge
aafcd1f1d7 fix failing pylint test (line too long) 2016-12-17 09:22:22 +10:30
Samuel Walladge
f6c73f3ad6 implement optional download-open handler setting
- adds new `general` -> `default-open-dispatcher` setting (string)
- if set, will be used instead of QDesktopServices.openUrl (xdg-open backend)
- fixes the 'download handlers' part of issue #841
- note that this is only relevent to the `:download-open` command and other
  methods of opening downloaded files from qutebrowser
2016-12-16 21:54:04 +10:30
Florian Bruhin
e1b5f6a64e Merge branch 'fiete201-master' 2016-12-15 06:38:31 +01:00
Florian Bruhin
6a1eafd9b1 Update authors 2016-12-15 06:38:25 +01:00
Florian Bruhin
76682d06fb Merge branch 'master' of https://github.com/fiete201/qutebrowser into fiete201-master 2016-12-15 06:37:49 +01:00
Florian Bruhin
caa3df1595 requirement updates 2016-12-14 20:32:00 +01:00
Florian Bruhin
f0831dacae Bind back/forward keys by default
Those are the XF86Back/Forward media keys on a keyboard, which are apparently
handled by default with QtWebKit, but not QtWebEngine.

Fixes #2166.
2016-12-13 21:49:10 +00:00
Fritz Reichwald
c63e2ee3b0 Add Keywords entry to comply with freedesktop guidelines 2016-12-10 13:38:30 +01:00
Florian Bruhin
5746337733 Fix downloads without QtWebEngine 2016-12-09 07:29:51 +01:00
Florian Bruhin
d0372f1730 Decode percent sequences in QtWebEngine downloads
Fixes #2122.
2016-12-09 07:08:51 +01:00
Florian Bruhin
03eea7f62a Remove download filename suffixes with QtWebEngine 2016-12-09 07:00:25 +01:00
Florian Bruhin
5b70df15fa Revert "Enable HighDPI scaling"
This reverts commit 62bcd24c9a.
Looks like this causes issues for various people...
2016-12-08 21:23:56 +01:00
Florian Bruhin
976cd5f881 Fix lint 2016-12-08 10:31:52 +01:00
Florian Bruhin
62bcd24c9a Enable HighDPI scaling
This should scale up things automatically, without needing to set e.g.
default-zoom (at least with QtWebEngine).

See #1993, #1585
2016-12-08 09:45:46 +01:00
Florian Bruhin
c7d4ea5247 Ignore connection failures for debug.log_signals 2016-12-08 07:15:59 +01:00
Florian Bruhin
70b0a86729 WebEngine: Save/restore zoom when opening a new page
This isn't very pleasurable, but I can't find a solution to set the zoom
correctly while the page is still loading.

See https://bugreports.qt.io/browse/QTBUG-51851
Fixes #1993
2016-12-08 07:06:11 +01:00
Florian Bruhin
3e1b8f0ee3 Update docs 2016-12-07 14:02:25 +01:00
Florian Bruhin
8116aef77a Fix prompt unittests 2016-12-07 12:55:58 +01:00
Florian Bruhin
e5ddb281f4 Add a ui -> prompt-filebrowser option
See #2104
2016-12-07 12:33:44 +01:00
Florian Bruhin
57adcea587 Fix QTBUG-54419 workaround with tabs-are-windows set
Fixes #2162
2016-12-07 07:01:06 +01:00
Nikolay Amiantov
a7d96e0b85 Ignore ESLint warnings for Mozilla's PAC utils 2016-12-07 02:01:19 +03:00
Nikolay Amiantov
27d64d3680 Add tests for PAC resolver and fetcher 2016-12-07 02:01:19 +03:00
Nikolay Amiantov
87890dab20 Add PAC files support 2016-12-07 02:01:19 +03:00
Florian Bruhin
1536a3324e Fix lint 2016-12-06 23:09:23 +01:00
Florian Bruhin
e39d6996c6 Fix test_tab 2016-12-06 22:50:25 +01:00
Florian Bruhin
d709756eb1 Add AbstractZoom._set_factor_internal 2016-12-06 22:50:08 +01:00
Florian Bruhin
caf1950868 Set the default zoom initially with QtWebEngine
This solves a part of #1993, however when the user navigates to a
different page, the zoom is reset.
2016-12-06 20:28:18 +01:00
Nikolay Amiantov
271cb4b001 Add network logger 2016-12-06 18:16:25 +03:00
Florian Bruhin
b31d978a3a Clarify 'go' 2016-12-06 15:21:06 +01:00
Florian Bruhin
df5ce12ed8 Make it possible to cancel authentication with QtWebEngine
Fixes #2156
2016-12-06 07:45:03 +01:00
Florian Bruhin
717fc97f05 Make tab.set_html work without base_url 2016-12-06 07:16:41 +01:00
Florian Bruhin
0ab23a74fb Allow --qt-arg and --qt-flag to be given multiple times
Fixes #2151
2016-12-06 06:47:42 +01:00
Florian Bruhin
7b8af9ebbf Try to stabilize history tests
Sometimes :history-clear would run before about:blank finished loading,
causing the test for :spawn with a history flag to fail.
2016-12-06 06:32:51 +01:00
Florian Bruhin
587e782738 Blacklist pytest 3.0.5
See https://github.com/pytest-dev/pytest/issues/2118
2016-12-05 22:40:09 +01:00
Florian Bruhin
6f90d93306 test requirements: Update pytest to 3.0.5 2016-12-05 16:17:51 +01:00
Florian Bruhin
af766ade48 requirements: Update requests to 2.12.3 2016-12-02 09:43:05 +01:00
Florian Bruhin
362039f1ea Merge branch 'Raihid-tab-move' 2016-12-01 13:25:58 +01:00
Florian Bruhin
568b256056 Regenerate authors 2016-12-01 13:25:15 +01:00
Florian Bruhin
61ada6ba32 Merge branch 'tab-move' of https://github.com/Raihid/qutebrowser into Raihid-tab-move 2016-12-01 13:25:03 +01:00
Florian Bruhin
c8f6006f00 Merge branch 'Raihid-master' 2016-12-01 13:23:23 +01:00
Florian Bruhin
08f537546f Regenerate authors 2016-12-01 13:23:17 +01:00
Florian Bruhin
d668a1b6d6 Merge branch 'master' of https://github.com/Raihid/qutebrowser into Raihid-master 2016-12-01 13:23:01 +01:00
Maciej Wołczyk
f6802272c7 Added a test for quopri with spaces at the end of the line 2016-12-01 01:17:00 +01:00
Maciej Wołczyk
63808fdb98 Removed handling of tab's position and color since it's done by QTabBar 2016-12-01 00:44:07 +01:00
Florian Bruhin
18ac35e7b8 test requirements: Add new pytest-xvfb deps 2016-11-30 20:31:34 +01:00
Florian Bruhin
506fe42957 requirements: Update requests to 2.12.2 2016-11-30 20:30:58 +01:00
Maciej Wołczyk
2fca442892 Fixed TabbedBrowserStub's tabBar, no longer toggling updates while moving tabs 2016-11-30 15:23:35 +01:00
Florian Bruhin
1ecda5a993 test requirements: Update pytest-xvfb to 1.0.0 2016-11-30 15:20:47 +01:00
Maciej Wołczyk
e613d01263 Fixed problems with tab completion after moving tabs (#2141) 2016-11-30 14:17:20 +01:00
Maciej Wołczyk
2cbea50152 Fixed style issues, corrected unit test 2016-11-29 19:10:36 +01:00
Florian Bruhin
9f5f362533 Don't crash if we can't get an element's value for editing
Fixes #2150
2016-11-29 11:31:03 +01:00
Florian Bruhin
5f22affa36 Show longer debug string for elems got from JS
See #2150
2016-11-29 11:16:04 +01:00
Florian Bruhin
6340eee448 Handle invalid text layout when drawing tab 2016-11-29 09:33:27 +01:00
Florian Bruhin
99fed71001 test/vulture requirements: Update vulture to 0.11 2016-11-29 09:23:00 +01:00
Florian Bruhin
856ae39673 flake8 requirements: Update flake8-pep1301 to 1.0 2016-11-29 07:29:47 +01:00
Maciej Wołczyk
729cc61152 Fixed mhtml quopri encoding with spaces and tabs (see: #2063) 2016-11-29 04:03:35 +01:00
Florian Bruhin
59d16efbef Don't set title from URL twice
browsertab already does that before emitting url_changed.
2016-11-26 13:35:49 +01:00
Florian Bruhin
c83c9d96ae Small cleanup 2016-11-26 13:33:38 +01:00
Florian Bruhin
c17bbd47b8 Fix QTBUG-54419 workaround for invalid URLs 2016-11-26 13:32:37 +01:00
Florian Bruhin
73c608dce7 Allow :open without URL with -t/-b/-w 2016-11-26 12:17:23 +01:00
Florian Bruhin
ea44c6d4b9 eslint: Turn off capitalized-comments 2016-11-26 11:48:57 +01:00
Florian Bruhin
3ca4916b76 Relax qt_log_ignore pattern
Earlier Qt versions show this:

        QStandardPaths: wrong ownership on runtime directory
        /tmp/pytest-of-user/pytest-0/test_linux_invalid_runtimedir0/does-not-exist,
        -2 instead of 1000
2016-11-24 10:37:56 +01:00
Florian Bruhin
64b47fc3a2 Handle an invalid $XDG_RUNTIME_DIR gracefully
This is probably against the XDG basedir spec, but some people have a
Linux without anything setting $XDG_RUNTIME_DIR correctly.

Fixes #971.
2016-11-24 10:14:02 +01:00
Florian Bruhin
98dc92fe16 Remove unused import 2016-11-24 08:50:54 +01:00
Florian Bruhin
34dd30e984 Fix bad merge 2016-11-24 08:29:31 +01:00
Florian Bruhin
002e30a6ca Remove :set --cycle completion test 2016-11-24 07:34:07 +01:00
Florian Bruhin
8ac16c0c4c Update pattern for completion tests 2016-11-24 07:33:50 +01:00
Niklas Haas
32cc6bea1d Add tests for the completion engine
I tested everything that I thought was interesting enough to warrant a
test: especially the ability to test multiple parameters deep, as well
as testing :set --cycle and some involved example to make sure
completion actually works and updates in realtime
2016-11-24 07:31:26 +01:00
Florian Bruhin
26e7ec848f Update docs 2016-11-24 07:24:26 +01:00
Florian Bruhin
3d140a1353 Get rid of --cycle for :set with multiple values
See https://github.com/The-Compiler/qutebrowser/pull/1840#issuecomment-258714784
2016-11-24 07:23:49 +01:00
Niklas Haas
1b5664b72f Add --cycle flag to :set
Chooses the next value from the provided list of values (string-wise
comparison). Technically, the 'option!' syntax for toggling bools is now
redundant, but a translation from 'option!' to '--cycle option false
true' is kept for backwards compatibility.

The '--cycle' flag could also be technically optionally, since the only
thing that depends on it is preserving the error message for specifying
multiple values. (But I think it's best to keep it explicit, as a
principle-of-least-surprise thing)

Note: The business logic of picking the next value and setting it was
moved out to a separate function to avoid tripping pylint's
too-many-branches detector.

Fixes #47
2016-11-24 07:22:06 +01:00
Florian Bruhin
c57ad91e04 Update comment for ignored Qt warning 2016-11-24 06:43:33 +01:00
Florian Bruhin
371e779d98 Fix tabs.feature 2016-11-23 13:16:15 +01:00
Florian Bruhin
8268c9c22f Merge branch 'blyxxyz-cancel-register-key' 2016-11-23 13:08:01 +01:00
Florian Bruhin
cc8db65b18 Merge branch 'cancel-register-key' of https://github.com/blyxxyz/qutebrowser into blyxxyz-cancel-register-key 2016-11-23 12:53:50 +01:00
Florian Bruhin
a3482a8979 Lowercase special keys when checking if they're new
Between v0.8.4 and now, the default keybinding for Ctrl-PgDown changed:

    - ('tab-focus', ['J', '<Ctrl-PgDown>']),
    + ('tab-next', ['J', '<Ctrl-PgDown>']),

The existing keybinding was lower-cased in the config, but _is_new
didn't lowercase the new one, causing a conflict to show up.

Fixes #1835
See #1958
Supersedes #1986
2016-11-23 12:37:19 +01:00
Florian Bruhin
552e0551af Revert zero counts
This initially seemed like a nice feature, but it means 0 can't be bound
as a separate key anymore, and 0<Esc> gives weird error messages...

Reverts #1953.
Fixes #2032.
2016-11-23 08:37:29 +01:00
Florian Bruhin
1507cfcae7 Fix lint 2016-11-23 08:37:24 +01:00
Florian Bruhin
946e3f93f9 Add --enable-webengine-inspector option
Since the inspector can be a security risk, it's now not linked to
developer-extras anymore until QtWebEngine provides a better way to
access it.

See:

https://bugreports.qt.io/browse/QTBUG-50725
http://bouk.co/blog/hacking-developers/
2016-11-23 08:12:13 +01:00
Florian Bruhin
d99a7bd7ad Pass arguments to websettings init functions 2016-11-23 07:57:35 +01:00
Florian Bruhin
df5fdb9864 test requirements: Update pytest-mock to 1.5.0 2016-11-22 22:50:58 +01:00
Florian Bruhin
59ec2eb0ec Merge branch 'Raihid-master' 2016-11-22 22:22:43 +01:00
Florian Bruhin
7ffabb2b92 Update docs 2016-11-22 22:22:24 +01:00
Florian Bruhin
f0cc1de808 Merge branch 'master' of https://github.com/Raihid/qutebrowser into Raihid-master 2016-11-22 20:32:59 +01:00
Maciej Wołczyk
81cbd4c8a0 Hyphen in variable name fixed 2016-11-22 17:39:13 +01:00
Maciej Wołczyk
9d19c3aee6 Changed add to history option name 2016-11-22 17:27:34 +01:00
Florian Bruhin
caf6b74954 Add missing file 2016-11-22 11:42:01 +01:00
Florian Bruhin
20af3133eb Simplify if-condition 2016-11-22 11:24:34 +01:00
Florian Bruhin
97d23144f7 Add an API to get the QNAM of a tab 2016-11-22 11:23:45 +01:00
Florian Bruhin
c363982d05 Use per-tab QNAM for QtNetwork downloads again
When starting a download due to unsupportedContent being emitted, we
need to use (and later adopt) the page's QNetworkAccessManager.

Since we need the whole adopting logic for that case anyways, let's keep
things as they were and always run downloads in per-tab QNAMs.

This reverts 53e360ec4b and fixes #2134.
2016-11-22 11:10:37 +01:00
Maciej Wołczyk
918b3e2d12 History flag: test added, short version changed, minor fixes 2016-11-21 15:33:38 +01:00
Florian Bruhin
c5cacbc439 Handle background tabs in QtWebEngine createWindow with older Qt 2016-11-21 06:22:38 +01:00
Rahid
058c3e6541 Trailing spaces 2016-11-18 23:45:12 +01:00
Rahid
bf41135846 Added chronicle flag to init function, docs 2016-11-18 23:10:50 +01:00
Maciej Wołczyk
554b9b2bda Added chronicle flag 2016-11-18 20:16:43 +01:00
Florian Bruhin
d1154759d1 Improve --qt-arg docs 2016-11-16 22:35:20 +01:00
Florian Bruhin
8d7fcf41da Set a maximum width for prompts
Fixes #2124
2016-11-16 22:26:16 +01:00
Florian Bruhin
9649884add tox requirements: Update tox to 2.5.0 2016-11-16 22:16:40 +01:00
Florian Bruhin
acd13eed49 pytest requirements: Update pytest-faulthandler to 1.3.1 2016-11-16 22:16:13 +01:00
Florian Bruhin
4fc2f93b7a codecov/pylint requirements: Update requests to 2.12.1 2016-11-16 22:15:37 +01:00
Florian Bruhin
7c88fe318f Handle cancelled SSL prompts correctly
When the user pressed esc during an SSL prompt, the message.ask call
returned None, which was handled fine by QtWebKit (which simply used an
'if') but failed with QtWebEngine (which returned the value to Qt).

Fixes #2123.
2016-11-16 22:13:57 +01:00
Florian Bruhin
52df867030 Fix test_webkitelem 2016-11-16 13:09:16 +01:00
Florian Bruhin
25358bb5fc Clean up webelem.text/set_text
webelem.text() was only used without use_js=True from webelem.__str__.
Now we instead default to the use_js=True behavior and renamed the
method from text() to value().

The old behavior is instead directly implemented in __str__.

This changes how webelem.value (aka text) handles elements for which
is_content_editable() returns True, but I haven't found any cases where
this makes a difference.

This also fixes getting existing text from elements with QtWebEngine,
which closes #1957.
2016-11-16 12:34:27 +01:00
Florian Bruhin
5e53f230ee travis: Set matrix.fast_finish 2016-11-16 08:28:36 +01:00
Florian Bruhin
35d9514456 Whoops...
Dang, spacemacs!
2016-11-16 07:50:47 +01:00
Florian Bruhin
e9a8201aa1 cxfreeze requirements: Blacklist >= 5.0.0
See #1004
2016-11-16 07:48:37 +01:00
Florian Bruhin
f274e198e4 tox requirements: Update virtualenv to 15.1.0 2016-11-16 07:16:37 +01:00
Florian Bruhin
2f5f17e121 pylint/codecov requirements: Update requests to 2.12.0 2016-11-15 23:52:53 +01:00
Florian Bruhin
3638849257 Fix lint 2016-11-15 23:41:53 +01:00
Florian Bruhin
d64efa6b9b Fix test_tabwidget 2016-11-15 23:40:24 +01:00
Florian Bruhin
7d8ef9fccf Remove urlutils import 2016-11-15 23:25:14 +01:00
Florian Bruhin
b5f9135f98 Update docs 2016-11-15 23:23:34 +01:00
Florian Bruhin
8e0565b79a Add {backend} window/tab title field 2016-11-15 23:23:20 +01:00
Florian Bruhin
d7d270ea28 Implement user stylesheets for QtWebEngine 2016-11-15 23:17:27 +01:00
Florian Bruhin
fcb955458c Require a filename for user-stylesheet; add hide-scrollbar setting 2016-11-15 22:58:56 +01:00
Florian Bruhin
964ddb472b Add urlutils.data_url 2016-11-15 22:25:51 +01:00
Florian Bruhin
e1928ad991 Mark javascript BDD test as flaky
For some reason it sometimes fails with an error message coming out of
nowhere...
2016-11-15 20:17:51 +01:00
Florian Bruhin
a09a565aea Improve :click-element error message 2016-11-15 19:43:03 +01:00
Florian Bruhin
456ab18f24 Fix double-When in BDD test 2016-11-15 19:36:32 +01:00
Florian Bruhin
d05918ac0b Add custom user-agent support for QtWebEngine 2016-11-15 11:32:05 +01:00
Florian Bruhin
8d173e1718 Update comment 2016-11-15 10:55:12 +01:00
Florian Bruhin
bc3f96ce9a flake8 requirement: Update pycodestyle to 2.2.0 2016-11-15 10:51:21 +01:00
Florian Bruhin
fc7961ae22 Set correct paths for QtWebEngine 2016-11-15 10:51:14 +01:00
Florian Bruhin
96e16d6fe8 Add a test for standarddir.runtime() 2016-11-15 09:12:52 +01:00
Florian Bruhin
ed10cd14d6 Remove history NUL byte logging
It just produces a lot of logging noise, and I still have no idea what
to do about it...
2016-11-15 07:28:35 +01:00
Florian Bruhin
a38e6be52a Fix standarddir._from_args 2016-11-15 07:26:10 +01:00
Florian Bruhin
671ce67be5 Remove --datadir/--confdir/--cachedir
Closes #2115.
2016-11-15 07:09:46 +01:00
Florian Bruhin
d04534dc33 Reenable @qtwebengine_createWindow tests
Closes #2121
2016-11-15 07:03:13 +01:00
Jan Verbeek
fc79349af6 Remove misplaced blank line 2016-11-15 00:30:54 +01:00
Jan Verbeek
f0d215e07a Change hard-coded escape to leave-mode binding 2016-11-14 23:28:38 +01:00
Florian Bruhin
81d67f8a2c Remove support for an empty data/config/cachedir
See #2115
2016-11-14 23:13:21 +01:00
Florian Bruhin
b30d37e3e0 WebEngine: Fake keypresses with modifiers instead of override_target
With QtWebEngine, handling a click (e.g. createWindow being called)
happens some time after a click event has been handled.

When setting override_target, that means we don't know when to set the
override target back, and we can't simply only unset it in createWindow
as elements not causing a new tab to be opened (like an input field) can
be hinted too.

Instead, we now only use override_target with QtWebKit, and simply
generate fake key events with the right modifiers to do the right thing
in createWindow for QtWebEngine.

Fixes #2119.
2016-11-14 23:09:16 +01:00
Florian Bruhin
81e8421f62 Stabilize rapid hinting test more 2016-11-14 10:52:30 +01:00
Florian Bruhin
cd3305b4dd Stabilize :hint --rapid test 2016-11-14 09:42:08 +01:00
Florian Bruhin
ba1bcc658e Fix WebEnginePage acceptNavigationRequest 2016-11-14 09:37:23 +01:00
Florian Bruhin
69452a9813 Fix hint tests 2016-11-14 09:37:01 +01:00
Florian Bruhin
781a326648 Fix lint 2016-11-14 09:14:57 +01:00
Florian Bruhin
004d0b7ae5 Add missing rapid.html 2016-11-14 09:14:57 +01:00
Florian Bruhin
30827c1239 Fix rapid hinting with QtWebEngine
There were actually two issues here:

- The override_target was reset too early - now
  acceptNavigationRequest/createWindow is responsible for resetting it.
- The QTBUG-54419 workaround opened any tabs in the background instead
  of preserving their position/focus.

Fixes #2086.
2016-11-14 07:14:44 +01:00
Florian Bruhin
5de07246be Handle clicks via createWindow with QtWebEngine
Before, we used the same logic for QtWebKit and QtWebEngine, where we
simply set an attribute on the tab on a mousePressEvent and then handled
opening links in acceptNavigationRequest.

However, this caused random links to pop up in new tabs (probably to
things being much more async?) on QtWebEngine, so we now handle those
cases in createWindow and only use override_target from the tab there.

Fixes #2102.
2016-11-14 06:52:33 +01:00
Florian Bruhin
650b9e465c Merge branch 'webengine-prompts' 2016-11-13 21:25:07 +01:00
Florian Bruhin
ffbd6fc347 Merge branch 'thuck-master' 2016-11-13 12:43:38 +01:00
Florian Bruhin
9d6e87848a Regenerate authors 2016-11-13 12:43:31 +01:00
Florian Bruhin
02257694c4 Fix indent 2016-11-13 12:43:20 +01:00
thuck
e1012501ec Issue only happens when using webengine
Check if using webengine, before trying to use thw workaround
2016-11-13 12:10:03 +01:00
thuck
0eab91ac4c Fix for webengine too 2016-11-13 11:56:21 +01:00
thuck
56ee7d63b3 Should fix the issue #2117 2016-11-13 09:50:54 +01:00
Florian Bruhin
2142bc23d4 test requirements: Update pytest to 3.0.4 2016-11-13 01:48:37 +01:00
Florian Bruhin
5bdd74138d Handle not being able to get elements via JS 2016-11-13 01:46:18 +01:00
Florian Bruhin
645a9aa6e1 Add a better workaround for QTBUG-54419
Whenever we open a new tab in createWindow, we now set an attribute
marking it - as soon as its URL changes the first time, we then close
and re-open it in a new tab in TabbedBrowser.
2016-11-13 01:38:02 +01:00
Florian Bruhin
67ad5c9837 Merge branch 'blyxxyz-union-tests' 2016-11-11 07:40:59 +01:00
Florian Bruhin
2dd857d580 Remove FakeTypingMeta.__subclasscheck__ 2016-11-11 07:40:21 +01:00
Florian Bruhin
4b4bf7ec9e Merge branch 'union-tests' of https://github.com/blyxxyz/qutebrowser into blyxxyz-union-tests 2016-11-11 07:18:23 +01:00
Florian Bruhin
94e2a4dccc Make sure the tab indicator color is always available 2016-11-11 07:04:01 +01:00
Jan Verbeek
75c996c13e Cancel register key input with escape 2016-11-11 02:45:59 +01:00
Florian Bruhin
2ded5ef6dd tests: Get rid of flaky_once mark 2016-11-10 22:45:27 +01:00
Florian Bruhin
40c5c75a6c tests: Add a js_prompt marker 2016-11-10 22:45:27 +01:00
Florian Bruhin
a6215be864 Get rid of NetworkManager._ask 2016-11-10 22:45:27 +01:00
Florian Bruhin
a9d48753ef Adjust docstring 2016-11-10 22:45:27 +01:00
Florian Bruhin
b270c69ea7 Improve authentication dialog with no realm 2016-11-10 22:45:27 +01:00
Florian Bruhin
29cb9279e5 Emit shutting_down signal when a WebEngineTab shuts down
Fixes #2109
2016-11-10 22:45:27 +01:00
Florian Bruhin
8d781c68c9 Fix lint 2016-11-10 22:45:27 +01:00
Florian Bruhin
6b14cda5d0 Re-enable SSL download test on QtWebEngine 2016-11-10 22:45:27 +01:00
Florian Bruhin
2d23ed52de Adjust check_coverage 2016-11-10 22:45:27 +01:00
Florian Bruhin
013c2691d5 Fix javaScriptPrompt override for newer PyQt versions 2016-11-10 22:45:27 +01:00
Florian Bruhin
62d258190f Only support :debug-clear-ssl-errors with QtWebKit 2016-11-10 22:45:27 +01:00
Florian Bruhin
adb2ce0160 Remove MouseLock permission support
For some reason it doesn't work...
2016-11-10 22:45:27 +01:00
Florian Bruhin
bbcbb24cb5 Handle feature permissions with QtWebEngine 2016-11-10 22:45:27 +01:00
Florian Bruhin
8f55725555 Fix lint 2016-11-10 22:45:27 +01:00
Florian Bruhin
8a4ca25b8d Avoid circular import 2016-11-10 22:45:27 +01:00
Florian Bruhin
c6f83d3148 Don't show SSL error page for subresources 2016-11-10 22:45:27 +01:00
Florian Bruhin
d93bc8b26b Make prompt tests run 2016-11-10 22:45:27 +01:00
Florian Bruhin
6697d692e1 webengine: Initial SSL error support 2016-11-10 22:45:27 +01:00
Florian Bruhin
65625a9dea webengine: Initial support for authentication and javascript prompts 2016-11-10 22:45:27 +01:00
Florian Bruhin
6d72bce4b6 Remove stub call for WebEngineCaret._on_mode_(entered|left)
It doesn't really serve a purpose...
2016-11-10 22:41:41 +01:00
Florian Bruhin
d8d7b42c43 Stabilize macro tests 2016-11-10 09:03:56 +01:00
Florian Bruhin
adcd8a7220 Fix lint 2016-11-10 08:53:44 +01:00
Florian Bruhin
bddda6b778 Use a data: URL for the broken qutebrowser logo
It blows our HTML up, but we use error.html from various places with
various security policies, so we can't rely on being able to load
file:// URLs.
2016-11-10 08:53:06 +01:00
Florian Bruhin
f1bba45db5 Revert "Serve broken qutebrowser logo via qute:resources"
This reverts commit 37fa7431b0.
2016-11-10 07:51:19 +01:00
Florian Bruhin
bbd842bd82 Get rid of modeman.maybe_leave 2016-11-10 07:19:45 +01:00
Florian Bruhin
2ef85d6c35 Fix macros with a mode-switching command 2016-11-10 07:16:52 +01:00
Florian Bruhin
22cd42c515 test requirements: Update Mako to 1.0.6 2016-11-10 06:56:01 +01:00
Florian Bruhin
29099b5fd5 Merge branch 'blyxxyz-macros' 2016-11-10 06:54:24 +01:00
Florian Bruhin
3884271505 check_coverage: Add keyinput.macros to WHITELISTED_FILES 2016-11-10 06:54:02 +01:00
Florian Bruhin
c7fb99878f Move macro tests to keyinput.feature 2016-11-10 06:51:59 +01:00
Florian Bruhin
2a094ce35c Update changelog 2016-11-10 06:51:17 +01:00
Florian Bruhin
5d30105a53 Merge branch 'macros' of https://github.com/blyxxyz/qutebrowser into blyxxyz-macros 2016-11-10 06:50:21 +01:00
Jan Verbeek
80c5e92094 Fix Union tests for newer Python 3.5 versions 2016-11-10 00:54:51 +01:00
Cosmin Popescu
89e6ff6599 fix wrong spaces and priority for session restore 2016-11-09 19:27:48 +01:00
Florian Bruhin
ac2df2f253 Merge branch 'webengine-downloads-3' 2016-11-09 19:09:58 +01:00
Jan Verbeek
a778b7184c Revert back to objreg to avoid circular import 2016-11-09 19:07:56 +01:00
Jan Verbeek
f1c3bc89ec Further cleanup 2016-11-09 14:56:41 +01:00
Florian Bruhin
9bc54ebf97 Merge branch 'insert-text-js' of https://github.com/paretje/qutebrowser into paretje-insert-text-js 2016-11-09 14:52:18 +01:00
Kevin Velghe
c36edfb2ba Wait for text being inserted before testing 2016-11-09 14:36:20 +01:00
Florian Bruhin
1a5e90f652 Fix lint 2016-11-09 14:29:06 +01:00
Jan Verbeek
479c8e56b4 Improve macro code style, info messages 2016-11-09 13:09:10 +01:00
Florian Bruhin
6e8f86207c Merge branch 'HolySmoke86-issue1619' 2016-11-09 12:36:25 +01:00
Florian Bruhin
0f05ff6536 Update docs 2016-11-09 12:36:07 +01:00
Florian Bruhin
d80022f3cd Merge branch 'issue1619' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue1619 2016-11-09 12:32:52 +01:00
Jan Verbeek
e5dec949b0 Merge https://github.com/The-Compiler/qutebrowser into macros 2016-11-09 12:17:04 +01:00
Daniel Karbach
b481dd668d test config migration for tab-{close,only} flags 2016-11-09 09:38:47 +01:00
Daniel Karbach
4afd75a24d typo in comment 2016-11-09 09:30:37 +01:00
Florian Bruhin
cf32aac111 Move usertypes.DownloadTarget to downloads module 2016-11-09 08:15:58 +01:00
Florian Bruhin
80562fbdca Add DownloadTarget.suggested_filename 2016-11-09 08:06:57 +01:00
Florian Bruhin
8771759f68 Improve error handling in objreg.dump_objects 2016-11-09 07:54:02 +01:00
Florian Bruhin
970e4d3e03 Fix mhtml overwrite prompts
See #2101
2016-11-08 23:23:53 +01:00
Florian Bruhin
df9bee33f4 Fix 100% coverage in misc.ipc 2016-11-08 21:56:54 +01:00
Florian Bruhin
baeb8653c8 Finish stats correctly with QtWebEngine downloads 2016-11-08 20:41:40 +01:00
Florian Bruhin
3ba7f28069 Re-add download cleanup on shutdown 2016-11-08 20:36:49 +01:00
Florian Bruhin
de1e3a7a54 Make DownloadItem._autoclose private 2016-11-08 20:35:07 +01:00
Florian Bruhin
b00c889dd1 Call _set_fileobj in AbstractDownloadItem.set_target 2016-11-08 20:33:25 +01:00
Florian Bruhin
23e7b3f551 Elide js element debug string 2016-11-08 12:17:44 +01:00
Florian Bruhin
19d31ac201 Deduplicate "Focus object changed" logging 2016-11-08 12:17:44 +01:00
Florian Bruhin
57ee378ec5 Ignore None-socket in ipc.on_timeout 2016-11-08 12:17:44 +01:00
Florian Bruhin
f271081012 Handle None-tab in on_current_changed 2016-11-08 12:17:44 +01:00
Florian Bruhin
19c7d747dd Fix downloads with unknown size with WebEngine 2016-11-08 09:18:10 +01:00
Florian Bruhin
ed3347365f Fix lint 2016-11-08 09:18:10 +01:00
Florian Bruhin
54db4255b1 Fix handling of temporary files
When we use self._set_filename in self._set_fileobj, the file already
exists, so we need to force "overwriting" it.

Also, move temporary file handling to a dedicated _set_tempfile method,
so we can officially claim not supporting _set_fileobj with QtWebEngine
instead of supporting it with a hack.
2016-11-08 09:18:10 +01:00
Florian Bruhin
53e360ec4b Always use a global QNAM for downloads
This makes a lot of code eaiser, and we don't have per-tab settings yet
anyways. Also, with QtWebEngine, we can't honour any per-tab settings
for downloads...
2016-11-08 09:18:09 +01:00
Florian Bruhin
bc1e4385e0 Fix first bunch of download tests 2016-11-08 09:18:09 +01:00
Florian Bruhin
ce1b675a1e Implement :download/hints via QtNetwork 2016-11-08 09:18:09 +01:00
Florian Bruhin
5bc3914f24 Pass basename only as suggested filename 2016-11-08 09:18:09 +01:00
Florian Bruhin
fc6c6d4998 Fix lint 2016-11-08 09:16:47 +01:00
Florian Bruhin
7e6edaf93d flake8: Get rid of 'hacking' plugin
It doesn't seem to be intended to be used outside OpenStack, and I'm not
sure if it even works properly in our setup...
2016-11-08 07:07:17 +01:00
Florian Bruhin
39b3bfba93 Mention package names in pdfjs error
Closes #2095.
2016-11-08 06:18:40 +01:00
Cosmin Popescu
c590a37043 changed to using an internal _autosave session 2016-11-07 20:45:46 +01:00
Florian Bruhin
6019e090a1 Fix get_coredumpctl_traces.py 2016-11-07 17:29:34 +01:00
Florian Bruhin
d279f4af89 Merge branch 'paretje-insert-text-js' 2016-11-06 22:42:11 +01:00
Florian Bruhin
9c4086a3f3 Regenerate authors 2016-11-06 22:42:02 +01:00
Florian Bruhin
a39fbc8a07 Merge branch 'insert-text-js' of https://github.com/paretje/qutebrowser into paretje-insert-text-js 2016-11-06 22:41:49 +01:00
Florian Bruhin
690633bd87 Release v0.8.4 2016-11-06 00:47:53 +01:00
Florian Bruhin
55541753e7 flake8 requirements: Update pycodestyle to 2.1.0 2016-11-05 23:58:04 +01:00
Florian Bruhin
be0fe8897b test requirements: Update pytest-bdd to 2.18.1 2016-11-05 23:55:50 +01:00
Florian Bruhin
3a87319830 flake8 requirements: Update flake8-tidy-imports to 1.0.3 2016-11-05 23:55:33 +01:00
Florian Bruhin
0c9a97225a Fix GitHub filename 2016-11-05 23:35:56 +01:00
Florian Bruhin
f7cfb6afc3 Release v0.8.3 2016-11-05 23:08:28 +01:00
Florian Bruhin
d23c7fc5b9 Update changelog for v0.8.3 2016-11-05 23:01:45 +01:00
Florian Bruhin
b6195d4e77 Fix handling of typing.Union with newer Python 3.5 versions 2016-11-05 22:11:52 +01:00
Florian Bruhin
18e5334905 test requirements: Update glob2 to 0.5 2016-11-04 23:44:12 +01:00
Florian Bruhin
a5afdf6fb6 Handle QtWebEngine downloads in DownloadModel 2016-11-04 18:49:25 +01:00
Florian Bruhin
ea9796403f Fix _ask_confirm_question 2016-11-04 18:49:25 +01:00
Florian Bruhin
bf994cd8da Initial QtWebEngine download support 2016-11-04 18:49:24 +01:00
Florian Bruhin
c876c3d244 Fix lint 2016-11-04 18:49:24 +01:00
Florian Bruhin
a3a167e683 Split _die in two methods
We need to do some stuff before AbstractDownloadItem._die runs.
2016-11-04 18:49:24 +01:00
Florian Bruhin
6eef79e180 Adjust imports/objreg 2016-11-04 18:49:24 +01:00
Florian Bruhin
990985e60f Rename browser.webkit.downloads to browser.qtnetworkdownloads 2016-11-04 18:49:24 +01:00
Florian Bruhin
e985730cbf Simplify TempDownloadManager initialization 2016-11-04 18:49:24 +01:00
Florian Bruhin
7ca6996f39 Adjust imports 2016-11-04 18:49:24 +01:00
Florian Bruhin
0ac2b71304 Simplify how filename questions are handled 2016-11-04 18:49:24 +01:00
Florian Bruhin
3b51548d3a More download splitting 2016-11-04 18:49:24 +01:00
Florian Bruhin
92b1bf2227 Get rid of win_id for DownloadItem 2016-11-04 18:49:24 +01:00
Florian Bruhin
12d798d54d Continue download splitting 2016-11-04 18:49:24 +01:00
Florian Bruhin
5b04f1052f Add DownloadItem.set_target
This allows us to make _set_fileobj private, and also makes some code
simpler.
2016-11-04 18:49:24 +01:00
Florian Bruhin
2c94efbf8a First big download refactoring chunk 2016-11-04 18:49:24 +01:00
Florian Bruhin
352f83b95e Rename DownloadItem.do_retry 2016-11-04 18:49:24 +01:00
Florian Bruhin
34b4dcf0d5 Make DownloadItem._retry_info private 2016-11-04 18:49:24 +01:00
Florian Bruhin
70e390a2e8 downloads: Simplify redirect handling 2016-11-04 18:49:24 +01:00
Florian Bruhin
aa9c23d1c1 Merge branch 'prompts' 2016-11-04 18:43:08 +01:00
Florian Bruhin
7256641288 Prevent questions from being aborted twice
When we abort a question (e.g. by closing a tab with SSL errors) while
another prompt is queued, the right prompt gets closed by the question
being aborted, but that in turn aborts the question again, affecting the
next prompt.
2016-11-04 13:21:22 +01:00
Florian Bruhin
15de465dbe bdd: Add a test for keyboard focus with multiple auth prompts 2016-11-04 08:11:06 +01:00
Florian Bruhin
76728f0f73 tests: Allow more auth paths in end2end.fixtures.webserver 2016-11-04 08:11:06 +01:00
Florian Bruhin
fb9415a809 bdd: Allow multiple "When I open" suffixes 2016-11-04 07:20:48 +01:00
Florian Bruhin
a16d41333b Fix prompts while in command mode 2016-11-04 06:48:32 +01:00
Florian Bruhin
dd0ce8fe3b Add some more prompt logging 2016-11-04 06:47:10 +01:00
Florian Bruhin
dc772350bf test requirements: Update pytest-mock to 1.4.0 2016-11-04 06:34:45 +01:00
Florian Bruhin
3a79faac16 Also hide existing prompts when showing a new one
Otherwise when a prompt is interrupted, we'd still see the older one.
2016-11-03 23:03:42 +01:00
Florian Bruhin
59b4ccc620 Rename max_height_padding 2016-11-03 09:29:27 +01:00
Florian Bruhin
a006ecffec Add MainWindow._update_overlay_geometries() 2016-11-03 09:29:27 +01:00
Florian Bruhin
2b46228e3d Customize prompt selection colors
Seems like if we make the foreground color configurable, the selection
isn't colored at all?!
2016-11-03 09:29:27 +01:00
Florian Bruhin
ebcae3a69c Fix tabbing over .. in some directories on Windows 2016-11-03 08:40:42 +01:00
Florian Bruhin
0f03960525 Log if getting directory information failed 2016-11-03 08:40:42 +01:00
Florian Bruhin
732e7c260b Handle empty path for file completion
This also allows us to select drives on Windows hopefully...
2016-11-03 08:40:42 +01:00
Florian Bruhin
cbf1a44b75 Fix handling of / as path 2016-11-03 08:40:42 +01:00
Florian Bruhin
16b3b7a262 Fix prompt positioning with top statusbar 2016-11-03 08:40:42 +01:00
Florian Bruhin
25bb720f09 Bound maximum size for prompts 2016-11-03 08:40:42 +01:00
Florian Bruhin
9cf5d645f0 Hide prompts correctly
We now make sure to hide prompts everywhere when the prompt mode was
left. We also make sure to hide the prompt widget before deleting, as it
might be deleted later.
2016-11-03 08:40:42 +01:00
Florian Bruhin
293a388ac6 Use HTML list for quit confirmation message 2016-11-03 08:40:42 +01:00
Florian Bruhin
fa1846ab0e Adjust prompt path when backspacing a path 2016-11-03 08:40:42 +01:00
Florian Bruhin
bbd8cc56a2 Restructure test_prompt 2016-11-03 08:40:42 +01:00
Florian Bruhin
60c6b7f0ab Simplify FilenamePrompt._insert_text 2016-11-03 08:40:42 +01:00
Florian Bruhin
5b33978259 Improve comment 2016-11-03 08:40:42 +01:00
Florian Bruhin
4e793180c1 Fix completion in file prompts 2016-11-03 08:40:42 +01:00
Florian Bruhin
63c6381e18 Add blank line 2016-11-03 08:40:42 +01:00
Florian Bruhin
fdc4b2e2f6 Move setting FilenamePrompt lineedit text up 2016-11-03 08:40:42 +01:00
Florian Bruhin
7d1b1d354d Remove duplicated docstrings 2016-11-03 08:40:42 +01:00
Florian Bruhin
14ecbc0cec Use jinja for SSL error message 2016-11-03 08:40:42 +01:00
Florian Bruhin
28a32e680d Add comment about HTML escaping 2016-11-03 08:40:42 +01:00
Florian Bruhin
64eeb95c30 Rename _init_title 2016-11-03 08:40:42 +01:00
Florian Bruhin
27f96943a2 Add missing html.escape 2016-11-03 08:40:42 +01:00
Florian Bruhin
efdcbd860e Increase font size for prompt titles 2016-11-03 08:40:42 +01:00
Florian Bruhin
3b7f65d956 Show URL in most questions 2016-11-03 08:40:42 +01:00
Florian Bruhin
4ad741d26d Simplify shutdown in app.py 2016-11-03 08:40:42 +01:00
Florian Bruhin
d85cfcbc07 Fix ask_for_filename call 2016-11-03 08:40:42 +01:00
Florian Bruhin
4552e06797 Only connect interrupted signal for questions once 2016-11-03 08:40:42 +01:00
Florian Bruhin
a87e46101c Fix lint 2016-11-03 08:40:42 +01:00
Florian Bruhin
5ebaddfaf2 Ignore "Unexpected null parameter" warning 2016-11-03 08:40:42 +01:00
Florian Bruhin
1b3e9613ea Fix mode handling with multi-window questions
When the prompt mode is left in any window, we need to take care of:

- Cancelling the question if needed (exactly once)
- Leaving the prompt mode in all other windows too
2016-11-03 08:40:42 +01:00
Florian Bruhin
4a360ba185 Simplify _set_fileview_root 2016-11-03 08:40:42 +01:00
Florian Bruhin
b0a04bff8e Use OS-independent path separators 2016-11-03 08:40:42 +01:00
Florian Bruhin
54a694e35e Hide prompts correctly after :prompt-download-open 2016-11-03 08:40:42 +01:00
Florian Bruhin
5eb66f2693 Restore self._question when restoring prompt 2016-11-03 08:40:42 +01:00
Florian Bruhin
6f83590553 Add some more logging for prompts 2016-11-03 08:40:42 +01:00
Florian Bruhin
dba29e518a First working prototype of global prompts 2016-11-03 08:40:42 +01:00
Florian Bruhin
fdd1147620 Revert "Global prompt container"
This reverts commit c23beee6502776dd19c0955b311e8dfb9f1c77ae.
2016-11-03 08:40:42 +01:00
Florian Bruhin
1d6166b474 Global prompt container 2016-11-03 08:40:42 +01:00
Florian Bruhin
9ce1180b31 First attempt at showing prompts in all windows 2016-11-03 08:40:42 +01:00
Florian Bruhin
d5a1f6d6b5 Only support calling _init_key_label once 2016-11-03 08:40:42 +01:00
Florian Bruhin
fefc8c4eb2 Add more tests for prompts 2016-11-03 08:40:42 +01:00
Florian Bruhin
653ca9799d Add a default for SSL questions 2016-11-03 08:40:41 +01:00
Florian Bruhin
20716c137c Support tab completion for auth prompts again 2016-11-03 08:40:41 +01:00
Florian Bruhin
3ffcb011a7 Simplify key label for auth prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
9bdbb257ba Add initial filename completion 2016-11-03 08:40:41 +01:00
Florian Bruhin
6ab51e0b7b Handle clicking on file items in prompt 2016-11-03 08:40:41 +01:00
Florian Bruhin
acbd5107d6 Only show directories in download filename prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
46b24fc64a Improve how file list is shown in download prompt 2016-11-03 08:40:41 +01:00
Florian Bruhin
6da6758263 Improve FilenamePrompt widget sizing 2016-11-03 08:40:41 +01:00
Florian Bruhin
741ecac9ef More improvements for yesno prompt key hints 2016-11-03 08:40:41 +01:00
Florian Bruhin
7d63795613 Improve bindings output for yesno questions 2016-11-03 08:40:41 +01:00
Florian Bruhin
7d57d884d6 Add configuration options for prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
a33333eb41 Make the radius for prompt edges configurable 2016-11-03 08:40:41 +01:00
Florian Bruhin
dff20ffe35 Fix message.confirm_async calls 2016-11-03 08:40:41 +01:00
Florian Bruhin
bc4e340323 Save key mode to leave
Doing self._prompt.question.done() already sets self._prompt to the next
prompt or to None.
2016-11-03 08:40:41 +01:00
Florian Bruhin
67cb3cd23e tests: Fix waiting for questions with a text 2016-11-03 08:40:41 +01:00
Florian Bruhin
80caed4642 Add missing docstring 2016-11-03 08:40:41 +01:00
Florian Bruhin
e110f3b590 Get rid of StatusBar._set_prompt_active 2016-11-03 08:40:41 +01:00
Florian Bruhin
fe59e0618f Rename download_open function 2016-11-03 08:40:41 +01:00
Florian Bruhin
fe230219a9 Fix lint 2016-11-03 08:40:41 +01:00
Florian Bruhin
a8d1187ba0 Fix keyhint tests 2016-11-03 08:40:41 +01:00
Florian Bruhin
d92674dd04 Remove test_prompt.py 2016-11-03 08:40:41 +01:00
Florian Bruhin
f4be35c981 Add a LineEdit subclass for prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
433afe8658 Handle invalid values with :prompt-accept 2016-11-03 08:40:41 +01:00
Florian Bruhin
051b31d101 Fix reinitializing of key label 2016-11-03 08:40:41 +01:00
Florian Bruhin
7d38430d2d Fix confirm_async 2016-11-03 08:40:41 +01:00
Florian Bruhin
9c34a64f81 self._build_question fail 2016-11-03 08:40:41 +01:00
Florian Bruhin
04d24e3d94 Fix permission question 2016-11-03 08:40:41 +01:00
Florian Bruhin
75bb2265be Take text as pos. argument for _build_question 2016-11-03 08:40:41 +01:00
Florian Bruhin
6d7748f05f Add FilenamePrompt 2016-11-03 08:40:41 +01:00
Florian Bruhin
47208eb022 Fix :prompt-open-download 2016-11-03 08:40:41 +01:00
Florian Bruhin
d74b0109c7 Add key hints 2016-11-03 08:40:41 +01:00
Florian Bruhin
f0ed43ec20 Use message module as API for most questions 2016-11-03 08:40:41 +01:00
Florian Bruhin
756564ebff Get rid of message_bridge.set_cmd_text 2016-11-03 08:40:41 +01:00
Florian Bruhin
523369882a Add title/text to questions 2016-11-03 08:40:41 +01:00
Florian Bruhin
e3581a50ca Remove generated stylesheets again
We can just use jinja logic instead...
2016-11-03 08:40:41 +01:00
Florian Bruhin
1f011bdd5f Fix prompt focus handling 2016-11-03 08:40:41 +01:00
Florian Bruhin
33088588d9 half-working auth prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
903e31efa4 First prototype of new prompts 2016-11-03 08:40:41 +01:00
Florian Bruhin
ced618eccb Pass all arguments to pip on Travis 2016-11-03 08:37:30 +01:00
Florian Bruhin
55d8239671 Fix pip installs on CI 2016-11-03 08:30:21 +01:00
Florian Bruhin
75a3b9ab1b test requirements: Update Mako to 1.0.5 2016-11-03 07:24:56 +01:00
Florian Bruhin
b0e0b1d073 Get rid of requirements-pip.txt
While pinning setuptools/pip versions is still somewhat desirable, we
can't pin it everywhere easily, and the current solution will break
stuff on Windows.
2016-11-03 07:22:31 +01:00
Florian Bruhin
b11a1e92cc test requirements: Update pytest-rerunfailures to 2.1.0 2016-11-02 10:12:10 +01:00
Florian Bruhin
cd97ef0047 Add a QtWebEngine C++ testbrowser 2016-11-02 08:01:09 +01:00
Cosmin Popescu
3692c86a7e auto save session 2016-11-01 19:43:37 +01:00
Kevin Velghe
7a207f7678 There are no events when javascript is disabled 2016-10-31 19:34:32 +01:00
Kevin Velghe
7a9f80bf9a Use jseval to test insert-text with js disabled 2016-10-31 18:26:50 +01:00
Florian Bruhin
f2bf5cc442 test requirements: Update hypothesis to 3.6.0 2016-10-31 16:12:34 +01:00
Florian Bruhin
51a0c2a32c Remove unused imports 2016-10-31 07:27:30 +01:00
Florian Bruhin
a6b0ef18d5 test requirements: Update xdis to 3.2.1 2016-10-31 06:39:23 +01:00
Florian Bruhin
f12d87fabc Only call sip.isdeleted on QObjects 2016-10-31 06:14:43 +01:00
Florian Bruhin
bda72261ad Merge branch 'HolySmoke86-more-tests' 2016-10-30 23:25:44 +01:00
Florian Bruhin
618e7650fe Don't include deleted objects in objreg.dump_objects 2016-10-30 23:25:28 +01:00
Florian Bruhin
a0b90e7bc2 Regenerate authors 2016-10-30 23:24:34 +01:00
Florian Bruhin
b4872192c3 Merge branch 'more-tests' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-more-tests 2016-10-30 23:24:15 +01:00
Florian Bruhin
f6aefabf40 Initialize QtWebKit-specific stuff with QtWebKit only
Maybe this fixes issues we had with QtWebEngine segfaults in proxy.py on
Travis?

Note we can't move cookies/cache/network stuff yet as we still need that
for e.g. adblock downloads with QtWebEngine.
2016-10-30 23:07:19 +01:00
Florian Bruhin
f9c35329df Merge branch 'paretje-insert-text-js' 2016-10-30 19:52:00 +01:00
Florian Bruhin
a74592b7e8 Regenerate authors 2016-10-30 19:51:46 +01:00
Florian Bruhin
428637746a Merge branch 'insert-text-js' of https://github.com/paretje/qutebrowser into paretje-insert-text-js 2016-10-30 19:51:25 +01:00
Florian Bruhin
bd5454b5ab Merge branch 'engelju-1490-help-not-discoverable' 2016-10-30 19:14:28 +01:00
Florian Bruhin
6de216d9e3 Regenerate authors 2016-10-30 19:14:20 +01:00
Florian Bruhin
a17f34bb74 Merge branch '1490-help-not-discoverable' of https://github.com/engelju/qutebrowser into engelju-1490-help-not-discoverable 2016-10-30 19:13:55 +01:00
Florian Bruhin
ddeca672f1 Merge branch 'Spreadyy-patch-4' 2016-10-30 19:12:04 +01:00
Florian Bruhin
6968050d74 Regenerate authors 2016-10-30 19:11:52 +01:00
Florian Bruhin
eeff299d52 Merge branch 'patch-4' of https://github.com/Spreadyy/qutebrowser into Spreadyy-patch-4 2016-10-30 19:11:40 +01:00
Florian Bruhin
664506c050 pip requirements: Update setuptools to 28.7.1 2016-10-30 19:09:24 +01:00
Florian Bruhin
713b00a102 Hide empty "Unhandled client message" warning
Fixes #2071
2016-10-30 19:00:29 +01:00
Kevin Velghe
0caee94994 Remove has_js 2016-10-30 18:54:34 +01:00
Florian Bruhin
7aa587d317 Merge branch 'paretje-jseval-2' 2016-10-30 18:53:03 +01:00
Florian Bruhin
d3f8157020 Update docs 2016-10-30 18:52:45 +01:00
Florian Bruhin
f4022a86fd Improve line breaking 2016-10-30 18:49:41 +01:00
Florian Bruhin
620b952bb2 Merge branch 'jseval-2' of https://github.com/paretje/qutebrowser into paretje-jseval-2 2016-10-30 18:48:14 +01:00
Kevin Velghe
5982787651 Enable javascript again after the test 2016-10-30 17:46:12 +01:00
Kevin Velghe
18420c6978 Test content of textarea without javascript 2016-10-30 16:11:48 +01:00
Kevin Velghe
2d6c443b1a Add test for insert-text with javascript disabled 2016-10-30 12:20:49 +01:00
Kevin Velghe
c537b901f0 Add test for jseval when javascript is disabled 2016-10-30 11:39:25 +01:00
Kevin Velghe
e83b99b0e1 Run javascript on document element
This enables `:jseval` for users who disable javascript on webpages.
2016-10-30 11:39:10 +01:00
Florian Bruhin
85005a44c0 pip requirements: Update setuptools to 28.7.0 2016-10-30 00:40:03 +02:00
Florian Bruhin
829867ed11 test requirements: Update pytest-mock to 1.3.0 2016-10-30 00:39:17 +02:00
Florian Bruhin
37d5991fff flake8 requirements: Update packaging to 16.8 2016-10-30 00:39:00 +02:00
Florian Bruhin
d939a16950 flake8 requirements: Update flake8-pep3101 to 0.6 2016-10-30 00:37:03 +02:00
Daniel Karbach
cfa9068eed flake...
*quitely shakes fist and then submits*
2016-10-28 11:23:05 +02:00
Daniel Karbach
6fff45daeb check exception messages in utilcmds tests 2016-10-28 10:50:58 +02:00
Daniel Karbach
e167f77d68 separate test for hunter exceptions 2016-10-28 10:44:55 +02:00
Spreadyy
33acb7972b Always show scrollbar so the page doesn't jump around 2016-10-28 09:42:50 +02:00
Florian Bruhin
6975e29c5c Regenerate docs 2016-10-27 23:15:51 +02:00
Florian Bruhin
2ce15b0499 Use start.duckduckgo.com as startpage
Apparently some users got nagged by duckduckgo to set it as start page.
2016-10-27 22:16:53 +02:00
Daniel Karbach
6e510372fb more cleanup
jeez, this is getting embarrassing
2016-10-27 15:50:17 +02:00
Daniel Karbach
23a62e952d another lineparser/utilcmds test revision
* verify exception message in lineparser double open
* check for hunter with `pytest.importorskip`
* stricter exception checking in debug_trace test
2016-10-27 14:56:28 +02:00
Daniel Karbach
64cf8fcd39 lineparser/utilcmds test cleanup
* fix date in copyright
* remove redundant class docstrings
* don't rename utilcmds module in unit test
* use `mode_manager` fixture in place of FakeModeMan
* some whitespace
2016-10-27 14:23:01 +02:00
Daniel Karbach
e1c467b3a0 move utilcmds specific tests from misc 2016-10-27 14:20:39 +02:00
Florian Bruhin
367063a776 Merge branch 'blyxxyz-progress-height' 2016-10-27 07:05:19 +02:00
Florian Bruhin
6f7f5ee269 Merge branch 'progress-height' of https://github.com/blyxxyz/qutebrowser into blyxxyz-progress-height 2016-10-27 07:04:28 +02:00
Florian Bruhin
1493bfe766 Revert "pip requirements: Update setuptools to 28.6.2"
This reverts commit 17f7bafc1c.

Turns out I was confused and that version doesn't even exist yet...
2016-10-27 06:46:18 +02:00
Florian Bruhin
17f7bafc1c pip requirements: Update setuptools to 28.6.2 2016-10-27 06:12:52 +02:00
Florian Bruhin
fa45536367 pyroma requirements: Update pyroma to 2.2 2016-10-27 06:09:57 +02:00
Florian Bruhin
634cad7f15 flake8 reqs: Update flake8-deprecated to 1.1 2016-10-27 06:09:43 +02:00
Florian Bruhin
1fb2dd2694 test requirements: Update uncompyle6 to 2.9.3 2016-10-26 19:16:38 +02:00
Florian Bruhin
96b4ab41c7 Re-add label.show() call
We don't actually show a window (so no need to use
waitForWindowShown/waitExposed), but we still need to make sure the
label is shown.
2016-10-26 14:54:35 +02:00
Jan Verbeek
2cc958fbb6 Stop progress bar from growing status bar height 2016-10-26 13:46:52 +02:00
Julie Engel
4093029ed5 also use rel paths for toplevel docs 2016-10-26 12:41:09 +02:00
Florian Bruhin
b9a7bdaab2 Merge branch 'engelju-1490-help-not-discoverable' 2016-10-26 12:02:34 +02:00
Florian Bruhin
0d00f1fecb Regenerate authors 2016-10-26 12:02:26 +02:00
Julie Engel
24b9cdb10c adjust title 2016-10-26 10:53:05 +02:00
Julie Engel
f6d0b6b133 include help doc page in main homepage menu 2016-10-26 10:50:34 +02:00
Florian Bruhin
24f93ee9a5 Merge branch 'engelju-master' 2016-10-26 08:49:02 +02:00
Florian Bruhin
06dcbb0595 Regenerate authors 2016-10-26 08:48:50 +02:00
Florian Bruhin
30e9cd666a Merge branch 'master' of https://github.com/engelju/qutebrowser into engelju-master 2016-10-26 08:48:42 +02:00
Florian Bruhin
c7bfefeb08 tests: Remove useless show() call
We add it to a layout anyways, so it will already be shown.
2016-10-26 08:08:00 +02:00
Florian Bruhin
04682ffbb2 Merge branch 'HolySmoke86-patch-1' 2016-10-26 08:07:03 +02:00
Florian Bruhin
e1740075ab Regenerate authors 2016-10-26 08:06:56 +02:00
Florian Bruhin
7414282500 Merge branch 'patch-1' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-patch-1 2016-10-26 08:06:47 +02:00
Florian Bruhin
ece3f3a2e1 Update to pytest-qt 2.1.0 2016-10-26 07:42:41 +02:00
Florian Bruhin
bd414c5f01 test requirements: Update xdis to 3.2.0 2016-10-26 07:38:05 +02:00
Florian Bruhin
e95056b7d6 Merge branch 'cincodenada-patch-1' 2016-10-25 22:59:21 +02:00
Florian Bruhin
b497e63672 Regenerate authors 2016-10-25 22:59:11 +02:00
Daniel Karbach
442549555b skip segfault test on windows
while technically possible (on both machine and OS level), termination due
to SIGSEGV cannot be prevented
maybe the test could be rewritten to spawn a subprocess and check its exit
status (of 11)
2016-10-25 17:24:14 +02:00
Daniel Karbach
b7b9b7208d Win Dev Environment instructions
adds a rough outline of how to set up a dev env on windows
2016-10-25 16:37:09 +02:00
Joel Bradshaw
3fe050f850 Update test for version bump 2016-10-25 07:11:56 -07:00
Joel Bradshaw
e5a1bb5091 Update version number to 0.8.2
Bump version info to 0.8.2 so that it shows up in `qutebrowser --version`
2016-10-25 06:01:45 -07:00
Daniel Karbach
9038b28ea4 different mocking of open() in lineparser test
apparently, python 3.4 (and less, probably) does not import
builtins into modules
2016-10-25 08:52:08 +02:00
Daniel Karbach
b5ffe979aa "typo" in utilcmds test 2016-10-25 08:48:04 +02:00
Florian Bruhin
872599065b pyinstaller requirements: Don't strip commit ID
See #1692
2016-10-25 08:18:01 +02:00
Florian Bruhin
650af3772a Use PyInstaller with QtWebEngine fix
See #1692
2016-10-25 06:58:29 +02:00
Florian Bruhin
7ebe4d8bfc Merge branch 'edrex-patch-1' 2016-10-24 22:24:37 +02:00
Florian Bruhin
ed3f6c2e90 Regenerate authors 2016-10-24 22:24:29 +02:00
Florian Bruhin
850a2edeaf Merge branch 'patch-1' of https://github.com/edrex/qutebrowser into edrex-patch-1 2016-10-24 22:24:20 +02:00
Florian Bruhin
6935a195e1 Merge branch 'edrex-osx_app_build' 2016-10-24 22:22:00 +02:00
Florian Bruhin
4e55c7b9f0 Update authors 2016-10-24 22:21:48 +02:00
Florian Bruhin
01344fbed7 Add a comment 2016-10-24 22:21:34 +02:00
Florian Bruhin
f25fd04100 Merge branch 'osx_app_build' of https://github.com/edrex/qutebrowser into edrex-osx_app_build 2016-10-24 22:21:11 +02:00
Eric Drechsel
4dfe1c6ab6 Set the bundle identifier to a fake value to allow icu data to be found. 2016-10-24 10:17:39 -07:00
Eric Drechsel
ce23979f91 Update macports Qt install instructions 2016-10-24 10:02:41 -07:00
Julie Engel
83694b6caa Merge pull request #1 from engelju/engelju-patch-1490
Starting on issue #1490
2016-10-24 17:26:42 +02:00
Julie Engel
322afb945d Starting on issue #1490 2016-10-24 17:25:29 +02:00
Daniel Karbach
e0d1fafe43 tests for misc.utilcmds 2016-10-24 17:13:38 +02:00
Daniel Karbach
863bab3ccf allow multiline matches in log messages 2016-10-24 17:10:47 +02:00
Daniel Karbach
c801caa19a log debug console status changes 2016-10-24 17:10:47 +02:00
Daniel Karbach
5d92934d76 less brutal synthetic segfault 2016-10-24 17:10:47 +02:00
Daniel Karbach
bdb96becd6 unit tests for misc.lineparser 2016-10-24 17:10:47 +02:00
Florian Bruhin
7a8f528b82 Merge branch 'HolySmoke86-issue2039' 2016-10-24 17:08:31 +02:00
Florian Bruhin
39b7c25fd4 Merge branch 'issue2039' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue2039 2016-10-24 17:08:15 +02:00
Florian Bruhin
b849f3f2e7 Merge branch 'Spreadyy-patch-3' 2016-10-24 17:03:45 +02:00
Florian Bruhin
fcf6453cf8 Regenerate authors 2016-10-24 17:03:33 +02:00
Florian Bruhin
cf740a6f52 Merge branch 'patch-3' of https://github.com/Spreadyy/qutebrowser into Spreadyy-patch-3 2016-10-24 17:03:20 +02:00
Florian Bruhin
fe70fddf9a test requirements: Update pytest-warnings to 0.2.0 2016-10-24 12:14:17 +02:00
Spreadyy
d5421c720a Fix hr on small devices 2016-10-24 09:07:55 +02:00
Spreadyy
43dc2bf163 fix footnotes, make page wider 2016-10-22 23:26:05 +02:00
Spreadyy
d8316955c7 fix code blocks inside new "table" 2016-10-22 23:11:17 +02:00
Spreadyy
12374fc6cf fix top margin 2016-10-22 23:07:16 +02:00
Jan Verbeek
21289a80ad Catch RegisterKeyParser command errors 2016-10-20 17:38:56 +02:00
Kevin Velghe
efadbe64b5 insert_text doesn't need javascript to be enabled
It runs in the context of an element, which seems possible, even without
javascript enabled (in qtwebkit?).
2016-10-20 15:54:06 +02:00
Daniel Karbach
da2ba86aa5 use https for links in docs and elsewhere
refs #2039
2016-10-20 14:48:35 +02:00
Florian Bruhin
ebe656fdf9 pip requirements: Update setuptools to 28.6.1 2016-10-20 07:30:13 +02:00
Jan Verbeek
f2b05a0395 Move keyboard macro system to MacroRecorder object 2016-10-20 02:50:00 +02:00
Daniel Karbach
ef3968c165 setting values tabs->new-tab-position[-explicit]
left -> prev
right -> next
2016-10-18 17:17:17 +02:00
Daniel Karbach
7eafa30084 :tab-close option names
--left -> --prev
--right -> --next
2016-10-18 15:03:08 +02:00
Daniel Karbach
845298ae41 :tab-close option names
--left -> --prev
--right -> --next
2016-10-18 15:03:08 +02:00
Daniel Karbach
828b7d744a setting values tabs->select-on-remove
left -> prev
right -> next
previous -> last-used

refs #1619
2016-10-18 15:03:01 +02:00
Spreadyy
383af12a74 commit again :D 2016-10-18 12:49:09 +02:00
Spreadyy
182368fda4 style changes 2016-10-18 11:44:54 +02:00
Florian Bruhin
d853cdc120 pyroma requirements: Update pyroma to 2.1 2016-10-18 10:06:18 +02:00
Spreadyy
cd3cf3620b qute css fix 2016-10-18 09:39:01 +02:00
Florian Bruhin
1dd308b50b Merge branch 'paretje-webengine-current' 2016-10-18 06:23:14 +02:00
Florian Bruhin
de2f054112 Update authors 2016-10-18 06:22:59 +02:00
Florian Bruhin
2ae9f14d22 Add pylint disable 2016-10-18 06:22:45 +02:00
Kevin Velghe
59536828a1 Implement hint target "current" for webengine 2016-10-17 23:33:44 +02:00
Florian Bruhin
d24162927a Merge branch 'paretje-webkitelemparent' 2016-10-17 22:29:37 +02:00
Florian Bruhin
b5bd1f8b3f Regenerate authors 2016-10-17 22:29:26 +02:00
Florian Bruhin
ab43ba71d2 Merge branch 'webkitelemparent' of https://github.com/paretje/qutebrowser into paretje-webkitelemparent 2016-10-17 22:26:58 +02:00
Florian Bruhin
b3620a99ff Merge branch 'paretje-webengine-setitem' 2016-10-17 21:43:58 +02:00
Florian Bruhin
906044d51f Merge branch 'webengine-setitem' of https://github.com/paretje/qutebrowser into paretje-webengine-setitem 2016-10-17 21:43:27 +02:00
Jan Verbeek
2a304d7a6b Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into macros
Conflicts:
	qutebrowser/commands/runners.py
2016-10-17 19:14:58 +02:00
Kevin Velghe
97493b71ad Add test for null element 2016-10-17 15:25:31 +02:00
Kevin Velghe
ed91e1d4c8 Implement __setitem__ in WebEngineElement 2016-10-17 14:14:45 +02:00
Florian Bruhin
27d8f25eeb travis: Allow El Capitan to fail 2016-10-17 07:25:35 +02:00
Florian Bruhin
fe5daca351 pip requirements: Update setuptools to 28.6.0 2016-10-16 21:30:25 +02:00
Florian Bruhin
6a93eee14e pip requirements: Update setuptools to 28.5.0 2016-10-16 17:53:12 +02:00
Florian Bruhin
72ae9c133c test reqs: Update uncompyle6/xdis to 2.9.2/3.1.0 2016-10-16 17:27:28 +02:00
Kevin Velghe
7bb4700352 Return None when parent is a null webelement 2016-10-14 14:54:43 +02:00
Florian Bruhin
229faac9cb Stabilize :session-delete tests 2016-10-14 07:24:36 +02:00
Florian Bruhin
8e879f9879 tox requirements: Update tox to 2.4.1 2016-10-14 06:48:38 +02:00
Florian Bruhin
f9f04763c9 Merge branch 'paretje-viewsource' 2016-10-14 06:47:05 +02:00
Florian Bruhin
c012a4e05c Regenerate authors 2016-10-14 06:46:58 +02:00
Florian Bruhin
f26aa9b383 Merge branch 'viewsource' of https://github.com/paretje/qutebrowser into paretje-viewsource 2016-10-14 06:46:38 +02:00
Florian Bruhin
89e422a9f7 Merge branch 'paretje-netrc' 2016-10-14 06:45:58 +02:00
Florian Bruhin
d301f200e2 Improve docs for netrc-file setting 2016-10-14 06:45:41 +02:00
Florian Bruhin
26b6688b61 Merge branch 'netrc' of https://github.com/paretje/qutebrowser into paretje-netrc 2016-10-14 06:39:03 +02:00
Florian Bruhin
d5a3d2e191 tox requirements: Update tox to 2.4.0 2016-10-13 11:30:51 +02:00
Florian Bruhin
9e08eb0d5c Update changelog 2016-10-12 16:21:54 +02:00
Florian Bruhin
6d87815a6b Merge branch 'rcorre-no-silly-command-count-syntax' 2016-10-12 16:21:22 +02:00
Florian Bruhin
c6f0b91832 Regenerate docs 2016-10-12 16:21:03 +02:00
Florian Bruhin
da8b09a164 Merge branch 'no-silly-command-count-syntax' of https://github.com/rcorre/qutebrowser into rcorre-no-silly-command-count-syntax 2016-10-12 16:20:36 +02:00
Florian Bruhin
72fd0df237 Merge branch 'sim590-castnow-userscript' 2016-10-12 16:17:58 +02:00
Florian Bruhin
8cda3b9aea Regenerate authors 2016-10-12 16:17:42 +02:00
Florian Bruhin
40e3d8ae07 Merge branch 'castnow-userscript' of https://github.com/sim590/qutebrowser into sim590-castnow-userscript 2016-10-12 16:16:47 +02:00
Simon Désaulniers
bdab57743a add cast userscript for ChromeCast 2016-10-11 21:22:34 -04:00
Florian Bruhin
90d868b033 test reqs: Update uncompile6/xdis to 2.9.1/3.0.2 2016-10-11 14:08:53 +02:00
Florian Bruhin
121b4bced5 test requirements: Update pytest-cov to 2.4.0 2016-10-11 14:08:04 +02:00
Florian Bruhin
d9e2172e44 Merge branch 'sebastian-frysztak-nm-error' 2016-10-11 13:58:51 +02:00
Florian Bruhin
99acb2309b Regenerate authors 2016-10-11 13:58:42 +02:00
Florian Bruhin
7589d3da0a Merge branch 'nm-error' of https://github.com/sebastian-frysztak/qutebrowser into sebastian-frysztak-nm-error 2016-10-11 13:58:33 +02:00
Florian Bruhin
d5f8181777 test requirements: Update uncompyle6 to 2.9.0 2016-10-10 15:44:08 +02:00
Florian Bruhin
a78fb6f5e4 test requirements: Update xdis to 3.0.0 2016-10-10 15:35:06 +02:00
Ryan Roden-Corrent
fbc084e416 Remove :<count>:cmd syntax support.
CommandRunner.parse had some logic for handling commands of form
:<count>:cmd. However, this complicated the parsing logic for something
that appears to only be used in tests. One could use it in a
userscript, but this is unlikely as it is undocumented. Removing
support for this simplifies the logic of parse.

The commnd `run-with-count` is added to provide this functionality.
It works like `repeat` but passes the count along to the command
instead of running the command multiple times.

This resolves #1997: Qutebrowser crashes when pasting commands.
This bug was caused by excess stripping of ':' from the command string
by _parse_count.
2016-10-10 08:02:30 -04:00
Florian Bruhin
aba67d0822 Add @qtwebengine_todo 2016-10-10 09:30:05 +02:00
Florian Bruhin
6d6655524c Fix quoting 2016-10-10 08:26:32 +02:00
Florian Bruhin
8670009c92 test requirements: Update uncompyle6 to 2.8.4 2016-10-10 08:11:58 +02:00
Florian Bruhin
422bbd0f2c pip requirements: Update setuptools to 28.3.0 2016-10-10 07:40:11 +02:00
Florian Bruhin
f0ebb2a6b8 Merge branch 'sebastian-frysztak-command-history-tests' 2016-10-10 07:38:34 +02:00
Florian Bruhin
cc74c87a4c Regenerate authors 2016-10-10 07:34:32 +02:00
Florian Bruhin
03c0eb244e Remove whitespace at EOL 2016-10-10 07:34:22 +02:00
Florian Bruhin
40eb875fb6 Add a test for private-browsing mode 2016-10-10 07:33:59 +02:00
Florian Bruhin
f7b5a2c9ff Merge branch 'command-history-tests' of https://github.com/sebastian-frysztak/qutebrowser into sebastian-frysztak-command-history-tests 2016-10-10 07:33:46 +02:00
Kevin Velghe
087342894e Add setting for location of netrc file
There is no reason I guess to do this with an environment variable. On
top of that, introducing a settings also documents the netrc feature
itself (Closes #1975?).
2016-10-09 00:15:46 +02:00
Jan Verbeek
87899cb6b3 Fix long lines 2016-10-08 22:00:26 +02:00
Jan Verbeek
33ff0ba715 Interactively get macro register 2016-10-08 21:17:47 +02:00
Sebastian Frysztak
a8847eacbe Cover HistoryEndReachedError in command_history_next(). 2016-10-08 18:14:37 +02:00
Sebastian Frysztak
97d00b2355 Ignore NetworkManager-related Qt warnings
(discussed in #2016)
2016-10-08 11:10:27 +02:00
Florian Bruhin
5eed5eb7f7 commit 5708bb0306fb28549fc47e686790d006398c27fa
Author: Florian Bruhin <git@the-compiler.org>
Date:   Fri Oct 7 07:44:54 2016 +0200

    Turn off private browsing in misc.feature tests
2016-10-07 20:10:39 +02:00
Florian Bruhin
0a8133cc9f test requirements: Update xdis to 2.3.2 2016-10-07 07:32:45 +02:00
Florian Bruhin
15a2b6ba82 flake8 requirements: Update pyparsing to 2.1.10 2016-10-07 07:32:35 +02:00
Florian Bruhin
ea5cbb0c7f Add new mailinglist to release checklist too
[ci skip]
2016-10-07 06:49:04 +02:00
Florian Bruhin
ec5ef2c629 Mention qutebrowser-announce mailinglist 2016-10-07 06:40:13 +02:00
Kevin Velghe
aa6d71ce68 Fix viewsource userscript
For months I've been wondering what created these files in my home
directory ...
2016-10-07 00:32:27 +02:00
Florian Bruhin
5fd43e19c6 Merge branch 'Kingdread-pdfjs-1.6.210' 2016-10-06 22:59:08 +02:00
Florian Bruhin
9ad4d46599 Update changelog 2016-10-06 22:58:45 +02:00
Florian Bruhin
c40539c7e9 Merge branch 'pdfjs-1.6.210' of https://github.com/Kingdread/qutebrowser into Kingdread-pdfjs-1.6.210 2016-10-06 22:52:44 +02:00
Jan Verbeek
7aaaadac1a Add keyboard macros 2016-10-06 22:24:04 +02:00
Florian Bruhin
378976db29 Make log.stub work when inspect.stack fails
I got this during shutdown once:

Traceback (most recent call last):
  File ".../qutebrowser/mainwindow/mainwindow.py", line 552, in closeEvent
  File ".../qutebrowser/mainwindow/mainwindow.py", line 538, in _do_close
  File ".../qutebrowser/mainwindow/tabbedbrowser.py", line 218, in shutdown
    self._remove_tab(tab)
  File ".../qutebrowser/mainwindow/tabbedbrowser.py", line 280, in _remove_tab
    tab.shutdown()
  File ".../qutebrowser/browser/webengine/webenginetab.py", line 536, in shutdown
    log.stub()
  File ".../qutebrowser/utils/log.py", line 151, in stub
    function = inspect.stack()[1][3]
  File "/usr/lib64/python3.5/inspect.py", line 1464, in stack
    return getouterframes(sys._getframe(1), context)
  File "/usr/lib64/python3.5/inspect.py", line 1441, in getouterframes
    frameinfo = (frame,) + getframeinfo(frame, context)
  File "/usr/lib64/python3.5/inspect.py", line 1414, in getframeinfo
    lines, lnum = findsource(frame)
  File "/usr/lib64/python3.5/inspect.py", line 804, in findsource
    if pat.match(lines[lnum]): break
IndexError: list index out of range
2016-10-06 21:04:53 +02:00
Sebastian Frysztak
b8156a0c32 BDD tests for :command-history-prev/next
ref #999
2016-10-06 21:02:15 +02:00
Daniel Schadt
a9ac123bfa tests: relax pdfjs tests
Updating the whole snippet in two places is bad, so we relax the testing
code.
2016-10-06 16:18:21 +02:00
Daniel Schadt
ffa276a182 pdfjs: compatibility for v1.6.210
They renamed PDFView to PDFViewerApplication, which we need to account
for in our pdfjs scripts.

Also, it seems like the actual viewer is now only created when the DOM
has been loaded. This means that at the time when our script is
executed, the viewer does not yet exist. Thus we need to delay the open
request too by registering a DOMContentLoaded handler.
2016-10-06 14:43:16 +02:00
Florian Bruhin
53ef16e26b Try to stabilize test_insert_mode 2016-10-06 10:40:28 +02:00
Florian Bruhin
356f6dc924 Disable OS X Yosemite build on Travis for now
See #2013
2016-10-06 09:27:38 +02:00
Florian Bruhin
69889f6bba Merge branch 'sebastian-frysztak-master' 2016-10-05 21:20:19 +02:00
Florian Bruhin
4f1bfd37e6 Regenerate authors 2016-10-05 21:20:13 +02:00
Florian Bruhin
5e6d8e3944 Merge branch 'master' of https://github.com/sebastian-frysztak/qutebrowser into sebastian-frysztak-master 2016-10-05 21:19:17 +02:00
Florian Bruhin
d1f21745e4 Merge branch 'rcorre-completer_unicode' 2016-10-05 21:16:42 +02:00
Florian Bruhin
6184da0224 Add a comment 2016-10-05 21:16:18 +02:00
Florian Bruhin
24eb27e385 Merge branch 'completer_unicode' of https://github.com/rcorre/qutebrowser into rcorre-completer_unicode 2016-10-05 21:15:28 +02:00
Florian Bruhin
ae5e2839ae Revert accidental changes 2016-10-05 15:45:30 +02:00
Florian Bruhin
6be4b74c59 tests: Fix redirect-later-continue with timeout 2016-10-05 15:36:25 +02:00
Florian Bruhin
f6729d23d2 Skip auto-follow-timeout test on OS X
This takes way too long on Travis...
2016-10-05 14:36:05 +02:00
Florian Bruhin
40052c1030 Add @qtwebengine_skip to some @no_xvfb tests 2016-10-05 14:35:25 +02:00
Florian Bruhin
c9f3fbc855 test requirements: Update hypothesis to 3.5.3 2016-10-05 13:32:33 +02:00
Florian Bruhin
08361e7034 Increase timeout for inhibited key test
It seems this fails on the new Travis OS X image.
2016-10-05 13:26:57 +02:00
Florian Bruhin
8fdc609b32 Improve error for inhibited key test 2016-10-05 13:26:44 +02:00
Florian Bruhin
bce5fc529b travis: Don't try to upgrade pip on OS X
We will run into (probably?) system integrity protection.
2016-10-05 13:20:33 +02:00
Florian Bruhin
197e3732d8 travis: Install pip on OS X
It seems pip isn't preinstalled on the newest image.
2016-10-05 13:10:31 +02:00
Florian Bruhin
04d2d60241 travis: Remove custom OS X Qt builds 2016-10-05 12:54:23 +02:00
Florian Bruhin
93f8f6ef4f travis: Add El Capiton/Yosemite OS X builds 2016-10-05 12:53:34 +02:00
Kevin Velghe
e3c92a9bae Set netrc location with QUTE_NETRC 2016-10-05 12:03:52 +02:00
Florian Bruhin
c36ae5ab8f Fix quit confirmation text for downloads 2016-10-05 10:13:01 +02:00
Florian Bruhin
dd537c9119 Really fix test_mthml 2016-10-05 10:12:38 +02:00
Florian Bruhin
8dab1cf58a Fix test_mhtml.py 2016-10-05 09:09:42 +02:00
Florian Bruhin
2f0db878e6 Break long lines 2016-10-05 09:07:35 +02:00
Florian Bruhin
9ca4ff896d flake8 requirements: Update pydocstyle to 1.1.1 2016-10-05 07:11:20 +02:00
Sebastian Frysztak
f0cc168609 Style changes 2016-10-04 16:45:31 +02:00
Sebastian Frysztak
0f84ea2339 Fix TabWidget unit test
(add show-favicons config option)
2016-10-04 16:34:52 +02:00
Ryan Roden-Corrent
2696f9b427 Handle unicode characters in Completer.
Just limit the cursor position to the length of the text to avoid
crashes in this case.

Resolves #2007.
2016-10-04 07:36:49 -04:00
Florian Bruhin
f34d896ff4 Log total initialization time 2016-10-04 10:26:44 +02:00
Florian Bruhin
b107522d8c Make cssutils a lazy import
Importing cssutils takes more than a second on the 2009 Thinkpad with a
Core2 I'm on right now, so let's only import it when actually necessary.
2016-10-04 08:51:10 +02:00
Sebastian Frysztak
df83862088 Reserve space for empty favicon in _get_icon_rect. 2016-10-03 13:14:49 +02:00
Florian Bruhin
4801352254 Merge branch 'Spreadyy-patch-1' 2016-10-03 07:03:19 +02:00
Florian Bruhin
c7e1497872 Regenerate authors 2016-10-03 07:03:08 +02:00
Florian Bruhin
4407ef032a Clean up JS 2016-10-03 07:01:22 +02:00
Florian Bruhin
323d5fc9e7 Also fix scroll.to_perc with position:absolute 2016-10-03 06:59:35 +02:00
Florian Bruhin
b21f7be03a Remove qtwebengine_todo for position:absolute test 2016-10-03 06:55:58 +02:00
Florian Bruhin
bd831939bc Adjust for scrolling off-by-one errors
On some pages with particular zoom levels, elem.offsetHeight is exactly
one pixel more than elem.scrollHeight when fully scrolled down.

This is probably due to rounding/floats/off-by-one errors somewhere
inside Chromium?

We now instead always clip the displayed percentage at 100% (so we don't
display 101%), and consider the page fully scrolled even if we're
scrolled more than the page.
2016-10-03 06:52:54 +02:00
Florian Bruhin
fc0b62f122 Revert "scroll.js --> fix scroll measures"
This reverts commit 0c5d95c943.

Using those values is probably okay as long as we adjust for the
off-by-one errors which will follow in the next commit.
2016-10-03 06:51:57 +02:00
Florian Bruhin
fc1943e5e6 Merge branch 'patch-1' of https://github.com/Spreadyy/qutebrowser into Spreadyy-patch-1 2016-10-03 06:51:37 +02:00
Florian Bruhin
7fae7257a9 Merge branch 'HolySmoke86-issue1987' 2016-10-03 06:45:23 +02:00
Florian Bruhin
53e3eff19d Regenerate authors 2016-10-03 06:45:15 +02:00
Florian Bruhin
5b11eaad85 Merge branch 'issue1987' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue1987 2016-10-03 06:45:01 +02:00
Florian Bruhin
296f309859 Merge branch 'HolySmoke86-issue1940' 2016-10-03 06:42:41 +02:00
Florian Bruhin
3ffbf07eab Update docs 2016-10-03 06:42:13 +02:00
Florian Bruhin
c7b74edfbe Merge branch 'issue1940' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue1940 2016-10-03 06:41:19 +02:00
Florian Bruhin
e4da6be5e9 Merge branch 'lzlw-master' 2016-10-03 06:11:54 +02:00
Florian Bruhin
c1ac84ff3f Regenerate authors 2016-10-03 06:11:47 +02:00
Lazlow Carmichael
3cadbd51db Note on Windows userscript extensions
Quick update for Issue #1946 (Document userscript types on Windows)
2016-10-02 21:49:05 -04:00
Florian Bruhin
f024cc2c59 pip requirements: Update setuptools to 28.2.0 2016-10-02 17:18:44 +02:00
Florian Bruhin
0c5e093c8a pip requirements: Update setuptools to 28.1.0 2016-10-02 10:22:39 +02:00
Florian Bruhin
cd17433d5c Update docs 2016-10-01 22:51:58 +02:00
Florian Bruhin
55cefd1ab7 Don't shadow outer name 2016-10-01 22:51:40 +02:00
Florian Bruhin
625bb7baa4 Clean up crash msgbox properly
Fixes #2004
2016-10-01 22:05:29 +02:00
Sebastian Frysztak
4f443c9f27 Reserve space for favicon with vertical tabs 2016-10-01 12:55:55 +02:00
Florian Bruhin
e73932a555 Merge branch 'knaggita-issue1768' 2016-09-30 18:22:04 +02:00
Florian Bruhin
c80f18522c Remove now-duplicate test
TestKeychain.test_count_0 now tests the exact same thing.
2016-09-30 18:17:28 +02:00
Florian Bruhin
28c87b5c6b Use right key in test_basekeyparser 2016-09-30 18:15:59 +02:00
Florian Bruhin
083d847316 Add a test for a zero count 2016-09-30 18:14:36 +02:00
Florian Bruhin
6b76d5defa Whitespace changes 2016-09-30 17:54:23 +02:00
Daniel Karbach
a3e9fe1fd7 removed duplicate userscript path lookup 2016-09-30 09:50:49 +02:00
Daniel Karbach
dc344989c6 revised missing userscript error messages 2016-09-30 09:50:49 +02:00
Daniel Karbach
eaa754648d common base for userscript exceptions 2016-09-30 09:26:43 +02:00
Daniel Karbach
bac22629e3 test for yanking queries with both '&' and ';' 2016-09-30 09:15:05 +02:00
Florian Bruhin
7df7200797 test requirements: Update pytest to 3.0.3 2016-09-30 08:51:14 +02:00
Florian Bruhin
6df1df2c04 flake8 requirements: Blacklist pydocstyle 1.1.0
See https://gitlab.com/pycqa/flake8-docstrings/issues/16
2016-09-30 08:43:07 +02:00
Florian Bruhin
822c100f52 Make 0 a usable count for :tab-focus
Fixes #1768
2016-09-30 08:33:16 +02:00
Daniel Karbach
46ca91cfc0 only use ';' as query delim if there's no '&' 2016-09-29 17:45:12 +02:00
Daniel Karbach
cbbfbabfc4 reorganize and document 2016-09-29 14:37:40 +02:00
Daniel Karbach
8eb12c6cb9 improved error messages for inexistent userscripts
fixes #1940
2016-09-29 13:29:39 +02:00
Daniel Karbach
ae674bc4ac test for yanking URLs with '&' in query
for completeness' sake
2016-09-29 11:04:38 +02:00
Daniel Karbach
b195b5b40d detect ';' delimiters when yanking URL
fixes #1987
2016-09-29 11:02:30 +02:00
Florian Bruhin
80b5c9127e Merge branch 'HolySmoke86-issue1988' 2016-09-29 10:59:32 +02:00
Florian Bruhin
8c70e1529c Regenerate authors 2016-09-29 10:59:21 +02:00
Florian Bruhin
71270dd8f7 Merge branch 'issue1988' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue1988 2016-09-29 10:59:10 +02:00
Daniel Karbach
4aa3ea89b3 test for yanking URLs with ';' separated queries
refs #1987
2016-09-29 10:44:05 +02:00
Daniel Karbach
6728bb6430 show webview when caret testing
fixes #1988
2016-09-29 09:26:58 +02:00
Spreadyy
0c5d95c943 scroll.js --> fix scroll measures
scroll measures failed a travis test where document.documentElement.offsetHeight and document.documentElement.scrollHeight diffed by one pixel when the browser zoomed. --> Removed offsetHeight.
2016-09-29 08:59:46 +02:00
Florian Bruhin
5ce1f0b912 Don't update scroll position with 0 tabs 2016-09-29 08:48:04 +02:00
Florian Bruhin
5b27e06ce2 Add xfailing test for #1945 2016-09-29 07:16:40 +02:00
Florian Bruhin
b0a2bfa3ee tests: Make scrolling checks stricter 2016-09-29 07:13:34 +02:00
Florian Bruhin
450730df2c Add position_absolute.html test file
Supersedes #1984.
2016-09-29 06:49:41 +02:00
Florian Bruhin
d07a488c9b Merge branch 'HolySmoke86-issue1947' 2016-09-29 06:38:52 +02:00
Florian Bruhin
609e206816 Use pytest.fail 2016-09-29 06:37:04 +02:00
Florian Bruhin
9eacf42693 Import modules 2016-09-29 06:36:31 +02:00
Florian Bruhin
42b7d1d10f Add a colon 2016-09-29 06:35:47 +02:00
Florian Bruhin
656d51d44f Update docs 2016-09-29 06:34:20 +02:00
Florian Bruhin
827ced7028 Merge branch 'issue1947' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-issue1947 2016-09-29 06:22:00 +02:00
Florian Bruhin
6f273398ce pip requirements: Update setuptools to 28.0.0 2016-09-28 22:45:10 +02:00
Florian Bruhin
b9f4013548 test requirements: Update CherryPy to 8.1.2 2016-09-28 22:44:07 +02:00
Daniel Karbach
d00750126e remove superfluous pass statement 2016-09-28 15:50:59 +02:00
Daniel Karbach
7884594f1b simplify checks in version invocation test 2016-09-28 15:31:32 +02:00
Daniel Karbach
73e1460556 test for --version invocation 2016-09-28 14:38:15 +02:00
Daniel Karbach
50fb4a78c7 early init of qapp and standarddir
this fixes the error that appeared when invoked with --version
2016-09-28 10:25:40 +02:00
Spreadyy
f2e471597d Lint test failed --> edited line length 2016-09-27 23:24:12 +02:00
Daniel Karbach
a3bf53d0cd removed blank lines around function docstring
D201/D202
2016-09-27 16:01:25 +02:00
Daniel Karbach
fb68245f2e unit test for utils.version._path_info()
refs #1947
2016-09-27 15:36:18 +02:00
Daniel Karbach
0c4c84d821 adhere to style guide 2016-09-27 13:22:28 +02:00
Daniel Karbach
10a1977459 adjust version unit test
to accomodate for new output from path info

refs #1947
2016-09-27 12:48:19 +02:00
Daniel Karbach
7ce442c771 standarddir path names in qute://version
fixes #1947
2016-09-27 12:01:04 +02:00
Spreadyy
a22ae2818c Fix scroll JS for xkcd.
Fix wrong scroll.height for xkcd. Solution according to:
http://stackoverflow.com/questions/1145850/how-to-get-height-of-entire-document-with-javascript
2016-09-27 11:41:47 +02:00
Florian Bruhin
05dddf4f13 Merge branch 'rcorre-bind-fixes' 2016-09-26 15:43:13 +02:00
Ryan Roden-Corrent
6aaa138619 Use a set instead of a list for Command._modes. 2016-09-26 08:30:28 -04:00
Ryan Roden-Corrent
14f8ec8754 Error on mode/command mismatch with :bind.
Resolves #1964 (:bind should error for mode/command mismatch)
2016-09-26 08:30:28 -04:00
Ryan Roden-Corrent
6fdd007dbb Simplify mode-checking in command.
Rather than maintaining separate _modes and _not_modes lists, just
build a single _modes list in the constructor.
2016-09-26 08:30:28 -04:00
Florian Bruhin
b49aa2d535 test requirements: Update hypothesis to 3.5.2 2016-09-26 10:54:58 +02:00
Florian Bruhin
68e60ecc3c configtypes: Add a "# pragma: no cover" 2016-09-26 08:25:54 +02:00
Florian Bruhin
aec1cf3842 Fix lint 2016-09-26 08:12:18 +02:00
Florian Bruhin
45ce430774 Fix test_check_coverage 2016-09-26 08:11:45 +02:00
Florian Bruhin
41db521b9e Improve check_coverage output
We now show the coverage report for the affected files so we have some
useful debug output.
2016-09-26 07:33:27 +02:00
Florian Bruhin
aec887bc46 Merge branch 'lahwaacz-pretty-url' 2016-09-26 07:08:52 +02:00
Florian Bruhin
62ac87c34f Merge branch 'pretty-url' of https://github.com/lahwaacz/qutebrowser into lahwaacz-pretty-url 2016-09-26 07:08:33 +02:00
Florian Bruhin
69ffb45152 Merge branch 'rsteube-master' 2016-09-26 07:07:30 +02:00
Florian Bruhin
482901169c Update docs 2016-09-26 07:07:23 +02:00
Florian Bruhin
0c89bfd16b Merge branch 'master' of https://github.com/rsteube/qutebrowser into rsteube-master 2016-09-26 07:06:23 +02:00
Florian Bruhin
67c24ec014 Merge branch 'HolySmoke86-option-description' 2016-09-26 07:02:00 +02:00
Florian Bruhin
301447baaa Update docs 2016-09-26 07:01:48 +02:00
Florian Bruhin
cfe25b96fc Merge branch 'option-description' of https://github.com/HolySmoke86/qutebrowser into HolySmoke86-option-description 2016-09-26 07:00:17 +02:00
Florian Bruhin
fbf65f677c tox requirements: Force pluggy 0.4.0 2016-09-26 06:57:21 +02:00
Florian Bruhin
27b524300b Improve configtypes tests
This also gets configtypes.py back to 100% coverage
2016-09-26 06:33:14 +02:00
Florian Bruhin
ab7cbfdea0 Improve keyhint tests
This also brings them back to 100% coverage
2016-09-25 16:42:13 +02:00
Florian Bruhin
02accf3e71 test requirements: Update pytest-bdd to 2.18.0 2016-09-25 15:53:21 +02:00
Florian Bruhin
6751c3f460 test requirements: Update hypothesis to 3.5.1
This also adds a few new dependencies as hypothesis >= 3.5.0 depends on
uncompyle6.
2016-09-25 15:52:18 +02:00
Florian Bruhin
d950762c58 pylint requirements: Update github3.py to 0.9.6 2016-09-25 15:45:34 +02:00
Daniel Karbach
b801208d97 show option description in qute:settings 2016-09-23 15:42:02 +02:00
Florian Bruhin
123aace3e8 Fix keyhint tests 2016-09-23 15:05:01 +02:00
Jakub Klinkovský
a72efe4a3e also prettify url:pretty variable 2016-09-22 19:25:54 +02:00
Florian Bruhin
d4376c5196 Fix overlays with a top statusbar 2016-09-22 17:34:30 +02:00
Florian Bruhin
e6f62f8118 Remove now-unneeded _get_overlay_position 2016-09-22 17:34:17 +02:00
Florian Bruhin
17ceba5ce4 Round correct edge for keyhint with top statusbar 2016-09-22 17:29:25 +02:00
Florian Bruhin
e04e6c51d1 Add generator argument to set_register_stylesheet 2016-09-22 17:29:03 +02:00
Florian Bruhin
750dfd98af Generalize statusbar-attached website overlays
We already had some duplicated logic for completion/keyhint/messageview,
and plan to add prompt overlays too now - so here we refactor related
code to have a list of overlays instead, which are all
resized/positioned by the mainwindow when needed.

This also changes the size management, which gets moved into the
sizeHint of the respective overlay widgets.
2016-09-22 17:04:39 +02:00
Jakub Klinkovský
268db48f19 prettify yank pretty-url 2016-09-22 14:25:48 +02:00
rsteube
08691dc020 Added readability userscript 2016-09-22 01:18:13 +02:00
Florian Bruhin
57d896e989 Fix hints when zoomed with QtWebEngine
We mutated rect (coming from self._js_dict), which means we used the
already adjusted values the second time we called rect_on_view.

Fixes #1863.
2016-09-21 20:09:31 +02:00
Florian Bruhin
a637de4bc5 Merge branch 'rcorre-fix-completer-search-crash' 2016-09-21 13:41:35 +02:00
Florian Bruhin
827a2d73b6 Merge branch 'fix-completer-search-crash' of https://github.com/rcorre/qutebrowser into rcorre-fix-completer-search-crash 2016-09-21 13:41:13 +02:00
Ryan Roden-Corrent
1d2cf3b648 Completer: don't try to partition search.
Exit before trying to partition if the command prefix is not ':'.

Resolves #1969:
'TypeError with refactored completion when searching for command'
2016-09-21 07:08:34 -04:00
Florian Bruhin
c864071c71 pip requirements: Update setuptools to 27.3.0 2016-09-21 07:46:11 +02:00
Florian Bruhin
ad84691f5b flake8 reqs: Blacklist flake8-debugger 2.0.0
See https://github.com/JBKahn/flake8-debugger/issues/5
2016-09-20 09:40:36 +02:00
Florian Bruhin
4c97684be8 Remove OS X bottle from CONTRIBUTING 2016-09-19 05:22:20 +02:00
Florian Bruhin
49f8fa6d76 Add some tests for earlyinit.fix_harfbuzz
See #1948
2016-09-16 08:43:12 +02:00
Florian Bruhin
43fa5f55c1 Don't set QT_HARFBUZZ with Qt >= 5.4
Fixes #1948
2016-09-16 08:35:17 +02:00
Florian Bruhin
e5b3880b71 Check for spaces in URLs with explicit scheme
Fixes #1954
2016-09-15 22:29:21 +02:00
Florian Bruhin
8b7c457802 Merge branch 'Kingdread-kwonly-default-fix' 2016-09-15 17:20:06 +02:00
Florian Bruhin
d0d3245d48 Remove extra blank line 2016-09-15 17:19:53 +02:00
Florian Bruhin
04a891cbf0 Merge branch 'kwonly-default-fix' of https://github.com/Kingdread/qutebrowser into Kingdread-kwonly-default-fix 2016-09-15 17:19:26 +02:00
Florian Bruhin
0d64257049 Add missing docstring 2016-09-15 17:16:30 +02:00
Florian Bruhin
0b9c3dedef Merge branch 'rcorre-completion_tests' 2016-09-15 16:47:51 +02:00
Florian Bruhin
9db3d3f7c3 Merge branch 'completion_tests' of https://github.com/rcorre/qutebrowser into rcorre-completion_tests 2016-09-15 16:47:32 +02:00
Florian Bruhin
42aa4deecd Merge branch 'rcorre-completion_split' 2016-09-15 16:46:16 +02:00
Florian Bruhin
bb1b1c8ee8 Remove unused imports 2016-09-15 16:45:48 +02:00
Florian Bruhin
018e9ef4a3 Merge branch 'completion_split' of https://github.com/rcorre/qutebrowser into rcorre-completion_split 2016-09-15 16:44:54 +02:00
Florian Bruhin
879ca0b873 Make qutescheme arg optional for resource_url 2016-09-15 16:42:07 +02:00
Daniel Schadt
eabfdb3c16 tests: make sure the type error is the one we want 2016-09-15 16:42:02 +02:00
Florian Bruhin
ac4724807a test requirements: Update pytest-xvfb to 0.3.0 2016-09-15 16:40:07 +02:00
Daniel Schadt
794eb84805 add parameter name in error message 2016-09-15 16:38:18 +02:00
Florian Bruhin
6e9501073a Remove @qtwebengine_todo for qute:settings 2016-09-15 16:13:51 +02:00
Florian Bruhin
37fa7431b0 Serve broken qutebrowser logo via qute:resources
This is needed when we want to display an error page after the user
requested a qute:// URL, as qute:// URLs can't access file:// content
with QtWebEngine.
2016-09-15 16:06:25 +02:00
Daniel Schadt
b6d9d3f955 fix tests for new "default required" policy
This test had a keyword only parameter without a default, which is now
disallowed. This caused the test to fail.
2016-09-15 15:46:26 +02:00
Daniel Schadt
0ef5d338bd make sure keyword-only arguments have a default
Fixes #1872.

This prevents inspect.Parameter.empty from slipping through to the
command.
2016-09-15 15:44:33 +02:00
Florian Bruhin
8bdcd49626 Fix lint 2016-09-15 15:10:55 +02:00
Florian Bruhin
4d6c1a6a4d Regenerate docs 2016-09-15 15:10:26 +02:00
Florian Bruhin
49615820bb Fix test path in check_coverage.py 2016-09-15 15:09:33 +02:00
Florian Bruhin
1523d512fe Update changelog 2016-09-15 15:05:07 +02:00
Florian Bruhin
035a7e3632 pip requirements: Update setuptools to 27.2.0 2016-09-15 15:01:56 +02:00
Florian Bruhin
606f4a7860 check-manifest reqs: Update check-manifest to 0.34 2016-09-15 15:01:20 +02:00
Florian Bruhin
44e8296a66 Remove environment variables from version()
We already have those in the report anyways.
2016-09-15 14:59:32 +02:00
Florian Bruhin
8403f2451f Add $PATH to crash info 2016-09-15 14:56:27 +02:00
Florian Bruhin
e338d4b49c Add MessageView tests 2016-09-15 14:51:22 +02:00
Florian Bruhin
7e30792bfe Fix lint 2016-09-15 14:51:22 +02:00
Florian Bruhin
e32bbfa8f7 Init message.global_bridge at import time 2016-09-15 14:51:22 +02:00
Florian Bruhin
43a5c46d82 Don't use @pyqtSlot for MessageMock 2016-09-15 14:51:22 +02:00
Florian Bruhin
fce9783570 Fix unit tests
Apart from changed parameters, messages now log even when messagemock is
used, so we needed to add a few caplog.at_level calls.
2016-09-15 14:51:22 +02:00
Florian Bruhin
713a74cfd4 Fix end2end tests 2016-09-15 14:51:22 +02:00
Florian Bruhin
2c98b837d5 Add config migrations 2016-09-15 14:51:21 +02:00
Florian Bruhin
e5293d34de Add missing str() calls 2016-09-15 14:51:21 +02:00
Florian Bruhin
dfac0658ae Re-add logging for messages 2016-09-15 14:51:21 +02:00
Florian Bruhin
ed4f476ab4 Get rid of queued messages and unused code 2016-09-15 14:51:21 +02:00
Florian Bruhin
a2254b671c Adjust tests/messagemock 2016-09-15 14:51:21 +02:00
Florian Bruhin
f16b96aa28 Initial implementation of new messages 2016-09-15 14:51:21 +02:00
Ryan Roden-Corrent
a7eea6a0c1 Rewrite test_on_next_prev_item after refactoring.
Check the value of the signal emitted after each one of a series of
next/prev_item calls.
2016-09-15 07:41:56 -04:00
Ryan Roden-Corrent
a9771007b1 Pass string, not index from on_selection_changed.
Simplify the CompletionWidget/Completer interface by changing
on_selection_changed to pass the newly selected text rather than the
index of the newly selected item.
This moves the logic from Completer to CompletionWidget but simplifies
the interaction between the two and makes testing easier.
2016-09-14 22:55:07 -04:00
Ryan Roden-Corrent
ac03095512 Small if-statement style tweak in Completer. 2016-09-14 22:35:05 -04:00
Ryan Roden-Corrent
6646bbfe1f Test config completion with a ValueList.
The help, section, and option completion models behavee differently
with a ValueList than with a KeyValue, but previously we only tested
KeyValue.
2016-09-14 17:26:56 -04:00
Ryan Roden-Corrent
657859524f Make completion/test_models more rigorous.
It was checking that every expected item was in the actual item list,
but not visa-versa. This meant that extra completion items could show
up without failing the test.

This caught one bad test case. Bind completion includes aliases, but
the test did not expect this.
2016-09-14 17:26:56 -04:00
Florian Bruhin
5bef7dc74c Use file with known mimetype for qutescheme test 2016-09-14 16:48:49 +02:00
Florian Bruhin
c071964091 Fix lint 2016-09-14 15:21:30 +02:00
Florian Bruhin
886103c887 Fix showing errors in the current window 2016-09-14 15:18:12 +02:00
Florian Bruhin
0c278bc31d Improve Archlinux section in stacktrace.asciidoc 2016-09-14 12:42:19 +02:00
Florian Bruhin
e2318c6ba3 Update stacktrace docs 2016-09-14 12:33:47 +02:00
Florian Bruhin
982d00ff84 Let qute:* handlers decide their mimetype
This means we have to guess less, and handlers can give us HTML as text
which we then encode for them.
2016-09-14 12:33:20 +02:00
Florian Bruhin
3a27c45ac9 More cleanup in test_webkitqutescheme 2016-09-14 12:08:35 +02:00
Florian Bruhin
5b527d0f1e Rename test_qutescheme to test_webkitqutescheme 2016-09-14 12:07:26 +02:00
Florian Bruhin
cc1e134f25 Fix test_qutescheme.py 2016-09-14 12:05:15 +02:00
Florian Bruhin
5501d90268 Fix lint 2016-09-14 12:00:29 +02:00
Florian Bruhin
c128aba27e Fix qute:* handlers in run_vulture.py 2016-09-14 11:39:19 +02:00
Florian Bruhin
0657eeb8f4 Activate QtWebEngine tests for qute:* 2016-09-14 11:14:04 +02:00
Florian Bruhin
a1527f35d4 Allow to restrict qute:* pages to a backend 2016-09-14 11:04:47 +02:00
Florian Bruhin
71bc5bb943 Move QuteSchemeError to qutescheme 2016-09-14 11:04:37 +02:00
Florian Bruhin
aa71c9ae58 Initial qute:* support for QtWebEngine 2016-09-14 10:18:25 +02:00
Florian Bruhin
4a14083507 Fix :jseval --world contitional in set_text_field
See #1942
2016-09-13 07:59:21 +02:00
Ryan Roden-Corrent
e23d611b37 Strip quotes from completion pattern.
Given a commandline like:
`:set general editor "gvim -f"|`, the pattern should be 'gvim -f'
rather than '"gvim -f"'.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
e65aba74fd Test pattern for Completion.update_completion.
In the update_completion unit test, verify the `pattern` parameter as
well as the `model`.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
b867b87955 Don't crash Completer on unknown command.
The CommandRunner's fallback parsing behavior treated whitespace
differently than the normal flow. When a user entered an unknown
command, trailing whitespace would be stripped and the cmdline length
would be less than the cursor position.

This is fixed by making the fallback use the ShellLexer just as the
'normal' parsing does.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
69a3df174d Remove needless try/catch in on_selection_changed. 2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
52fdad8186 Test on_selection_changed with maxsplit 2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
d651cc75b0 Fix flake8/pylint errors. 2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
808a645b40 Fix quick-complete highlighting quirk.
When the commandline reads ':open |', quick-completing the only offered
completion will set the commandline to ':open some_url |'. Since `open`
has `maxsplit=0`, everything after ':open' is (correctly) treated as
one argument. This means completion is opened again with 'some url '
as the pattern (note trailing whitespace), which makes the comletion
menu 'flicker' and stay open even though it was 'supposed' to quick
compelte.

This is fixed by ignoring the next completion request if we just
completed something after maxsplit (because we don't expect any more
completions after the last split).

Resolves #1519.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
fcadde6aef Merge _split into _partition in Completer.
After the refactoring, _split is only called by _partition so just make
it part of the same method. This also removes the use of
_empty_item_index, as it can be figured out on the fly.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
127412d91c Simplify update_completion.
Remove the class variables _cursor_part and _empty_item_index. Instead,
split up the commandline around the cursor whenever that information is
needed. Using locals instead of class variables makes the logic easier
to follow and ends up requiring much less code.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
581d7659ba Clean up Completer.on_selection_changed.
Remove the dependency on the class variables _empty_item_index
and _cursor_part to make the code easier to follow. If
_update_completion is refactored in a similar way these variables can
be removed.
2016-09-12 22:19:44 -04:00
Ryan Roden-Corrent
eb384fdda0 Better Completer.on_selection_changed testing.
Preparation for refactoring.
2016-09-12 22:19:44 -04:00
Florian Bruhin
e4192b5158 Yet another flaky test... 2016-09-12 22:49:55 +02:00
Florian Bruhin
1f10c7ff94 Fix broken hint test
The wait we added a few commits earlier was just plain wrong, filtering
the strings isn't going to print that, and shouldn't happen async
anyways...
2016-09-12 22:00:54 +02:00
Florian Bruhin
0b310d6910 Fix removing of a clicked download 2016-09-12 21:47:01 +02:00
Florian Bruhin
5b0fc41367 Log scroll data we got via JS 2016-09-12 21:46:51 +02:00
Florian Bruhin
11abb642ab Remove downloading test with deleting handler
This actually is kind of tricky, and it makes later tests fail because
the tmpdir is suddenly gone...
2016-09-12 20:53:01 +02:00
Florian Bruhin
54c32cc74e Fix long line 2016-09-12 20:41:51 +02:00
Florian Bruhin
07e67740cc Add missing jseval.html 2016-09-12 20:02:03 +02:00
Florian Bruhin
4b4582c452 Adjust comment in _rect_on_view_js 2016-09-12 20:00:59 +02:00
Florian Bruhin
e6680c3c60 Also redirect $HOME for QtWebEngine tests
See https://github.com/The-Compiler/qutebrowser/pull/1637#issuecomment-243043811
2016-09-12 19:55:31 +02:00
Florian Bruhin
08e95f76a6 QtWebEngine: Stabilize/reactivate two hint tests 2016-09-12 18:59:37 +02:00
Florian Bruhin
516bfb5ba3 Un-flaky another test waiting for scrolling 2016-09-12 18:58:31 +02:00
Florian Bruhin
c40325b510 Stabilize "Jumping back after searching" test
The test was flaky because waiting for scrolling didn't actually wait,
as the page logged a scroll position change to 0/0 directly after
loading.

We work around this by making the generic "And I wait until the scroll
position changed" not wait when it changed to 0/0.
2016-09-12 18:53:56 +02:00
Florian Bruhin
14de9f58b8 Fix docstring 2016-09-12 18:33:57 +02:00
Florian Bruhin
9e20e3a802 Skip :jseval with world tests for PyQt < 5.7.0 2016-09-12 18:30:49 +02:00
Florian Bruhin
8a35ebac7b Use a separate JS world for :jseval 2016-09-12 18:27:51 +02:00
Florian Bruhin
c9e3cc04cf Accept a name for --world with :jseval 2016-09-12 18:23:23 +02:00
Florian Bruhin
97edc59f03 Add some logging to argparse.multitype_conv 2016-09-12 18:22:49 +02:00
Florian Bruhin
2281f0c790 Fix :insert-text test for QtWebEngine 2016-09-12 15:59:23 +02:00
Florian Bruhin
b2608d7697 Add --world to :jseval 2016-09-12 15:59:17 +02:00
Florian Bruhin
a16c5a6a25 Add a world argument to tab.run_js_async 2016-09-12 15:59:03 +02:00
Florian Bruhin
fa78cc9f69 tests: Allow to mark JS errors as expected 2016-09-12 15:57:02 +02:00
Florian Bruhin
b645a88ade Stabilize :insert-text tests
With QtWebEngine, inserting text into the field is async, so if our
test runs too fast, it would fail. Now we instead log stuff via JS on
changes insteaad, and wait for those log messages in the tests.
2016-09-12 15:25:03 +02:00
Florian Bruhin
d988f919d7 Fix test_quteprocess.py 2016-09-12 12:01:31 +02:00
Florian Bruhin
2388489038 downloads: Be okay with the tmpdir being gone 2016-09-12 11:30:44 +02:00
Florian Bruhin
38a3d118ab Nicer linebreaking in _render_log 2016-09-12 11:24:57 +02:00
Florian Bruhin
469c75662e Fix docstring 2016-09-12 11:24:20 +02:00
Florian Bruhin
8afb02eef7 bdd: Don't log VDEBUG lines without --verbose 2016-09-12 11:23:56 +02:00
Florian Bruhin
0fef141db5 Handle QBuffer in on_feature_permission_requested 2016-09-12 09:43:08 +02:00
Florian Bruhin
32a33c26a8 Restore sys.excepthook in scripts.run_profile 2016-09-12 09:28:09 +02:00
Florian Bruhin
43b563f600 Add missing docstring 2016-09-11 21:27:16 +02:00
Florian Bruhin
7ec62c4523 Make some more things in download.py private 2016-09-11 20:58:34 +02:00
Florian Bruhin
3550d59e3a Make DownloadItem.reply private
This adds a new uses_nam method to DownloadItem though.
2016-09-11 20:58:34 +02:00
Florian Bruhin
36b7485262 Make some things in downloads.py private 2016-09-11 20:48:19 +02:00
Florian Bruhin
4a2f0eea2f Fix import order in utilcmds 2016-09-11 20:29:19 +02:00
Florian Bruhin
4537b786f5 Ignore already deleted windows in :window-only 2016-09-11 20:29:05 +02:00
Florian Bruhin
e05196c4b2 pip requirements: Update setuptools to 27.1.2 2016-09-11 20:22:56 +02:00
Florian Bruhin
94a3047df2 flake8 requirements: Update pyparsing to 2.1.9 2016-09-11 20:22:22 +02:00
Florian Bruhin
3edd6d4834 flake8 requirements: Update flake8-mock to 0.3 2016-09-11 20:22:11 +02:00
Florian Bruhin
1b5cd98d38 Fix lint 2016-09-11 20:16:03 +02:00
Florian Bruhin
8eeb3b9c75 QtWebEngine: Round scroll percentages 2016-09-11 19:59:00 +02:00
Florian Bruhin
fff777404b Use QApplication.postEvent again
We had some funny segfaults reported during scrolling (i.e. with
QApplication.sendEvent), and some code already had to use postpone=True
so there was no segfault...

So now we're back to postEvent again, and eliminated the main reason for
segfaults with it, which was re-using (and -posting) events which had
already been posted.

At least during tests this seems to run stable, let's hope it helps for
the people having crashes as well.
2016-09-11 19:37:09 +02:00
Florian Bruhin
de03feabfe Fix DownloadModel.itemFlags with invalid index 2016-09-11 17:10:52 +02:00
Florian Bruhin
4ea8584556 Update mailinglist description in quickstart docs 2016-09-11 16:30:23 +02:00
Florian Bruhin
fb8428d5ba Merge branch 'sivers-shortcutfoo' 2016-09-11 16:30:11 +02:00
Florian Bruhin
e2f2c2dac8 Regenerate authors 2016-09-11 16:29:59 +02:00
Florian Bruhin
e340cd33e3 Add a note about shortcutfoo to quickstart docs 2016-09-11 16:29:37 +02:00
Florian Bruhin
92804fc6cc Merge branch 'shortcutfoo' of https://github.com/sivers/qutebrowser into sivers-shortcutfoo 2016-09-11 16:28:22 +02:00
Florian Bruhin
8a9365f24c Merge branch 'craftyguy-windows_edits' 2016-09-11 16:27:42 +02:00
Florian Bruhin
e3820c5172 Regenerate authors 2016-09-11 16:27:32 +02:00
Florian Bruhin
be13ffeb84 Merge branch 'windows_edits' of https://github.com/craftyguy/qutebrowser into craftyguy-windows_edits 2016-09-11 16:27:20 +02:00
Florian Bruhin
d59589cbff Merge branch 'Ban3-visibility-api' 2016-09-11 16:25:37 +02:00
Florian Bruhin
41d5a9202c Update docs 2016-09-11 16:25:03 +02:00
Florian Bruhin
4d96586eb6 Merge branch 'visibility-api' of https://github.com/Ban3/qutebrowser into Ban3-visibility-api 2016-09-11 16:23:14 +02:00
Florian Bruhin
ac7ee5ed8b Stabilize :tab-clone tests
Those were flaky with QtWebEngine on OS X:
https://travis-ci.org/The-Compiler/qutebrowser/jobs/159094434
2016-09-11 16:22:20 +02:00
Florian Bruhin
0d84ea9b8a Merge branch 'Kingdread-windows-userscripts' 2016-09-11 16:16:31 +02:00
Florian Bruhin
0b816181c0 Update changelog 2016-09-11 16:16:19 +02:00
Florian Bruhin
101d30fe1e Make _get_echo_exe_path() private in bdd conftest 2016-09-11 16:15:27 +02:00
Florian Bruhin
1fe2579bb1 Merge branch 'windows-userscripts' of https://github.com/Kingdread/qutebrowser into Kingdread-windows-userscripts 2016-09-11 16:14:25 +02:00
Florian Bruhin
4686e0349b Fix lint 2016-09-11 16:06:16 +02:00
Florian Bruhin
162e6d6483 Fix closing with no last-visible-main-window
Fixes #1918
2016-09-11 16:03:15 +02:00
Florian Bruhin
11ee5befcc Fix download tests on Windows 2016-09-11 15:53:46 +02:00
Florian Bruhin
1c09649dcb Pass QNAM instead of page to DownloadManager 2016-09-11 14:58:07 +02:00
Florian Bruhin
e8f8f1e72a Add DownloadItem.remove
This also gets rid of the remove_items method and replaces it by a
simple loop. I don't think the optimization is actually needed...
2016-09-11 14:58:07 +02:00
Florian Bruhin
b332d22967 Make DownloadModel a sequence 2016-09-11 14:58:07 +02:00
Florian Bruhin
b949e4d73a Start splitting DownloadModel from DownloadManager
This mostly works, apart from remove_item/remove_items not being
available on the model.
2016-09-11 14:58:07 +02:00
Jussi Timperi
19d9ec374d Handle the missing attribute 2016-09-11 13:12:27 +03:00
Jussi Timperi
1adc308676 Access enums by their base class 2016-09-11 13:04:58 +03:00
Florian Bruhin
4c55963dc3 Fix lint 2016-09-10 17:32:04 +02:00
Jussi Timperi
6437a28184 QtWebKit: Add version checks to visibility API 2016-09-10 17:55:00 +03:00
Florian Bruhin
bd5f63db46 Make an invalid download target fatal
This should never happen, so there's no reason for it to log an error
instead of raising an exception.
2016-09-10 16:42:27 +02:00
Florian Bruhin
b2d8905d68 Remove {downloaddir} in downloads.feature
We can just use (tmpdir) instead which we already use everywhere else as
well.
2016-09-10 16:42:27 +02:00
Florian Bruhin
0ba74ad023 Add Qt model test for download model 2016-09-10 16:42:26 +02:00
Florian Bruhin
d13f88f0ac Add lots of new BDD tests for downloads 2016-09-10 16:42:26 +02:00
Florian Bruhin
dc8396986e FIx expected message in test_invocations 2016-09-10 16:42:26 +02:00
Florian Bruhin
a21cd9f56e Set remove-finished-downloads in download tests 2016-09-10 16:42:26 +02:00
Florian Bruhin
17caf80f2a bdd: Add "I wait for the javascript message" step 2016-09-10 16:42:26 +02:00
Florian Bruhin
9f1aacc4f0 Move pdfjs check to the end2end conftest 2016-09-10 16:24:31 +02:00
Florian Bruhin
cc4cd6913d Make download model qtmodeltester compliant 2016-09-10 16:24:31 +02:00
Florian Bruhin
3bf841bdb4 Delete file on infinite redirects 2016-09-10 16:24:31 +02:00
Florian Bruhin
dc0ddd023a Add logging for deleting/removing downloads 2016-09-10 16:24:31 +02:00
Jussi Timperi
13d73359d4 QtWebKit: Handle visibility API
closes #1886
2016-09-10 16:07:29 +03:00
Florian Bruhin
7f2cc5dbc3 Make remove_data in DownloadItem.cancel kw-only 2016-09-09 19:29:14 +02:00
Florian Bruhin
b39d33d5e3 Revert "Remove remove_data arg for DownloadItem.cancel"
This reverts commit ece85dc903.

It's actually needed in _ask_confirm_question...
2016-09-09 19:28:17 +02:00
Florian Bruhin
230cd40b12 Add a test for a misconfigured XDG_DOWNLOAD_DIR
See #866 and #1269.
2016-09-09 18:46:51 +02:00
Florian Bruhin
a4d0449e19 Use a shorter XDG_RUNTIME_DIR for temp_basedir_env
Otherwise with longer test names, we can't listen to the IPC server as
the filename is too long for a local socket.
2016-09-09 18:46:51 +02:00
Florian Bruhin
143a4af91b Improve :download-open tests 2016-09-09 18:46:51 +02:00
Florian Bruhin
433a8a8ced Fix filename with a misconfigured XDG_DOWNLOAD_DIR
'filename' is the relative path we got from the broken config file.
Instead of using the garbage, let's just drop it and use the suggested
name (self.basename) instead.
2016-09-09 18:46:51 +02:00
Florian Bruhin
a5793695de Mark almost-impossible check with a nocover pragma
This can only happen when running :download-open on a download created
by :adblock-update right now, which is a very small chance, so we can't
easily test for it.
2016-09-09 18:46:51 +02:00
Florian Bruhin
2df971a79c Move short_tmpdir fixture to conftest.py 2016-09-09 18:46:51 +02:00
Florian Bruhin
ece85dc903 Remove remove_data arg for DownloadItem.cancel
This was added in f0779f8cc0 but never
actually used.
2016-09-09 18:46:51 +02:00
Florian Bruhin
b5b46332c7 Add test for downloading to an inexistent dir 2016-09-09 18:46:51 +02:00
Florian Bruhin
ab30124bd0 Remove (hopefully) dead download code
If the percentage is None, remaining/total should always be None
too (as percentage/remaining being None should be triggered by total
being None).
2016-09-09 18:46:51 +02:00
Florian Bruhin
d64241bed9 Add a test for a download without content-size 2016-09-09 18:46:51 +02:00
Florian Bruhin
2177aa574c Improve download BDD tests
This reorganizes the existing tests a bit and adds some new ones.
2016-09-09 18:46:51 +02:00
Florian Bruhin
7611281563 Add basename to "download finished" message 2016-09-09 18:46:51 +02:00
Florian Bruhin
0053548036 Merge branch 'knaggita-issue1703' 2016-09-09 17:58:59 +02:00
Florian Bruhin
984e1cf3c5 Update docs 2016-09-09 17:58:35 +02:00
Florian Bruhin
864ec94cde Fix lint 2016-09-09 17:56:58 +02:00
knaggita
9ff3f6810a Remove --qt-* arguments 2016-09-09 17:55:16 +02:00
Florian Bruhin
f75f45addc Fix at_bottom scrolling check
This is a regression introduced in
b45f940e72
2016-09-09 16:03:51 +02:00
Florian Bruhin
d0cf452ec8 Remove :prompt-yes and :prompt-no
Those are replaced by :prompt-accept yes and :prompt-accept no
2016-09-09 15:59:00 +02:00
Florian Bruhin
d579697245 Add a value argument to :prompt-accept 2016-09-09 15:48:42 +02:00
Florian Bruhin
b45f940e72 Move some scroll logic from JS to Python 2016-09-09 14:19:21 +02:00
Florian Bruhin
71a89bd418 *Really* fix completion with multiple words.
Turns out re.escape also escapes spaces, so we'd need to replace '(\\ )'
groups after escaping. At this point it's easier to just combine spaces
before escaping the pattern.

Fixes #1934.
Supersedes #1935.
2016-09-09 09:03:18 +02:00
Daniel Schadt
b0114768c7 fix spawn tests on Windows
On Windows, no echo.exe exists normally, so calling echo from the tests
is no good idea, since it relies on Cygwin to be installed and in %PATH%
(so that echo.exe is available).

This fixes this by providing a small echo.bat which is callable from the
tests, and then using a platform-specific path to the executable instead
of the hardcoded "echo". This should ensure that the tests pass even on
systems where echo.exe is not installed.

Note that we can't simply use a do-nothing exe (like rundll or hh.exe),
as we're passing parameters, and those executables may behave
differently in the presence of those parameters.
2016-09-08 23:14:10 +02:00
Daniel Schadt
f6c6f766cd add newline at the end of the file 2016-09-08 23:13:00 +02:00
Clayton Craft
e9aaec6d0d Update tox.ini to support Windows, and adjust install instructions 2016-09-08 13:31:17 -07:00
Florian Bruhin
0a3853fcb7 Fix handling of spaces in completion
This is a regression introduced in
faa052ad6f.

Fixes #1934.
2016-09-08 21:59:18 +02:00
Florian Bruhin
861ce478b3 Add a 'this' pytest marker 2016-09-07 20:26:41 +02:00
Florian Bruhin
93428c4e2b Skip instead of xfail JS prompt test on WebEngine
We probably get stuck with a visual JS prompt, so for some reason the
following header tests fail.
2016-09-07 20:25:56 +02:00
Florian Bruhin
26025214ed Mark session loading tests with @qtwebengine_flaky 2016-09-07 19:03:41 +02:00
Florian Bruhin
a119e9d5b0 Mark :insert-text with undo test as xfail on OS X 2016-09-07 19:01:24 +02:00
Florian Bruhin
f8f74400c6 Fix more lint 2016-09-07 18:57:00 +02:00
Florian Bruhin
d299fd260c Fix adblock tests 2016-09-07 18:53:11 +02:00
Florian Bruhin
f3d540b375 Fix adblock tests 2016-09-07 18:47:39 +02:00
Florian Bruhin
955910a0e8 Fix lint 2016-09-07 18:45:46 +02:00
Florian Bruhin
44d1056e54 QtWebEngine: Implement custom HTTP headers 2016-09-07 18:29:38 +02:00
Florian Bruhin
5a54699863 Remove unused code from qutebrowser.browser.shared 2016-09-07 18:17:56 +02:00
Florian Bruhin
df7f74c782 Add qutebrowser.browser.shared 2016-09-07 18:17:05 +02:00
Florian Bruhin
d7f9e4735e earlyinit: Only display exception if there was one 2016-09-07 17:33:22 +02:00
Florian Bruhin
4d91ccfea5 Enforce Qt >= 5.6.0 for QtWebEngine 2016-09-07 17:31:48 +02:00
Florian Bruhin
02bd42cbed Implement adblocking for QtWebEngine 2016-09-07 17:27:21 +02:00
Florian Bruhin
6fec236757 Add some blank lines to app._init_modules 2016-09-07 16:45:46 +02:00
Florian Bruhin
3ce9e795a1 Add a simple end2end test for :adblock-update 2016-09-07 16:27:27 +02:00
Florian Bruhin
3a55dbf712 Don't use 'current' win_id for adblock update 2016-09-07 16:24:51 +02:00
Florian Bruhin
8cef35517f Add a manual test file for uploading files 2016-09-07 13:40:05 +02:00
Florian Bruhin
bac7a6eaf2 Remove BrowserPage.chooseFile
Seems like QtWebKit comes with a default implementation of that.
2016-09-07 13:39:19 +02:00
Florian Bruhin
6831177f2e Add docstring for update_3rdparty.update_ace 2016-09-07 13:02:48 +02:00
Florian Bruhin
3d9b33f6a5 Ignore ace.js for spellcheck 2016-09-07 13:01:54 +02:00
Florian Bruhin
8c3906b784 Remove BrowserPage.shouldInterruptJavaScript
This is useless due to a Qt bug anyways:
https://bugreports.qt.io/issues/?jql=text%20~%20%22shouldInterruptJavascript%22
2016-09-07 12:49:57 +02:00
Florian Bruhin
fca37abf55 QtWebEngine: Implement webelem.classes 2016-09-07 12:31:48 +02:00
Florian Bruhin
522049132b Add a test for hinting with ACE editor 2016-09-07 12:28:12 +02:00
Florian Bruhin
3e1583bb1c Make WebKitElement._is_visible private
It makes a lot of sense for this to be in webkitelem.py, but it should
not be public API as it's only used internally and can't be implemented
here with QtWebEngine.
2016-09-07 11:58:39 +02:00
Florian Bruhin
ae3b7c9f15 Remove unused imports 2016-09-07 11:51:57 +02:00
Florian Bruhin
0ff98f568c Add a webelem logger 2016-09-07 11:51:23 +02:00
Florian Bruhin
c3b80c6b5b Use double quotes for JS strings
eslint won't enforce it inside that snippet, but hey, why not?
2016-09-07 11:48:34 +02:00
Florian Bruhin
60c86a08c4 Get rid of WebElement.debug_text 2016-09-07 11:47:39 +02:00
Florian Bruhin
6635c71849 Fix test_webkitelem.py path in check_coverage 2016-09-07 11:37:31 +02:00
Florian Bruhin
2da827462e Add a test to make sure check_coverage files exist 2016-09-07 11:37:21 +02:00
Florian Bruhin
e700d11447 Add check_vanished() in webkitelem.insert_text 2016-09-07 11:29:26 +02:00
Florian Bruhin
8f9cfcf232 Get rid of webelem.run_js_async 2016-09-07 11:27:37 +02:00
Florian Bruhin
78d64f4791 Get rid of webkitelem.focus_elem 2016-09-07 11:24:28 +02:00
Florian Bruhin
c267776491 Add missing :leave-mode for insert-mode test
Otherwise we hint while still in insert mode - while this seems to work
fine, let's do things the cleaner way.
2016-09-07 11:21:27 +02:00
Florian Bruhin
948fa033c7 Implement :insert-text for QtWebEngine 2016-09-07 11:20:32 +02:00
Florian Bruhin
ee5a972069 Move auto-insert-mode handling to browsertab
This means auto-insert-mode now works correctly with QtWebEngine.
2016-09-07 10:24:27 +02:00
Florian Bruhin
2ef6423cf2 Add some QtWebEngine comments to webkit.webview 2016-09-07 10:11:01 +02:00
Florian Bruhin
02df91e369 Mark colors -> webpage.bg as QtWebKit-only 2016-09-07 09:49:37 +02:00
Florian Bruhin
919196714b QtWebEngine: Implement WebEngineScroller.at_bottom 2016-09-07 09:32:51 +02:00
Florian Bruhin
cf6cffeb08 tests: Ignore "Xlib: sequence lost" error 2016-09-06 22:10:34 +02:00
Florian Bruhin
08302c5a5f Apply @qtwebengine_flaky (too) liberally 2016-09-06 22:10:28 +02:00
Florian Bruhin
1106104700 Add a @qtwebengine_flaky marker 2016-09-06 21:43:02 +02:00
Florian Bruhin
37b1c26e1c Don't check active win for WebEngine session test 2016-09-06 21:22:50 +02:00
Florian Bruhin
e3e7366863 Make pylint shut up 2016-09-06 21:21:37 +02:00
Daniel Schadt
22ac19b151 style fixes 2016-09-06 20:33:48 +02:00
Florian Bruhin
c58a0e926f Skip scrolling tests on Qt < 5.7
This fixes tests on OS X on Travis, since Homebrew is still on Qt 5.6.
2016-09-06 20:29:58 +02:00
Florian Bruhin
22d9c49169 Stabilize scrolling in :repeat-command test 2016-09-06 19:34:38 +02:00
Florian Bruhin
010a52efb8 Stabilize :tab-detach test in invoke.feature
When we detach a tab, we need to wait until the page is actually loaded
in the newly detached tab before saving the session.
2016-09-06 19:33:09 +02:00
Florian Bruhin
c59a1535c5 Don't check active window in session test
This is flaky as we don't know which window is actually focused.
2016-09-06 19:29:12 +02:00
Daniel Schadt
0ab1902c98 add an userscript test for Windows 2016-09-06 18:41:24 +02:00
Florian Bruhin
29715ae7a7 Merge branch 'nanjekyejoannah-issue#1516' 2016-09-06 18:21:34 +02:00
Florian Bruhin
b65440e7e3 Update docs 2016-09-06 18:21:12 +02:00
Florian Bruhin
7c4548ece1 Split off _yank_url from :yank 2016-09-06 18:19:40 +02:00
nanjekyejoannah
d3e19ec8fc Add general -> yank-ignored-url-parameters 2016-09-06 18:19:40 +02:00
Florian Bruhin
e77bf62ace Remove unnecessary @qtwebengine_createWindow tags
Since we did now remove the error message, some more tests actually run
fine without the createWindow patch.
2016-09-06 18:04:54 +02:00
Daniel Schadt
1c76f121a2 userscripts: fix FIFO on Windows
The userscript FIFO on Windows suffered the same problem that open-editor
once did, because files on Windows can't be opened with write access by
two different processes. We kept the oshandle around and only closed it
when the process exited, which means that userscripts could not actually
write any commands to the FIFO.

This patch closes the file earlier, allowing the userscript to actually
write commands to it.

See also
https://lists.schokokeks.org/pipermail/qutebrowser/2016-September/000256.html
2016-09-06 18:03:53 +02:00
Florian Bruhin
80ac0c1b1b Remove createWindow error message
See https://github.com/The-Compiler/qutebrowser/issues/1911#issuecomment-244966547
2016-09-06 17:57:24 +02:00
Florian Bruhin
76176814e0 Move createWindow debug logging to the top 2016-09-06 17:56:25 +02:00
Florian Bruhin
7356e32b94 QtWebEngine: Don't search the Holy Grail 2016-09-06 17:38:13 +02:00
Florian Bruhin
921d5794a7 Add missing file 2016-09-06 17:17:12 +02:00
Florian Bruhin
fcaadb9352 Stabilize :save-session --force test 2016-09-06 17:04:13 +02:00
Florian Bruhin
c6d6483929 bdd: Show what exactly failed with InvalidLine 2016-09-06 17:00:25 +02:00
Florian Bruhin
7f013b7808 Fix lint 2016-09-06 17:00:25 +02:00
Florian Bruhin
ce1b2e6f15 quteprocess: Only wait for first about:blank load
We accidentally marked all about:blank lines as waited for...
2016-09-06 17:00:25 +02:00
Florian Bruhin
8b3517af7b bdd: Skip another flaky QtWebEngine tabs test 2016-09-06 17:00:25 +02:00
Florian Bruhin
c07ff15b9b bdd: Display milliseconds in log output 2016-09-06 17:00:25 +02:00
Florian Bruhin
52649aea70 bdd: Improve output when line was already found 2016-09-06 15:55:22 +02:00
Florian Bruhin
db7de0d619 tests: Set waited_for for initial about:blank load
Otherwise, subsequent lines where we wait for about:blank will fall back
on the older one and not actually wait.
2016-09-06 15:50:36 +02:00
Florian Bruhin
82180429ed Add missing wait in :undo test 2016-09-06 15:50:27 +02:00
Florian Bruhin
4b431fdf61 Add some more @qtwebengine_createWindow tags 2016-09-06 15:28:30 +02:00
Florian Bruhin
8a5d7455c1 Skip some broken :undo tests with QtWebEngine 2016-09-06 15:28:19 +02:00
Florian Bruhin
abdc604ead :tab-clone - restore tab zoom after history
This makes cloning the zoom work with QtWebEngine.
2016-09-06 15:15:59 +02:00
Florian Bruhin
7b9b08a167 QtWebEngine: Fix session tests 2016-09-06 15:13:43 +02:00
Florian Bruhin
85b3d08c66 bdd: Fix scrolling tests with QtWebEngine
Scrolling happens async with QtWebEngine, so we add a new log output
when the page was scrolled, and wait for that in various places.
2016-09-06 14:58:33 +02:00
Florian Bruhin
f6392d730f Stabilize test in invoke.feature
When we use about:blank, the wait doesn't actually wait (because we
already did open about:blank earlier), so we need to use another URL or
this test will be flaky.
2016-09-06 14:04:54 +02:00
Florian Bruhin
2e49368b51 Add missing @qtwebengine_createWindow tag 2016-09-06 13:56:41 +02:00
Florian Bruhin
1ed637a906 QtWebEngine: Initial session implementation 2016-09-06 13:55:35 +02:00
Florian Bruhin
4f55b435f0 Move various session unit tests to BDD tests 2016-09-06 13:55:28 +02:00
Florian Bruhin
3b16e171cb Avoid calling str() on bytes in mainwindow.py 2016-09-06 12:35:52 +02:00
Florian Bruhin
f6ba859896 Move tabhistory.TabHistoryItem to misc.sessions
This makes browser.webkit.tabhistory contain only QtWebKit-specific
code.
2016-09-06 09:50:55 +02:00
Florian Bruhin
9f5c8957aa travis: Re-enable OS X tests 2016-09-06 09:34:18 +02:00
Florian Bruhin
108c091894 Get rid of test_smoke.py
If anything is broken in those tests, other tests are going to be broken
as well, so this is just a waste of time.
2016-09-06 08:05:23 +02:00
Florian Bruhin
26aeff2332 testprocess: Don't fail if it was never started 2016-09-06 08:05:23 +02:00
Florian Bruhin
d819ce1b18 Read --qute-bdd-webengine in test_invocations.py 2016-09-06 08:05:16 +02:00
Florian Bruhin
1123a25668 travis: Add --qute-bdd-webengine on OS X 2016-09-05 23:14:33 +02:00
Florian Bruhin
cf44019475 Don't require QtWebEngine for history tests 2016-09-05 22:25:20 +02:00
Florian Bruhin
2658b7c4e7 pastebin: Accept HTTPS URLs
This will let us switch the URLs the pastebin returns to HTTPS some
day...
2016-09-05 22:06:26 +02:00
Florian Bruhin
ff5bfced9d Skip flaky QtWebEngine :forward test 2016-09-05 22:05:12 +02:00
Florian Bruhin
5fff70f879 flake8: Disable invalid naming for some modules 2016-09-05 21:35:27 +02:00
Florian Bruhin
1e0f97b64d pylint: Disable invalid-name in helpers/fixtures 2016-09-05 21:32:45 +02:00
Florian Bruhin
c503c2953d Make testbrowser.py run without QtWebKit 2016-09-05 18:50:39 +02:00
Florian Bruhin
7592345b6e Make unittests work without QtWebKit 2016-09-05 18:45:50 +02:00
Florian Bruhin
3b8537ff26 Make webkitelem/mhtml imports optional in commands 2016-09-05 18:20:48 +02:00
Florian Bruhin
bf3cccfe56 Make QWebPage import in commands.py optional 2016-09-05 18:15:30 +02:00
Florian Bruhin
1773c1cbd6 Remove wrong @pyqtSlot in downloads.py 2016-09-05 18:14:50 +02:00
Florian Bruhin
5f58ebebbf Remove needs_js for @cmdutils.register
This gets rid of a QtWebKit import in commands.py, and also makes those
checks work later when we have per-domain settings.
2016-09-05 18:11:01 +02:00
Florian Bruhin
af40abd3b2 Add websettings.shutdown() 2016-09-05 17:58:56 +02:00
Florian Bruhin
0ad8578aa8 Make QtWebKit optional in earlyinit.py 2016-09-05 17:58:29 +02:00
Florian Bruhin
050507c0a6 Merge branch 'webengine-createwindow' 2016-09-05 17:42:15 +02:00
Florian Bruhin
59300cb71e Add tests for js-can-open-windows-automatically 2016-09-05 17:25:52 +02:00
Florian Bruhin
0b3656c446 tests: Don't wait for nonexistant log message 2016-09-05 17:25:41 +02:00
Florian Bruhin
525d5ce922 Mark another flaky test with @qtwebengine_skip 2016-09-05 17:10:30 +02:00
Florian Bruhin
308f38ab34 Rename javascript-can-open-windows setting
Fixes #1896.
2016-09-05 17:09:14 +02:00
Florian Bruhin
d71aa2c0ba Ignore IMAGEFORMAT_WHITELIST warning in tests 2016-09-05 17:01:55 +02:00
Florian Bruhin
d2a3541d6e Make pylint shut up 2016-09-05 16:54:31 +02:00
Florian Bruhin
22be46e7d3 Skip flaky QtWebEngine test 2016-09-05 16:53:27 +02:00
Florian Bruhin
f26ce3a8ff Only add BDD markers if condition matches
This should make multiple markers on the same test work correctly.
2016-09-05 16:49:17 +02:00
Florian Bruhin
bdc1885f6d Add missing @qtwebengine_createWindow marker 2016-09-05 16:48:21 +02:00
Florian Bruhin
a94cf90842 Fail early when running WebEngine tests without it 2016-09-05 16:33:06 +02:00
Florian Bruhin
61270b8f92 Fix lint 2016-09-05 16:21:30 +02:00
Florian Bruhin
ba718a2b9d end2end: Improve output when subprocess exits
We don't really have the "infrastructure" set up yet to have proper log
output at that point, but we can always just show the log output as part
of the exception.
2016-09-05 16:19:22 +02:00
Florian Bruhin
baf6bb5514 Pass $QUTE_BDD_WEBENGINE to Docker correctly 2016-09-05 16:00:23 +02:00
Florian Bruhin
c6142df3ec bdd: Re-add test for #906 for QtWebEngine 2016-09-05 15:53:31 +02:00
Florian Bruhin
6151a5faa7 bdd: Fix handling of @qtweb{kit_engine}_* tags 2016-09-05 15:53:19 +02:00
Florian Bruhin
21fe8f43f9 tests: Fix handling of QUTE_BDD_WEBENGINE
The tryfirst decorator somehow messed up handling of other pytest
marks... Also we need to do this in the root conftest for it to work
properly.
2016-09-05 15:32:12 +02:00
Florian Bruhin
f2c4cedf61 QtWebEngine: Don't add invalid URLs to history 2016-09-05 15:08:00 +02:00
Florian Bruhin
8115fa2af8 Re-enable some createWindow tests 2016-09-05 15:08:00 +02:00
Florian Bruhin
a52c8d6576 Clean up javascript double-close test
The test for QtWebEngine was removed because something weird happened
with the two pytest-bdd tags, and I'm too annoyed with everything being
broken to investigate now... Future me, I'm sorry.
2016-09-05 15:08:00 +02:00
Florian Bruhin
ce98d89352 Add some (crashing...) window.open/.close tests 2016-09-05 15:08:00 +02:00
Florian Bruhin
cf89204ac3 Only skip because of QTBUG-54419 with WebEngine 2016-09-05 15:08:00 +02:00
Florian Bruhin
141b7c5893 Increase timeout in auto-follow-timeout test 2016-09-05 15:08:00 +02:00
Florian Bruhin
1c1d75e793 travis: Add a build job for QtWebEngine 2016-09-05 15:08:00 +02:00
Florian Bruhin
ebf093bb6e tests: Skip unittests with QUTE_BDD_WEBENGINE 2016-09-05 15:08:00 +02:00
Florian Bruhin
aec0e4ca40 tests: Fix applying of end2end marker 2016-09-05 15:08:00 +02:00
Florian Bruhin
19ac488997 tests: Add QUTE_BDD_WEBENGINE environment variable 2016-09-05 15:08:00 +02:00
Florian Bruhin
cf070d48f2 WebEngine: Disable createWindow for Qt < 5.7.1
Fixes #1911.

The bugfix is backported in my qt5-webengine-debug package, and
QUTE_QTBUG54419_PATCHED can be set to force qutebrowser to use
createWindow.
2016-09-05 15:08:00 +02:00
Florian Bruhin
6a26907ded Fix lint 2016-09-05 15:08:00 +02:00
Florian Bruhin
2c2375ff18 Add a separate QtWebEngine test for #906 2016-09-05 15:08:00 +02:00
Florian Bruhin
30327b2acf Move end2end tag handling to end2end/conftest.py 2016-09-05 15:08:00 +02:00
Florian Bruhin
6c6e98aac4 Add a @qtwebkit_skip marker 2016-09-05 15:08:00 +02:00
Florian Bruhin
30c07e9b5c tests: Add url to window_open.html 2016-09-05 15:08:00 +02:00
Florian Bruhin
8b7d21876f Add debug logging to createWindow 2016-09-05 15:08:00 +02:00
Florian Bruhin
2687b59373 Code cleanup 2016-09-05 15:08:00 +02:00
Florian Bruhin
a4cd0291a6 Implement QWebEngineView.createWindow 2016-09-05 15:08:00 +02:00
Florian Bruhin
bb4d09ffd9 test requirements: Update CherryPy to 8.1.0 2016-09-05 11:08:20 +02:00
Florian Bruhin
ef4c39d7c1 Merge branch 'kobezda-open-editor-all-modes' 2016-09-05 11:00:34 +02:00
Florian Bruhin
e82a119061 Update docs 2016-09-05 11:00:22 +02:00
Florian Bruhin
a85ea92a21 Merge branch 'open-editor-all-modes' of https://github.com/kobezda/qutebrowser into kobezda-open-editor-all-modes 2016-09-05 10:59:53 +02:00
Florian Bruhin
63090df52b Merge branch 'lahwaacz-docstrings' 2016-09-05 10:58:50 +02:00
Florian Bruhin
366c230e0a Merge branch 'docstrings' of https://github.com/lahwaacz/qutebrowser into lahwaacz-docstrings 2016-09-05 10:58:39 +02:00
Ján Kobezda
da65f7234a Allow :open-editor in modes other than insert
':open-editor' can now be run in all modes.

Resolves #1902
2016-09-04 22:23:16 +02:00
Florian Bruhin
ea4f4e197f Handle elements which are out of view correctly
Fixes #1910
2016-09-04 21:09:15 +02:00
Florian Bruhin
7a98af4c2f test requirements: Update CherryPy to 8.0.1 2016-09-04 20:30:10 +02:00
Florian Bruhin
faa052ad6f Fix hang with multiple spaces in URL completion 2016-09-04 20:19:16 +02:00
Jakub Klinkovský
0764bdd50b regenerate commands.asciidoc 2016-09-02 19:53:04 +02:00
Jakub Klinkovský
cbe74f6991 fix adblock-update documentation
The tilde has to be escaped, otherwise the HTML is broken.
2016-09-02 19:52:45 +02:00
Jakub Klinkovský
3518fe19e8 move explanation of ;; to commands documentation
The note was out of place in keys.conf as it's not about keyinput. Since
we have a top-level documentation for commands now, let's keep the info
in once place. People will look there anyway for the documentation of
commands they want to bind.
2016-09-02 19:52:45 +02:00
Jakub Klinkovský
f36b8acec1 adjust wording in commands top-level documentation
There is no "commandline" for bindings in keys.conf, so describing it as
for "command arguments" should be more accurate.
2016-09-02 19:52:45 +02:00
Jakub Klinkovský
9669aca7d9 remove random description of variables in commands' docstrings
Full description is given at the top of qute://help/commands.html,
duplicating this for some commands where it might be useful is
unmaintainable.
2016-09-02 19:52:45 +02:00
Florian Bruhin
64b3980685 test requirements: Update CherryPy to 8.0.0 2016-09-02 19:13:37 +02:00
Florian Bruhin
2de3065187 Use new Docker repository 2016-09-02 19:03:13 +02:00
Florian Bruhin
6a7d03fad1 Adjust qt-debug-pkgbuild URL 2016-09-02 19:02:48 +02:00
Florian Bruhin
0763acb625 Remove misc/docker
Those now live in a separate repo:
https://www.github.com/qutebrowser/docker-travis
2016-09-02 16:48:54 +02:00
Florian Bruhin
55557b5c19 test requirements: Update pytest to 3.0.2 2016-09-02 07:00:19 +02:00
Florian Bruhin
1e601d3419 Add apikey to test_pastebin.py 2016-09-02 06:10:21 +02:00
Florian Bruhin
3f279a3a31 flake8 requirements: Update pyflakes to 1.3.0 2016-09-01 23:00:00 +02:00
Florian Bruhin
1cdf90f1c7 pastebin: Start sending API key
This is not enforced on the server yet, but this way we can do so after
a few releases (and break crash reports for older releases).
2016-09-01 22:57:35 +02:00
Florian Bruhin
44d6db4f45 QtWebEngine: Fix crash with userscript + selection
Fixes #1878

Unfortunately it seems impossible to implement a test for this, as
selection via javascript somehow doesn't trigger this.
2016-09-01 22:45:57 +02:00
Florian Bruhin
d8492fef61 Merge branch 'julianuu-test_yanking' 2016-09-01 22:05:47 +02:00
Florian Bruhin
d80ac2f129 Update authors 2016-09-01 22:05:36 +02:00
Florian Bruhin
6798583e91 Merge branch 'test_yanking' of https://github.com/julianuu/qutebrowser into julianuu-test_yanking 2016-09-01 22:05:21 +02:00
Florian Bruhin
cd975f3f07 Merge branch 'arza-zara-patch-1' 2016-09-01 22:04:33 +02:00
Florian Bruhin
b1a92c7646 Update docs 2016-09-01 22:04:21 +02:00
arza
9b6541638e Update CHANGED_KEY_COMMANDS and test_migrations for sk-keybinding. 2016-09-01 21:05:44 +03:00
arza
a90314985a Fix sk-keybinding. 2016-09-01 16:23:16 +03:00
Florian Bruhin
438a924238 Merge branch 'rokm-adwaita-fix' 2016-09-01 07:29:23 +02:00
Florian Bruhin
7499255395 Update docs 2016-09-01 07:29:13 +02:00
Florian Bruhin
02fbee0762 Merge branch 'adwaita-fix' of https://github.com/rokm/qutebrowser into rokm-adwaita-fix 2016-09-01 07:19:22 +02:00
Florian Bruhin
2157635ccc Update changelog
[ci skip]
2016-09-01 07:14:36 +02:00
Florian Bruhin
c9fbb75d4f Merge branch 'rcorre-test_completion' 2016-09-01 07:09:21 +02:00
Florian Bruhin
654260dd2e Add blank line 2016-09-01 07:09:06 +02:00
Florian Bruhin
6b31576950 Merge branch 'test_completion' of https://github.com/rcorre/qutebrowser into rcorre-test_completion 2016-09-01 07:08:10 +02:00
Florian Bruhin
f1588640a8 test requirements: Update Werkzeug to 0.11.11 2016-09-01 07:02:47 +02:00
Florian Bruhin
be129b8aad freeze: Fix pkg_resources._vendor.appdirs include 2016-09-01 07:00:26 +02:00
Ryan Roden-Corrent
24a5bffbd8 Test for completion warnings with 1 item.
Add a regression test for #1600: Warnings from completionwidget when it
only has 1 item.

Addresses #1899.
2016-08-31 22:25:34 -04:00
Ryan Roden-Corrent
48fe309a48 Regression test for repeated completion.
Add a completionwidget unit test for #1812: help completion repeatedly
completes.

Addresses #1899.
2016-08-31 22:16:26 -04:00
Florian Bruhin
e12eb28635 pylint reqs: Update uritemplate.py to 3.0.2 2016-08-31 07:22:24 +02:00
Florian Bruhin
6dace67074 freeze.py: Include pkg_resources.extern.appdirs 2016-08-30 13:23:53 +02:00
Julian Weigt
fc3c93d3dd run test for clipboard also if selection is not supported 2016-08-30 11:30:32 +02:00
Florian Bruhin
30ff2141b9 pylint reqs: Update uritemplate.py to 3.0.1
Deprecate in favor of uritemplate. This package is now a metapackage
that depends on uritemplate.
2016-08-30 06:35:48 +02:00
Florian Bruhin
bb2cddb846 pip requirements: Update setuptools to 26.1.1 2016-08-30 06:33:50 +02:00
Florian Bruhin
a8fd908143 check-manifest reqs: Update check-manifest to 0.33
Fix WindowsError due to git submodules in subdirectories
2016-08-30 06:30:17 +02:00
Rok Mandeljc
469590d4e8 TabWidget: a possible fix for #1693 - grey area under custom tabbar
Attempt to fix the issue #1693 by:
- setting the TabBarStyle to TabWidget in addition to TabBar
- chain up SE_TabWidgetTabBar requests in TabBarStyle.subElementRect
  to the super() rather than self._style, in order to avoid getting
  adwaita-specific rect sizes instead of default ones that are also
  used in rendering.
2016-08-29 14:11:34 +02:00
Florian Bruhin
0b7a71e18e Add Qt Quick for Docker images
This is needed for #1891
2016-08-29 13:39:40 +02:00
Derek Sivers
21d4f22499 link to shortcutFoo training course 2016-08-29 18:58:05 +12:00
Florian Bruhin
bfbb2cc11f requirements: Update PyYAML to 3.12
- Wheel packages for Windows binaries.
- Adding an implicit resolver to a derived loader should not affect the
  base loader.
- Uniform representation for OrderedDict? across different versions of
  Python.
- Fixed comparison to None warning.
2016-08-29 07:31:31 +02:00
Florian Bruhin
8bbadc79a0 Merge branch 'mlochbaum-auto-open-fixes' 2016-08-29 07:16:53 +02:00
Florian Bruhin
343630ef46 Update docs 2016-08-29 07:14:44 +02:00
Florian Bruhin
b9282587d0 Merge branch 'auto-open-fixes' of https://github.com/mlochbaum/qutebrowser into mlochbaum-auto-open-fixes 2016-08-29 07:12:14 +02:00
Florian Bruhin
074a5f86a2 Merge branch 'lahwaacz-settings' 2016-08-29 07:09:29 +02:00
Florian Bruhin
1c0cbc3269 Improve qute:settings tests 2016-08-29 07:09:14 +02:00
Florian Bruhin
5917f34eab Merge branch 'settings' of https://github.com/lahwaacz/qutebrowser into lahwaacz-settings 2016-08-29 06:52:17 +02:00
Jakub Klinkovský
b272fce2cf fix test for setting an invalid value via qute://settings 2016-08-26 15:33:35 +02:00
Jakub Klinkovský
9ff945c56f add tests for qute://settings 2016-08-26 14:51:40 +02:00
Florian Bruhin
187bfa8fce tests: Use pytest_register_assert_rewrite 2016-08-26 06:22:03 +02:00
Florian Bruhin
553eaee467 Fix pylint false-positive 2016-08-26 05:21:10 +02:00
Florian Bruhin
9f234d21c8 Merge branch 'ryanjmortenson-format-debug-log-level' 2016-08-25 23:17:54 +02:00
Florian Bruhin
7364793ea5 Regenerate authors 2016-08-25 23:17:48 +02:00
Florian Bruhin
2408d76e4c Improve get_console_format docstring 2016-08-25 23:17:10 +02:00
Florian Bruhin
29778bb799 Merge branch 'format-debug-log-level' of https://github.com/ryanjmortenson/qutebrowser into ryanjmortenson-format-debug-log-level 2016-08-25 23:16:36 +02:00
Florian Bruhin
899c819d8c Merge branch 'knaggita-issue1867' 2016-08-25 23:13:50 +02:00
Florian Bruhin
bce5d0f7cc Regenerate authors 2016-08-25 23:13:28 +02:00
Florian Bruhin
76a3bdd94a Improve message for invalid --logfilter 2016-08-25 23:12:51 +02:00
Florian Bruhin
99daa9e165 Merge branch 'issue1867' of https://github.com/knaggita/qutebrowser into knaggita-issue1867 2016-08-25 23:11:35 +02:00
Florian Bruhin
2650d9350d bdd: Improve webserver error on unexpected status
pytest 3.0 removed the assertion reinterpretation which made this nice:
https://github.com/pytest-dev/pytest/issues/1871
2016-08-25 22:58:14 +02:00
Florian Bruhin
be7abb53ad cmdutils: Assert on positional-only params 2016-08-25 22:16:25 +02:00
Florian Bruhin
8823ed2821 Improve cmdutils tests
This would have caught 12061b8bb1.
2016-08-25 22:16:25 +02:00
Florian Bruhin
943dc564b2 Fix choices validation with unannotated args
Something like:

    @cmdutils.argument('foo', choices=['one', 'two'])
    def func(foo):
        # ...

didn't actually validate the foo argument, since the inferred type of
the argument is None, and that skipped all conversion (and thus
validation).

Fixes #1871
See #1885

This is a reworked version of 12061b8bb1
which lets special parameters (count/win_id/flags) through correctly.
2016-08-25 22:16:25 +02:00
Florian Bruhin
ce4dcf9e80 test requirements: Update pytest-repeat to 0.4.1 2016-08-25 21:19:45 +02:00
Julian Weigt
853e75e3db Split test for yanking 2016-08-25 13:41:47 +02:00
knaggita
d26566a1f6 Validate loggernames passed to --logfilter 2016-08-24 18:56:18 +03:00
Julian Weigt
193d219eaf Added test for yanking 2016-08-24 17:39:52 +02:00
rmortens
384e3d1d88 Add change format for debug-log-level cmd 2016-08-24 08:40:11 -06:00
knaggita
0b60d28742 Validate loggernames passed to --logfilter 2016-08-24 17:09:34 +03:00
knaggita
cf1dc28214 Validate logger names passed to --logfilter 2016-08-24 16:12:32 +03:00
knaggita
848af2e294 Validation of logger names passed to --logfilter 2016-08-24 15:15:20 +03:00
Florian Bruhin
6b4f719897 Revert "tests: Add a autouse fixture as workaround"
This reverts commit 853f4cd9d8.
2016-08-24 07:23:00 +02:00
Florian Bruhin
c2a1231f47 test requirements: Update pytest to 3.0.1
Fixes various 3.0.0 regressions.
2016-08-24 07:22:36 +02:00
Florian Bruhin
445d287955 Revert "Fix choices validation with unannotated args"
This reverts commit 12061b8bb1.
2016-08-23 23:34:02 +02:00
Florian Bruhin
e4008c4e08 Merge branch 'julianuu-test_no_dict' 2016-08-23 23:09:13 +02:00
Florian Bruhin
778d96c3c6 Regenerate authors 2016-08-23 23:09:04 +02:00
Florian Bruhin
8c9bf96435 Merge branch 'test_no_dict' of https://github.com/julianuu/qutebrowser into julianuu-test_no_dict 2016-08-23 23:08:51 +02:00
Florian Bruhin
12061b8bb1 Fix choices validation with unannotated args
Something like:

    @cmdutils.argument('foo', choices=['one', 'two'])
    def func(foo):
        # ...

didn't actually validate the foo argument, since the inferred type of
the argument is None, and that skipped all conversion (and thus
validation).

Fixes #1871
See #1885
2016-08-23 22:01:21 +02:00
Florian Bruhin
8643f6f28d Add explicit else in :completion-item-focus
See #1885
2016-08-23 20:49:56 +02:00
Florian Bruhin
64a61ce07f Merge branch 'pytest30' 2016-08-23 09:03:24 +02:00
Florian Bruhin
a17b8bec90 Don't treat "Hello." as URL with auto-search=naive 2016-08-23 09:02:39 +02:00
Florian Bruhin
f45c4d73f4 Split test_is_url into three separate tests 2016-08-23 08:07:45 +02:00
Florian Bruhin
703c4e1973 Fix comma in stacktrace.asciidoc 2016-08-23 07:49:13 +02:00
Florian Bruhin
42b177474a flake8: Ignore E731 (do not assign a lambda expr) 2016-08-23 07:47:48 +02:00
Florian Bruhin
77aa8b4337 pylint: Use ignored-modules for pytest
See https://github.com/PyCQA/astroid/pull/357
2016-08-23 07:45:31 +02:00
Florian Bruhin
3b6286f71a Remove old pylint suppression for ssl.PROTOCOL_* 2016-08-23 07:45:15 +02:00
Florian Bruhin
23c4c89a0f tests: Set __tracebackhide__ to a callable
This allows us to only filter the exceptions we actually want to hide.

See #1877
2016-08-23 07:28:08 +02:00
Jakub Klinkovský
1411c287c5 qute://settings: set valid type of <input> fields
fixes #1883
2016-08-22 21:09:57 +02:00
Marshall Lochbaum
44411e02c6 Replace != with (is not) when testing whether a model is new 2016-08-22 13:02:13 -04:00
Florian Bruhin
0c6574afb1 Replace py.test with pytest
See #1877
2016-08-22 07:41:10 +02:00
Florian Bruhin
df3733af54 tests: Use pytest.fixture instead of yield_fixture
See #1877
2016-08-22 07:40:24 +02:00
Florian Bruhin
4658bdcacf Use pytest.approx in tests.helpers.utils
See #1877
2016-08-22 07:39:11 +02:00
Florian Bruhin
853f4cd9d8 tests: Add a autouse fixture as workaround
This is a workaround for
https://github.com/pytest-dev/pytest/issues/1832
2016-08-22 07:24:17 +02:00
Florian Bruhin
80a3920aad Revert "Revert "tests: Use getfixturevalue""
This reverts commit c8fe21c85f.
2016-08-22 07:24:17 +02:00
Florian Bruhin
1bb8ab08fc Revert "Revert "test requirements: Update to pytest 3.0""
This reverts commit 762e13c870.
2016-08-22 07:24:17 +02:00
Marshall Lochbaum
2aef26c58b Linting 2016-08-21 23:22:46 -04:00
Marshall Lochbaum
994c6e35d9 Test completion show when calling next with no completion 2016-08-21 23:05:56 -04:00
Marshall Lochbaum
fb9867b6a7 Add tests for completion show with no rows 2016-08-21 22:57:16 -04:00
Marshall Lochbaum
cbecd48871 Refactor Completer/CompletionView interface, removing set_pattern() 2016-08-21 22:56:18 -04:00
Florian Bruhin
29898751dc Update INSTALL for OpenBSD 2016-08-21 22:16:51 +02:00
Julian Weigt
be89e8f499 Add check that qutebrowser defaults to letter hints 2016-08-21 19:37:30 +02:00
Florian Bruhin
c8fe21c85f Revert "tests: Use getfixturevalue"
This reverts commit 961d33b712.
2016-08-21 16:59:54 +02:00
Florian Bruhin
762e13c870 Revert "test requirements: Update to pytest 3.0"
This reverts commit a5e4e88ac8.
2016-08-21 16:59:52 +02:00
Florian Bruhin
961d33b712 tests: Use getfixturevalue
See #1877
2016-08-21 16:18:33 +02:00
Florian Bruhin
a5e4e88ac8 test requirements: Update to pytest 3.0
See #1877
2016-08-21 16:17:16 +02:00
Florian Bruhin
d21e482964 pip requirements: Update setuptools to 26.0.0 2016-08-21 16:12:07 +02:00
Julian Weigt
f98ba7ba0e Added test for empty dictionary 2016-08-21 15:33:55 +02:00
Florian Bruhin
4271e27672 Add OpenBSD to INSTALL 2016-08-21 15:16:13 +02:00
Florian Bruhin
618a9cbc57 Fix lint 2016-08-20 22:57:09 +02:00
Florian Bruhin
bd53d4a410 tests: Clean up test_utils 2016-08-20 22:39:53 +02:00
Florian Bruhin
5bdeacd772 tests: Clean up test_config 2016-08-20 22:26:32 +02:00
Florian Bruhin
cfbd02eaba tests: Clean up test_column_widths 2016-08-20 22:08:07 +02:00
Florian Bruhin
4c2b64b573 tests: Clean up test_http 2016-08-20 22:07:12 +02:00
Florian Bruhin
794bdf54a3 tests: Clean up test_log 2016-08-20 21:57:52 +02:00
Florian Bruhin
e447e2de65 pylint-master requirements: Add editdistance 2016-08-20 20:54:22 +02:00
Florian Bruhin
c7abed7718 pylint requirements: Update uritemplate to 2.0.0
Relicense uritemplate.py as Apache 2 and BSD
2016-08-20 20:49:48 +02:00
Florian Bruhin
d51097972d pip requirements: Update setuptools to 25.4.0 2016-08-20 20:48:53 +02:00
Marshall Lochbaum
e4cec43cf4 Add quick-complete to completion widget tests 2016-08-20 01:27:39 -04:00
Marshall Lochbaum
2db0ec8b6d Fix test_completion_show name and docstring 2016-08-20 01:13:32 -04:00
Marshall Lochbaum
64d53e4cf9 Add unit test for completion show 2016-08-20 01:01:38 -04:00
Marshall Lochbaum
c5ca102d93 Fix completion flicker on quick-complete with show=auto 2016-08-20 01:01:12 -04:00
Marshall Lochbaum
08b348be50 Merge branch 'master' into auto-open-fixes 2016-08-19 22:50:26 -04:00
Florian Bruhin
679165ebab Remove unneeded import 2016-08-19 19:02:12 +02:00
Florian Bruhin
99c2f8eca5 Add missing import 2016-08-19 19:02:02 +02:00
Florian Bruhin
2946290df9 pylint requirements: Update uritemplate to 1.0.1
- Fix some minor packaging problems.
2016-08-19 18:54:25 +02:00
Florian Bruhin
fe11e25430 Ignore mouse events going to non-main widgets
When we hide the context menu on QtWebEngine, we get a mouse event
relative to the QMenu in the filter, which means tab.elements.at_pos
will get called with a negative position (and thus assert) or at least a
wrong position.
2016-08-19 18:38:07 +02:00
Florian Bruhin
dec0f0753d Relax the checking in :view-source test 2016-08-19 17:22:07 +02:00
Florian Bruhin
003952748b Turn on BDD tests for pytest 3.0 again
pytest-bdd is fixed in the respective PR
2016-08-19 17:17:08 +02:00
Florian Bruhin
bcb06f0cc6 Fix lint 2016-08-19 15:47:35 +02:00
Florian Bruhin
1cfadbf034 Fix / ? : bindings
This was broken in #1859 and I didn't notice...
2016-08-19 15:35:20 +02:00
Florian Bruhin
60001ec8b1 Merge branch 'knaggita-issue52' 2016-08-19 15:28:18 +02:00
Florian Bruhin
e074192cc4 Update docs 2016-08-19 15:27:56 +02:00
Florian Bruhin
5367434a13 Add a unit test for :debug-log-filter 2016-08-19 15:20:08 +02:00
Florian Bruhin
7e3d1ccd24 Simplify :debug-log-filter implementation 2016-08-19 15:08:15 +02:00
Florian Bruhin
e1cd905163 Move :window-only below :debug-log-* in utilcmds 2016-08-19 15:06:08 +02:00
Florian Bruhin
3b897d6a64 bdd: Move :debug-log-* near :log-capacity tests 2016-08-19 15:05:45 +02:00
Florian Bruhin
6781f6409b bdd: Test :debug-log-capacity with negative value 2016-08-19 15:05:20 +02:00
Florian Bruhin
33e71525ed bdd: Test :debug-log-filter with invalid filter 2016-08-19 15:04:11 +02:00
Florian Bruhin
71b0876188 Improve :debug-log-filter message
This changes the message so it resembles the default choices=... one,
and also changes the argument to "filters" because that sounds nicer as
a metavar.
2016-08-19 15:03:19 +02:00
Florian Bruhin
fd0965703e Remove log.change_loglevel 2016-08-19 14:57:55 +02:00
Florian Bruhin
75c3b1a9f8 Fix test for :debug-log-level with invalid level
Since we're getting dictionary keys in choices=..., we need to sort them
so we get a consistent message.
2016-08-19 14:57:21 +02:00
Florian Bruhin
37758131f5 Delete broken :debug-log-{filter,level} tests 2016-08-19 14:43:42 +02:00
knaggita
bd6f4ae7c0 Add end2end tests issue52 2016-08-19 14:21:06 +02:00
knaggita
1d5a3a6175 Add :debug-loglevel :debug-logfilter commands 2016-08-19 14:12:19 +02:00
Florian Bruhin
d25fde4f29 Whoops... 2016-08-19 13:42:38 +02:00
Florian Bruhin
b6f35a52cd Merge branch 'nanjekyejoannah-issue#672' 2016-08-19 13:41:33 +02:00
Florian Bruhin
5a3328d834 Update docs 2016-08-19 13:41:21 +02:00
Florian Bruhin
29cd878902 Fix lint 2016-08-19 13:40:21 +02:00
nanjekyejoannah
056c0c3c14 Make command keys configurable
Fixes #672
2016-08-19 13:40:21 +02:00
Florian Bruhin
8eb8039370 Merge branch 'rewrite-pP' of https://github.com/blyxxyz/qutebrowser into blyxxyz-rewrite-pP 2016-08-19 13:36:33 +02:00
Florian Bruhin
b5444338ba Fix lint 2016-08-19 13:35:39 +02:00
Florian Bruhin
f7a7e82939 bdd: Skip another flaky backforward test with qtwe 2016-08-19 13:15:45 +02:00
Florian Bruhin
2eae6a0603 bdd: Wait less for xfailing tests
We now divide all timeouts by ten for xfailing tests, with the hope to
still catch newly passing tests, but not spend too much time waiting.

With a quick test, this reduced the testsuite run length from 12 to
7-8 minutes.
2016-08-19 13:11:29 +02:00
Florian Bruhin
362c23692a Change quteproc._request back to quteproc.request
Otherwise our per-test quteproc fixture wouldn't set the 'request'
object properly from the outside, and quteproc always had a module as
request.node.
2016-08-19 13:05:59 +02:00
Florian Bruhin
8378e16139 Fix ignored tag in misc.feature
Seems like pytest-bdd ignores that second tag...
2016-08-19 12:20:23 +02:00
Florian Bruhin
6cd890aa19 bdd: Set request object on QuteProc 2016-08-19 12:15:50 +02:00
Florian Bruhin
c0c3279424 Fix test_quteprocess.test_set with QtWebEngine
network -> accept-language is not available for QtWebEngine, and we
simply need a setting which accepts an arbitrary string.
2016-08-19 11:25:59 +02:00
Florian Bruhin
388d771a2e Use send_event with postpone=True in webelem.click
For some reason, since 0557fea79e we're
getting segfaults in misc.feature...
2016-08-19 10:23:10 +02:00
Florian Bruhin
4362d42c50 Add postpone argument to AbstractTab.send_event 2016-08-19 10:13:07 +02:00
Florian Bruhin
a846a5b89f Move send_event to AbstractTab
This means subclasses only need to implement _event_target.
2016-08-19 10:12:57 +02:00
Florian Bruhin
a40dd7edf6 Allow empty string for tabs -> title-format 2016-08-19 08:31:36 +02:00
Florian Bruhin
3d1859b13e Fix lint 2016-08-19 00:05:56 +02:00
Florian Bruhin
a88adcca17 bdd: Stop checking requests in yankpaste.feature
It's not needed and only makes the test more unreliable (e.g. flaky with
QtWebEngine)
2016-08-18 23:58:33 +02:00
Florian Bruhin
044b3df872 bdd: Skip another flaky test for QtWebEngine 2016-08-18 23:47:27 +02:00
Florian Bruhin
fa0bde631d bdd: at_top is actually implemented (scroll) 2016-08-18 23:47:09 +02:00
Florian Bruhin
ea0f137fd1 bdd: Tag flaky backforward test qtwebengine_skip 2016-08-18 23:33:56 +02:00
Florian Bruhin
44c74c0887 tests: Mark test_mhtml_e2e as qtwebengine_todo 2016-08-18 23:32:26 +02:00
Florian Bruhin
914ce85780 tests: Fix quteproc_new fixture 2016-08-18 23:31:18 +02:00
Florian Bruhin
33755b09df Skip :insert-text in test_insert_mode in webengine 2016-08-18 23:30:35 +02:00
Florian Bruhin
4d1ae999c6 tests: Allow to mark files as qtwebengine_todo 2016-08-18 23:28:37 +02:00
Florian Bruhin
322a4323cb Improve file validating in test_hints 2016-08-18 23:28:27 +02:00
Florian Bruhin
1eb0eabdab test_hints_html: Split off _parse_file 2016-08-18 23:14:21 +02:00
Florian Bruhin
63cc73d56d Try to make test_hints work with QtWebEngine 2016-08-18 23:10:37 +02:00
Florian Bruhin
94e3d7b050 Mark test_dirbrowser as qtwebengine_skip 2016-08-18 23:05:31 +02:00
Florian Bruhin
339ac42623 bdd: Mark :insert-text tests as @qtwebengine_todo 2016-08-18 23:04:03 +02:00
Florian Bruhin
d2f69db0ff bdd: Mark qute:bookmarks tests as qtwebengine_todo 2016-08-18 23:00:10 +02:00
Florian Bruhin
63628d2f97 bdd: Wait for any focus object in tabs.feature
With QtWebEngine, we get a "Focus object changed" logged pointing to the
QOpenGLWidget, not the tab.
2016-08-18 22:57:21 +02:00
Florian Bruhin
50031c5aae bdd: xfail in check_open_tabs for QtWebEngine 2016-08-18 22:54:41 +02:00
Florian Bruhin
15f142880e bdd: Mark qute:settings test as @qtwebengine_todo 2016-08-18 22:52:36 +02:00
Florian Bruhin
1763f9bb58 bdd: Mark search/sessions as qtwebengine_todo 2016-08-18 22:50:57 +02:00
Florian Bruhin
2969d3dc91 bdd: Mark prompt.feature as TODO on QtWebEngine 2016-08-18 22:47:11 +02:00
Florian Bruhin
84b8ea856d bdd: Skip :scroll-page+navigate tests on webengine 2016-08-18 22:46:48 +02:00
Florian Bruhin
8da942ddc7 bdd: Skip tests on WebEngine causing memory leaks 2016-08-18 22:46:32 +02:00
Florian Bruhin
1c581cf1cf quteproc: Ignore failing messages on xfail
When a test calls pytest.xfail it might stop early, so the message
doesn't get marked as ignored.
2016-08-18 22:23:29 +02:00
Florian Bruhin
d5131aa0a4 navigate.feature: Add @qtwebengine_todo 2016-08-18 22:23:11 +02:00
Florian Bruhin
69514df126 hints.feature: Skip flaky test on QtWebEngine 2016-08-18 22:22:56 +02:00
Florian Bruhin
0557fea79e Use QApplication.sendEvent instead of postEvent
From the QApplication.postEvent docs:
http://doc.qt.io/qt-5/qcoreapplication.html#postEvent

  The event must be allocated on the heap since the post event queue
  will take ownership of the event and delete it once it has been
  posted. It is not safe to access the event after it has been posted.

We can't reliably guarantee that from Python, so we need to use
sendEvent instead.
2016-08-18 21:36:43 +02:00
Florian Bruhin
25faa04196 bdd: Add qtwebengine tags in misc.feature 2016-08-18 20:34:03 +02:00
Florian Bruhin
ec59bfb584 bdd: Handle @qtwebengine_skip tag 2016-08-18 20:33:53 +02:00
Florian Bruhin
ccc676c04f Handle CommandError in show_source_cb 2016-08-18 19:32:16 +02:00
Florian Bruhin
788eebc1ad bdd: Ignore "Running without the SUID sandbox!" 2016-08-18 19:29:34 +02:00
Florian Bruhin
577f1b850a bdd: Make :jseval tests work with QtWebEngine 2016-08-18 19:26:50 +02:00
Florian Bruhin
d298787b1a bdd: Make marks.feature work with QtWebEngine 2016-08-18 19:22:18 +02:00
Florian Bruhin
105c1952a8 bdd: Skip scroll checks with QtWebEngine 2016-08-18 19:20:48 +02:00
Jan Verbeek
b6c96855c8 Rewrite paste -s/pP 2016-08-18 19:05:35 +02:00
Florian Bruhin
c0ffcfc585 QtWebEngine: Make :fake-key work 2016-08-18 18:44:33 +02:00
Florian Bruhin
2cbaf0ccb3 Add @qtwebengine_todo in javascript.feature 2016-08-18 18:44:07 +02:00
Florian Bruhin
e477b810bd bdd: Mark backforwards test as qtwebengine_todo 2016-08-18 18:29:10 +02:00
Florian Bruhin
0c50e7dfb9 WebEngine: Don't bother running downloads.feature 2016-08-18 18:28:41 +02:00
Florian Bruhin
f03cd5022e pylint doesn't know pytest.xfail 2016-08-18 18:27:24 +02:00
Florian Bruhin
ab4e442602 QtWebEngine: Don't bother running caret.feature 2016-08-18 18:26:31 +02:00
Florian Bruhin
001e839ca9 Remove qtwebengine_todo for backforward.feature 2016-08-18 18:22:44 +02:00
Florian Bruhin
2d97ffa323 bdd: xfail in compare_session with WebEngine 2016-08-18 18:20:25 +02:00
Florian Bruhin
e950b09027 tests: Get history.feature to work with WebEngine 2016-08-18 18:17:01 +02:00
Florian Bruhin
8d381aaa01 tests: Improve @qtwebengine_* markers
This uses xfail for @qtwebengine_todo and adds a new @qtwebengine_skip
marker.
2016-08-18 18:16:33 +02:00
Florian Bruhin
dfed2f9c9c WebEngine: Don't save title if generated from URL 2016-08-18 18:05:48 +02:00
Florian Bruhin
4b7a3db0eb tests: QtWebEngine: Make hints.feature work 2016-08-18 17:50:52 +02:00
Florian Bruhin
2a0e503644 QtWebEngine: Don't raise CommandError with no hint 2016-08-18 17:47:05 +02:00
Florian Bruhin
0b9aec873f tests: Accept HTTP "not modified" as status
It seems like QtWebEngine sends some caching headers QtWebKit didn't?
2016-08-18 17:44:35 +02:00
Florian Bruhin
5e8254d470 bdd: Mark some hint tests as @qtwebengine_todo 2016-08-18 17:43:50 +02:00
Florian Bruhin
3dccd15663 bdd: Handle @qtwebengine_todo tags 2016-08-18 17:41:34 +02:00
Florian Bruhin
745614e45d BDD: Wait until hints are ready after hinting
With QtWebEngine, hinting happens async, so we need to wait for
"hints: ..." in the log before we can actually follow a hint.
2016-08-18 17:21:50 +02:00
Florian Bruhin
d7110069bb Fix broken :repeat-command test 2016-08-18 16:58:56 +02:00
Florian Bruhin
205c12c530 Fix docs for :click-element 2016-08-18 16:58:56 +02:00
Florian Bruhin
927f378c6d Fix eslint 2016-08-18 16:52:53 +02:00
Florian Bruhin
73210fb87c QtWebEngine: Fix tab passed to WebEngineElement 2016-08-18 16:25:58 +02:00
Florian Bruhin
a06dcc7f0b BDD: Use :click-element instead of hints 2016-08-18 16:25:58 +02:00
Florian Bruhin
4345d60ff1 Revert "javascript.assemble: Support document module"
This reverts commit afc7faabda.

This isn't actually needed as we can't use document.getElementById()
directly without serializing anyways.
2016-08-18 15:58:46 +02:00
Florian Bruhin
1956480164 Revert "Handle {} elements in elements._js_cb_single"
This reverts commit f59a9d37252599c8fbda4cc687bd9f094c6d05b9.

Since we're now using a webelem function, this isn't needed anymore.
2016-08-18 15:58:46 +02:00
Florian Bruhin
dbb3929bf3 QtWebEngine: Serialize element correctly (find_id) 2016-08-18 15:58:46 +02:00
Florian Bruhin
f98820971d Handle {} elements in elements._js_cb_single
When using document.getElementById like in find_id, we can get {}
instead of null/None back when nothing was found.
2016-08-18 15:58:46 +02:00
Florian Bruhin
d9d14d4a4c Fix lint 2016-08-18 15:58:46 +02:00
Florian Bruhin
4719e11e78 Add a test for :click-element with --target 2016-08-18 15:58:46 +02:00
Florian Bruhin
e0af03db80 Add a default target for :click-element 2016-08-18 15:58:46 +02:00
Florian Bruhin
cc9b776476 tests: Use :click-element in editor.feature 2016-08-18 15:58:40 +02:00
Florian Bruhin
0cef4ac2db Add a :click-element command 2016-08-18 15:30:04 +02:00
Florian Bruhin
28a6b3918c Fix lint 2016-08-18 14:42:42 +02:00
Florian Bruhin
e851839973 Don't make HintActions a QObject
It probably still makes sense for HintManager to be one for the moment
though, as it's in the objreg.
2016-08-18 14:39:13 +02:00
Florian Bruhin
5113fa8515 Fix test_tab 2016-08-18 14:36:56 +02:00
Florian Bruhin
0d1ea0b93a Add FIXME for webkitelem.focus_elem 2016-08-18 14:33:55 +02:00
Florian Bruhin
63c66945a4 Add webelem.click() and webelem.hover() 2016-08-18 14:32:19 +02:00
Florian Bruhin
5ac9fe9c32 Add tab.elem.find_id 2016-08-18 14:08:34 +02:00
Florian Bruhin
afc7faabda javascript.assemble: Support document module 2016-08-18 14:07:21 +02:00
Florian Bruhin
2c6fe35398 Fix blank lines 2016-08-18 14:03:27 +02:00
Florian Bruhin
a0add7b66c Get rid of tab.run_js_blocking
We had some trouble with it, and it's not actually needed.
2016-08-18 14:02:59 +02:00
Florian Bruhin
d3084dd690 Add a separate tab.elements object 2016-08-18 14:01:27 +02:00
Florian Bruhin
da73a7123c Add quteproc.click_element_by_id 2016-08-18 13:24:47 +02:00
Florian Bruhin
c37c501b25 Mark download BDD tests as TODO for QtWebEngine 2016-08-18 13:16:52 +02:00
Florian Bruhin
7515438f88 Skip back/forward BDD tests for now 2016-08-18 13:12:07 +02:00
Florian Bruhin
082fc5667e Remove requests check for :back/:forward test 2016-08-18 13:06:42 +02:00
Florian Bruhin
e10b7ba8ab tests: Add @qtwebengine_todo marker 2016-08-18 13:05:37 +02:00
Florian Bruhin
1ec59f3f0e Add FIXME 2016-08-18 12:46:55 +02:00
Florian Bruhin
0c1412a218 pylint requirements: Update uritemplate to 1.0.0 2016-08-18 12:44:13 +02:00
Florian Bruhin
939935c2d1 requirements: Update requests to 2.11.1
- Fixed a bug when using iter_content with decode_unicode=True for
  streamed bodies would raise AttributeError. This bug was introduced in
  2.11.
- Strip Content-Type and Transfer-Encoding headers from the header block
  when following a redirect that transforms the verb from POST/PUT to
  GET.
2016-08-18 12:43:48 +02:00
Florian Bruhin
2b6f4f0698 Merge branch 'webengine-hints' 2016-08-18 12:41:31 +02:00
Florian Bruhin
9226e3eece QtWebEngine: Implement only_visible for find_all 2016-08-18 12:40:21 +02:00
Florian Bruhin
30029a8259 utils.javascript: Handle bools in _convert_js_arg 2016-08-18 12:40:21 +02:00
Florian Bruhin
b596c4da27 eslint: Enable long lines with URLs 2016-08-18 12:40:21 +02:00
Florian Bruhin
274fe58d6d Simplify webelem.js
serialize_elem() now takes care of assigning IDs.
2016-08-18 12:40:21 +02:00
Florian Bruhin
0d35502e87 Use HintingError for all hinting errors 2016-08-18 12:40:21 +02:00
Florian Bruhin
eabac17c58 Combine hint signals into a single one 2016-08-18 12:40:21 +02:00
Florian Bruhin
39fd6a6062 QtWebEngine: Adjust hints according to zoom 2016-08-18 12:40:21 +02:00
Florian Bruhin
30f6afc2aa Pass tab to WebEngineElement 2016-08-18 12:40:21 +02:00
Florian Bruhin
53e747d7ea Disable download hints for QtWebEngine 2016-08-18 12:40:21 +02:00
Florian Bruhin
58d2d30e9a Add initial hinting implementation 2016-08-18 12:40:21 +02:00
Florian Bruhin
1b3d693a5e Add post_event to tab API 2016-08-18 12:40:21 +02:00
Florian Bruhin
6f24221c54 Replace WebElement.frame() by .has_frame() 2016-08-18 12:40:21 +02:00
Florian Bruhin
91b43c5cef hints: Use tab API to move cursor for input fields 2016-08-18 12:40:21 +02:00
Florian Bruhin
62db0095d1 Revert "Make webelem.rect_on_view work async"
This reverts commit 4e11613d2df064b138532c18f88bbf278c64f347.

We can actually make this synchronous just fine by collecting that
information when searching for the elements...
2016-08-18 12:40:21 +02:00
Florian Bruhin
e6d6302958 Make webelem.rect_on_view work async
WebKitElement still has an internal sync version used for is_visible,
but hopefully we can get rid of that soon too.
2016-08-18 12:40:21 +02:00
Florian Bruhin
7dadc28eb7 Handle an immediate callback in CallbackChecker 2016-08-18 12:40:21 +02:00
Florian Bruhin
359d4dd427 tests: Add a callback_checker fixture 2016-08-18 12:40:21 +02:00
Florian Bruhin
aba1556324 Remove old comment 2016-08-18 12:40:21 +02:00
Florian Bruhin
343b2d8385 Remove old FIXME 2016-08-18 12:40:21 +02:00
Florian Bruhin
15dcd5284c Enable :hint for QtWebEngine 2016-08-18 12:40:21 +02:00
Florian Bruhin
713201aa13 Merge branch 'new-hints' 2016-08-18 12:39:20 +02:00
Florian Bruhin
8eaa387f21 Adjust default hint.bg gradient orientation 2016-08-17 21:00:13 +02:00
Florian Bruhin
52e47e0c3d Add HintLabel.__repr__ 2016-08-17 15:32:24 +02:00
Florian Bruhin
955ed2f52d Simply connect HintLabel._move_to_elem to signal 2016-08-17 15:32:24 +02:00
Florian Bruhin
1d82ea8740 Remove logging in _on_contents_size_changed
Otherwise this will be logged once for every element.
2016-08-17 15:32:24 +02:00
Florian Bruhin
d87a255c0a Don't fully clean up labels if their frame is gone
Otherwise they're invalid but still in the HintContext, so calling
.hide() on it later (e.g. because the user pressed another key) would
give us a RuntimeError from PyQt.
2016-08-17 15:32:24 +02:00
Florian Bruhin
f42f54f403 Update changelog 2016-08-17 15:32:24 +02:00
Florian Bruhin
8cd822c7db Add blank lines 2016-08-17 14:51:05 +02:00
Florian Bruhin
0293307d61 Remove adjust_zoom for webelem.rect_on_view
Previously, the drawn hint labels were affected by the zoom, i.e., they
were stretched out by QtWebKit and actually had to be drawn at the
unzoomed position.

The Python/C++ API gives us coordinated adjusted for zoom, so
we always *negatively* adjusted them to get the unzoomed coordinates.

JS gave us the original coordinates, so we stretched them out according
to the zoom if adjust_zoom was given (which means only when clicking a
link).

Now we always operate in term of display coordinates: The point where we
draw the hint label is equal to the point we're clicking.

Thus, the zoom level for javascript is always adjusted, and the Python
zoom level is never (negatively) adjusted.
2016-08-17 14:51:05 +02:00
Florian Bruhin
7c17af3889 Use ${_monospace} for default hints font 2016-08-17 14:51:05 +02:00
Florian Bruhin
016349941b Update vulture whitelist 2016-08-17 14:51:05 +02:00
Florian Bruhin
4860ad5487 Add some tests for config transformers 2016-08-17 14:51:05 +02:00
Florian Bruhin
373eca1ad2 Fix some corner cases in _transform_hint_color 2016-08-17 14:51:05 +02:00
Florian Bruhin
eac30fc84b Add styling of new hints
This also removes the hints -> opacity setting, as this is now set by
using an rgba(...) color.
2016-08-17 14:51:05 +02:00
Florian Bruhin
c033ed9edb Allow config value transformers to give up 2016-08-17 14:51:04 +02:00
Florian Bruhin
9c3807c117 Store HintLabels (not ElemTuples) in HintManager 2016-08-17 14:44:49 +02:00
Florian Bruhin
cf7170a33b Remove no longer needed webelem methods
The following methods were only used for hint labels and thus removed
now:

- document_element
- create_inside
- find_first
- set_inner_xml
- remove_from_document
- set_style_property
2016-08-17 14:44:49 +02:00
Florian Bruhin
1753d3507c Use native QLabels for hints
This will make labels work easily with QtWebEngine, and make sure
they're not affected by the page's contents.

Fixes #925.
Fixes #1126.
2016-08-17 14:43:35 +02:00
Florian Bruhin
ea14b5bb42 Merge branch 'haasn-issue1060' 2016-08-17 12:05:01 +02:00
Florian Bruhin
781e7554e4 Set open target for force_tab to tab-silent
Fixes #1328
2016-08-17 12:04:46 +02:00
Florian Bruhin
00b59eedf7 Update docs 2016-08-17 12:02:09 +02:00
Florian Bruhin
01fd7cd210 Merge branch 'issue1060' of https://github.com/haasn/qutebrowser into haasn-issue1060 2016-08-17 12:01:53 +02:00
Florian Bruhin
eabd41711e Merge branch 'Kingdread-docker-xvfb-fix' 2016-08-17 11:15:00 +02:00
Daniel Schadt
b6ea601f93 Dockerfile: fix pacman invocations 2016-08-16 22:59:55 +02:00
Daniel Schadt
8a644177ca Dockerfile: Upgrade pacman early
Otherwise we have a pacman without hook support which fails to e.g. run
update-ca-trust after updating ca-certificates.
2016-08-16 22:55:24 +02:00
Daniel Schadt
d3982f0325 docker: don't start Xvfb and herbstluftwm
Since we use pytest-xvfb, Xvfb is automatically started and stopped by
pytest. The herbstluftwm also runs in the "outer" Xvfb and is not
actually available inside the tests, as the tests run in another
display, while  herbstluftwm runs in :0.

This patch removes herbstluftwm completely (it was not used until now,
so there shouldn't be a problem), and doesn't start Xvfb (the package is
still needed for pytest-xvfb to work).

Additionally, it adds the "xauth" package on debian, because we'll need
it anyway sooner or later. It's automatically included in Ubuntu and
Arch because xvfb depends on it, but on debian, xauth is only
recommended and not installed automatically.
2016-08-16 22:36:08 +02:00
Florian Bruhin
cc693f17ca QtWebEngine: Use loadFinished as history trigger
Using urlChanged spams the history with too many entries...

Fixes #1837
2016-08-16 21:46:25 +02:00
Florian Bruhin
1dbedbc474 Fix :restart deleting the given --basedir 2016-08-16 21:27:23 +02:00
Florian Bruhin
577c6270ad Remove some old entries from vulture whitelist 2016-08-16 20:20:09 +02:00
Florian Bruhin
87aa11de7f Remove unused WebView._check_insertmode attribute 2016-08-16 19:57:43 +02:00
Florian Bruhin
dc87e66d75 tests: Ignore "Error when parsing the netrc file"
qutebrowser shows this on an invalid ~/.netrc when testing
authentication, but that shouldn't fail our testsuite.
2016-08-16 19:56:49 +02:00
Florian Bruhin
1138d068e6 Move insert-mode-on-click to tab API / mouse.py
This also implements the feature for QtWebEngine.
2016-08-16 16:22:18 +02:00
Florian Bruhin
eef76dde86 eslint: Disable no-warning-comments 2016-08-16 15:21:37 +02:00
Florian Bruhin
7b463f2d8b Update changelog
[ci skip]
2016-08-16 14:22:47 +02:00
Florian Bruhin
6794187390 Fix too long line 2016-08-16 14:19:39 +02:00
Florian Bruhin
1a5f057090 Merge branch 'blyxxyz-safe-args' 2016-08-16 14:19:20 +02:00
Florian Bruhin
5d6abc6f67 Merge branch 'safe-args' of https://github.com/blyxxyz/qutebrowser into blyxxyz-safe-args 2016-08-16 14:18:44 +02:00
Florian Bruhin
dba579c202 Update user-agent completion list 2016-08-16 14:06:57 +02:00
Florian Bruhin
c99d3e7dca Fix %s output in scripts.dev.ua_fetch 2016-08-16 14:06:37 +02:00
Jan Verbeek
cfd166a95e Merge https://github.com/The-Compiler/qutebrowser into safe-args 2016-08-16 14:05:04 +02:00
Jan Verbeek
096387897c Make pp bindings work with option in clipboard
If the clipboard contains "-a" then "open {clipboard}" will fail because
-a gets parsed as an option. "open -- {clipboard}" doesn't do that. See
some comments in #1791.
2016-08-16 14:00:37 +02:00
Florian Bruhin
f4b72d4b24 Revert "Revert "Handle counts for special keys.""
This reverts commit 2d5ffbfd02.
2016-08-16 13:44:28 +02:00
Florian Bruhin
33cda441e6 Merge branch 'blyxxyz-insert-text' 2016-08-16 13:33:20 +02:00
Florian Bruhin
5ecef0004c Add some docs for command replacements 2016-08-16 13:32:53 +02:00
Florian Bruhin
9c76ce1255 Update docs 2016-08-16 13:31:41 +02:00
Florian Bruhin
8d6b905f95 Merge branch 'insert-text' of https://github.com/blyxxyz/qutebrowser into blyxxyz-insert-text 2016-08-16 13:29:42 +02:00
Florian Bruhin
2d7d47dc30 Rewrite word hint test as BDD test
See #1842.
2016-08-16 13:08:49 +02:00
Florian Bruhin
7b7dff30bf Merge branch 'lahwaacz-fix_hints_autofollow' 2016-08-16 13:00:09 +02:00
Florian Bruhin
7519ba3ea4 Update docs 2016-08-16 12:59:54 +02:00
Florian Bruhin
8e6d784fd7 Merge branch 'fix_hints_autofollow' of https://github.com/lahwaacz/qutebrowser into lahwaacz-fix_hints_autofollow 2016-08-16 12:58:56 +02:00
Niklas Haas
c2cc28a72b Add new-instance-open-target.window = first-opened
Fixes #1060.

In the process of adding this, I also decided to rewrite
mainwindow.get_window() for clarity (and also because flake8 was warning
about complexity).

Also adds some tests to the new-instance-target mechanism, in particular
a specific test for the issue in question.
2016-08-16 12:24:38 +02:00
Florian Bruhin
df1806ef4e Merge branch 'lahwaacz-var_replacements' 2016-08-16 11:49:41 +02:00
Florian Bruhin
cf0b12b5a9 Merge branch 'var_replacements' of https://github.com/lahwaacz/qutebrowser into lahwaacz-var_replacements 2016-08-16 11:49:31 +02:00
Florian Bruhin
e55528d2b7 Merge branch 'rcorre-completion-category-focus' 2016-08-16 11:47:07 +02:00
Florian Bruhin
cfa246a4bd Update docs 2016-08-16 11:46:57 +02:00
Florian Bruhin
ee3ea739fc Merge branch 'completion-category-focus' of https://github.com/rcorre/qutebrowser into rcorre-completion-category-focus 2016-08-16 11:45:23 +02:00
Florian Bruhin
91db564e1a Fix lint 2016-08-16 11:36:55 +02:00
Florian Bruhin
242dd4a6f7 Merge branch 'pvsr-navigate-count' 2016-08-16 11:22:41 +02:00
Florian Bruhin
d1138fa342 Update docs 2016-08-16 11:22:29 +02:00
Florian Bruhin
380856bcb2 Merge branch 'navigate-count' of https://github.com/pvsr/qutebrowser into pvsr-navigate-count 2016-08-16 11:21:07 +02:00
Florian Bruhin
62cce23b84 Update changelog
Seems like that fix accidentally didn't make it to v0.8.2
2016-08-16 11:16:32 +02:00
Florian Bruhin
0058917b8d Merge branch 'haasn-winonly' 2016-08-16 11:08:04 +02:00
Florian Bruhin
239e563ebb Regenerate docs 2016-08-16 11:07:57 +02:00
Florian Bruhin
882d1a5e88 Move :window-only to misc.utilcmds 2016-08-16 11:05:02 +02:00
Florian Bruhin
9d7d307aa5 Merge branch 'winonly' of https://github.com/haasn/qutebrowser into haasn-winonly 2016-08-16 11:02:49 +02:00
Florian Bruhin
ccce55443f Fix TabWidget.init_config with PyQt 5.2
See #1847, #1775
2016-08-16 10:44:53 +02:00
Peter Rice
ad9dfc1981 add end-to-end tests for navigating with a count 2016-08-16 04:28:31 -04:00
Florian Bruhin
51dd51cf55 Merge branch 'airodactyl-fix/fail-tab-detach' 2016-08-16 10:08:03 +02:00
Florian Bruhin
e1332412b9 Update docs 2016-08-16 10:07:46 +02:00
Florian Bruhin
a98d407467 Merge branch 'fix/fail-tab-detach' of https://github.com/airodactyl/qutebrowser into airodactyl-fix/fail-tab-detach 2016-08-16 10:06:57 +02:00
Florian Bruhin
fe44ac86dc requirements: Update check-manifest to 0.32
- New config/command line option to ignore bad ideas (ignore-bad-ideas)
- Files named .hgsigs are ignored by default. Contributed by Jakub Wilk.
2016-08-16 09:15:28 +02:00
Florian Bruhin
160d4de33f tests-git requirements: Pin PyYAML 2016-08-16 09:14:12 +02:00
Peter Rice
67609af21b resolve linter warnings 2016-08-15 22:53:28 -04:00
Peter Rice
d4c16aa3c7 add a test for incdec with a count 2016-08-15 22:53:28 -04:00
Peter Rice
060305279c update navigate-related help and function docs 2016-08-15 22:28:25 -04:00
Peter Rice
d3e4d62d14 make navigate take counts for inc, dec, and up 2016-08-15 21:13:52 -04:00
Michael Hoang
8608c6b8b3 Remove unnecessary fresh instance requirement for test 2016-08-16 08:04:54 +10:00
Michael Hoang
c0ab474b21 Give error when trying to detach a single tab 2016-08-16 07:36:39 +10:00
Florian Bruhin
5c766ff7da test requirements: Update httpbin, unpin Flask
httpbin
=======

- Allow /redirect-to to work with multiple methods
- Allow MD5 or SHA-256 to be chosen as algorithms for HTTP Digest Auth
- Set a 10MB limit on /drip

Flask
=====

Version 0.11.1
--------------

Bugfix release, released on June 7th 2016.

- Fixed a bug that prevented ``FLASK_APP=foobar/__init__.py`` from
  working.

Version 0.11
------------

Released on May 29th 2016, codename Absinthe.

- Added support to serializing top-level arrays to
  :func:`flask.jsonify`. This introduces a security risk in ancient
  browsers. See :ref:`json-security` for details.
- Added before_render_template signal.
- Added `**kwargs` to :meth:`flask.Test.test_client` to support passing
  additional keyword arguments to the constructor of
  :attr:`flask.Flask.test_client_class`.
- Added ``SESSION_REFRESH_EACH_REQUEST`` config key that controls the
  set-cookie behavior.  If set to ``True`` a permanent session will be
  refreshed each request and get their lifetime extended, if set to
  ``False`` it will only be modified if the session actually modifies.
  Non permanent sessions are not affected by this and will always
  expire if the browser window closes.
- Made Flask support custom JSON mimetypes for incoming data.
- Added support for returning tuples in the form ``(response, headers)``
  from a view function.
- Added :meth:`flask.Config.from_json`.
- Added :attr:`flask.Flask.config_class`.
- Added :meth:`flask.Config.get_namespace`.
- Templates are no longer automatically reloaded outside of debug mode. This
  can be configured with the new ``TEMPLATES_AUTO_RELOAD`` config key.
- Added a workaround for a limitation in Python 3.3's namespace loader.
- Added support for explicit root paths when using Python 3.3's namespace
  packages.
- Added :command:`flask` and the ``flask.cli`` module to start the local
  debug server through the click CLI system.  This is recommended over the old
  ``flask.run()`` method as it works faster and more reliable due to a
  different design and also replaces ``Flask-Script``.
- Error handlers that match specific classes are now checked first,
  thereby allowing catching exceptions that are subclasses of HTTP
  exceptions (in ``werkzeug.exceptions``).  This makes it possible
  for an extension author to create exceptions that will by default
  result in the HTTP error of their choosing, but may be caught with
  a custom error handler if desired.
- Added :meth:`flask.Config.from_mapping`.
- Flask will now log by default even if debug is disabled.  The log format is
  now hardcoded but the default log handling can be disabled through the
  ``LOGGER_HANDLER_POLICY`` configuration key.
- Removed deprecated module functionality.
- Added the ``EXPLAIN_TEMPLATE_LOADING`` config flag which when enabled will
  instruct Flask to explain how it locates templates.  This should help
  users debug when the wrong templates are loaded.
- Enforce blueprint handling in the order they were registered for template
  loading.
- Ported test suite to py.test.
- Deprecated ``request.json`` in favour of ``request.get_json()``.
- Add "pretty" and "compressed" separators definitions in jsonify() method.
  Reduces JSON response size when JSONIFY_PRETTYPRINT_REGULAR=False by removing
  unnecessary white space included by default after separators.
- JSON responses are now terminated with a newline character, because it is a
  convention that UNIX text files end with a newline and some clients don't
  deal well when this newline is missing. See
  https://github.com/pallets/flask/pull/1262 -- this came up originally as a
  part of https://github.com/kennethreitz/httpbin/issues/168
- The automatically provided ``OPTIONS`` method is now correctly disabled if
  the user registered an overriding rule with the lowercase-version
  ``options``.
- ``flask.json.jsonify`` now supports the ``datetime.date`` type.
- Don't leak exception info of already catched exceptions to context teardown
  handlers.
- Allow custom Jinja environment subclasses.
- ``flask.g`` now has ``pop()`` and ``setdefault`` methods.
- Turn on autoescape for ``flask.templating.render_template_string`` by default.
- ``flask.ext`` is now deprecated.
- ``send_from_directory`` now raises BadRequest if the filename is invalid on
  the server OS.
- Added the ``JSONIFY_MIMETYPE`` configuration variable.
- Exceptions during teardown handling will no longer leave bad application
  contexts lingering around.

Version 0.10.2
--------------

(bugfix release, release date to be announced)

- Fixed broken `test_appcontext_signals()` test case.
- Raise an :exc:`AttributeError` in :func:`flask.helpers.find_package` with a
  useful message explaining why it is raised when a PEP 302 import hook is used
  without an `is_package()` method.
- Fixed an issue causing exceptions raised before entering a request or app
  context to be passed to teardown handlers.
- Fixed an issue with query parameters getting removed from requests in
  the test client when absolute URLs were requested.
- Made `@before_first_request` into a decorator as intended.
- Fixed an etags bug when sending a file streams with a name.
- Fixed `send_from_directory` not expanding to the application root path
  correctly.
- Changed logic of before first request handlers to flip the flag after
  invoking.  This will allow some uses that are potentially dangerous but
  should probably be permitted.
- Fixed Python 3 bug when a handler from `app.url_build_error_handlers`
  reraises the `BuildError`.
2016-08-15 19:38:55 +02:00
Florian Bruhin
355388226b flake8 requirements: Update pyparsing to 2.1.8
- Fixed issue in the optimization to _trim_arity, when the full
  stacktrace is retrieved to determine if a TypeError is raised in
  pyparsing or in the caller's parse action. Code was traversing
  the full stacktrace, and potentially encountering UnicodeDecodeError.

- Fixed bug in ParserElement.inlineLiteralsUsing, causing infinite
  loop with Suppress.

- Fixed bug in Each, when merging named results from multiple
  expressions in a ZeroOrMore or OneOrMore. Also fixed bug when
  ZeroOrMore expressions were erroneously treated as required
  expressions in an Each expression.

- Added a few more inline doc examples.

- Improved use of runTests in several example scripts.
2016-08-15 19:37:09 +02:00
Florian Bruhin
1846726f49 Regenerate docs 2016-08-15 19:35:50 +02:00
Florian Bruhin
0cefcef8f3 Change user-stylesheet default
This shows scrollbars like the one in the code block here:
https://devtalk.nvidia.com/default/topic/918822/linux/hevc-main-10-profile-decoding-using-vdpau-unsupported-on-gtx-950-361-28-/
2016-08-15 18:00:18 +02:00
Ryan Roden-Corrent
7b3839b44b Focus completion by category.
Implement `completion-item-focus next-category` and
`completion-item-focus prev-category` to jump through completions by
category rather than by item.

Resolves #1567.
2016-08-15 07:14:28 -04:00
Jakub Klinkovský
befaf4f6dc fix nested expansion of {variables} in command args 2016-08-14 15:29:16 +02:00
Florian Bruhin
69d772cbee requirements: Update setuptools to 25.2.0 2016-08-12 23:32:10 +02:00
Florian Bruhin
e7d08db6c3 eslint: Turn off sort-keys 2016-08-12 20:58:20 +02:00
Niklas Haas
b6145d98a4 Remove some unnecessary "fresh instances" in tests
With the addition of :window-only, it's no longer necessary to use
"Given I have a fresh instance" to clean up previous windows. This
greatly cuts down on the amount of process restarts that need to happen
to complete a full testing cycle.

I also made one of the tests more robust against order alterations, and
removed some unnecessary extra commands that were already implied by the
background on others.
2016-08-12 00:20:57 +02:00
Niklas Haas
d5080bdb1a Add :window-only command
I mainly added this so I can speed up all of the tests that rely on
closing other windows.
2016-08-11 23:37:14 +02:00
Florian Bruhin
b51dffc517 Merge branch 'lahwaacz-keyinput' 2016-08-11 21:02:05 +02:00
Florian Bruhin
e676063cee Update docs 2016-08-11 19:47:07 +02:00
Florian Bruhin
9c67e87c37 Merge branch 'keyinput' of https://github.com/lahwaacz/qutebrowser into lahwaacz-keyinput 2016-08-11 19:46:30 +02:00
Florian Bruhin
9d39bf7bab Merge branch 'julianuu-test_short_dict' 2016-08-11 19:31:52 +02:00
Florian Bruhin
b535d0c57c Regenerate authors 2016-08-11 19:31:46 +02:00
Florian Bruhin
cd0b5e6889 Merge branch 'test_short_dict' of https://github.com/julianuu/qutebrowser into julianuu-test_short_dict 2016-08-11 19:31:39 +02:00
Julian Weigt
5913c55864 Fixed syntax and improved test 2016-08-11 20:41:02 +02:00
Florian Bruhin
273b7c01ca flake8 requirements: Update pyparsing to 2.1.7
- Fixed regression reported by Andrea Censi (surfaced in PyContracts
  tests) when using ParseSyntaxExceptions (raised when using operator '-')
  with packrat parsing.

- Minor fix to oneOf, to accept all iterables, not just space-delimited
  strings and lists. (If you have a list or set of strings, it is
  not necessary to concat them using ' '.join to pass them to oneOf,
  oneOf will accept the list or set or generator directly.)
2016-08-11 19:26:19 +02:00
Jakub Klinkovský
0e35983362 fix lint ('line too long') 2016-08-11 19:15:26 +02:00
Florian Bruhin
af5d166ae1 QtWebEngine: Fix error message with :print --pdf 2016-08-11 19:13:45 +02:00
Florian Bruhin
fb07655e56 Move input -> rocker-gestures to MouseEventFilter 2016-08-11 18:51:51 +02:00
Florian Bruhin
e8980d01e6 MouseEventFilter: Don't pass obj to handlers 2016-08-11 18:51:50 +02:00
Julian Weigt
060a3998c6 Merge remote-tracking branch 'upstream/master' into test_short_dict 2016-08-11 17:51:45 +02:00
Florian Bruhin
9195e6a3a7 Fix :follow-selected --tab 2016-08-11 17:50:19 +02:00
Jakub Klinkovský
567fe0ec10 keyinput: don't emit keystring_updated twice when clearing 2016-08-11 17:48:43 +02:00
Florian Bruhin
fe3c748e44 Fix another navigation request log 2016-08-11 17:47:13 +02:00
Jakub Klinkovský
2d2b0f5340 fix tests for config migrations 2016-08-11 17:30:46 +02:00
Florian Bruhin
59faee8518 Don't return page from WebView._init_page
We don't need to refer to it anymore.
2016-08-11 16:48:27 +02:00
Florian Bruhin
e50f5ad55c tests: Get rid of TestTabData
Since we don't use __slots__ anymore, no need for those tests.
2016-08-11 16:47:28 +02:00
Florian Bruhin
b1227391c5 tests: Request mode_manager in fake_web_tab
Since we create a HintManager in AbstractTab now, we need a ModeManager
present to use FakeWebTab.
2016-08-11 16:46:05 +02:00
Florian Bruhin
f9db6b1d3d tests: Use mode_manager fixture in test_tab 2016-08-11 16:45:53 +02:00
Florian Bruhin
533319c1ae tests: Use dict.update in mode_manager fixture
This means we can use the fixture in tests which use config_stub
themselves.
2016-08-11 16:45:00 +02:00
Florian Bruhin
20517e9a8f Adjust navigation request logging in hints.feature 2016-08-11 16:38:51 +02:00
Florian Bruhin
d6a3134b3e Remove unused imports 2016-08-11 16:38:45 +02:00
Florian Bruhin
ad1e1e5f92 Log is_main_frame in acceptNavigationRequest 2016-08-11 16:36:41 +02:00
Florian Bruhin
421b14681f Move HintManager out of WebView
This moves creating the HintManager to AbstractTab, and lets
TabData (which is now a QObject) handle the start_hinting/end_hinting
signal.

For the mouse_event signal of HintManager, we now have a slot in
AbstractTab too, though that might actually be moved to
WebKitTab/WebEngineTab later when needed.
2016-08-11 16:30:55 +02:00
Jakub Klinkovský
9f8b5dad92 simplify <Escape> binding
Note that leave-mode implies clear-keychain since bf0fe3c.
2016-08-11 16:11:13 +02:00
Florian Bruhin
3bffb71b55 QtWebEngine: Implement mouse opentarget handling
This moves various stuff around and out of QtWebKit code:

- open_target and hint_target are now in TabData, not on the WebPage

- As much as possible got extracted from WebPage.acceptNavigationRequest
  to AbstractTab._on_link_clicked, with a new link_clicked signal added
  to WebPage. However, we need to decide whether to handle the request
  in this tab or not inside acceptNavigationRequest, so we have some
  code duplicated there and in WebEnginePage.acceptNavigationRequest.

- _mousepress_opentarget (i.e., setting the open_target) is now handled
  in MouseEventFilter, not in WebView.
2016-08-11 16:09:59 +02:00
Jakub Klinkovský
55a00ab2cf emit keystring_updated iff necessary 2016-08-11 15:57:46 +02:00
Jakub Klinkovský
bf0fe3c43b clear keychain properly
fixes #1805
2016-08-11 15:45:44 +02:00
Jakub Klinkovský
9b1c07e2e2 add tests for hints auto-follow in word mode 2016-08-11 15:20:52 +02:00
Julian Weigt
6973c93fa7 Added test to check handling of the case of a too small dictionary 2016-08-11 15:06:24 +02:00
Florian Bruhin
8b0028cb87 Add FIXME 2016-08-11 14:55:19 +02:00
Jan Verbeek
79ab5da45b Update test comment 2016-08-11 14:04:30 +02:00
Florian Bruhin
1a94cb551c Move mouse wheel zooming to MouseEventHandler 2016-08-11 13:50:06 +02:00
Florian Bruhin
677bb29251 Document event filter attributes 2016-08-11 13:38:20 +02:00
Florian Bruhin
93db3886e8 Merge branch 'airodactyl-fix/undo-tab-detach' 2016-08-11 13:14:46 +02:00
Florian Bruhin
7a28268d2f Update docs 2016-08-11 13:14:33 +02:00
Florian Bruhin
b50ab37bbc Merge branch 'fix/undo-tab-detach' of https://github.com/airodactyl/qutebrowser into airodactyl-fix/undo-tab-detach 2016-08-11 13:04:31 +02:00
Florian Bruhin
a23f3a24b3 scroll.js: Use window.inner{Width,Height}
It seems with document.documentElement.client{Height,Width} we
sometimes (e.g. without <!DOCTYPE html)...) get the full element height
instead of the viewport height.

Fixes #1821.
2016-08-11 11:57:20 +02:00
Florian Bruhin
aafdc225bc tests: Use last history item to check scroll pos 2016-08-11 11:56:11 +02:00
Florian Bruhin
bb2eee6178 Add a test for #1821 2016-08-11 11:49:56 +02:00
Florian Bruhin
c12aeea670 tests: Move data/scroll.html to data/scroll/simple 2016-08-11 11:47:55 +02:00
Michael Hoang
ed137c01aa Make add_undo for tab close a keyword arg 2016-08-11 15:18:07 +10:00
Jan Verbeek
e7367bd949 Make :insert-text test platform-independent
The test for inserting text at a specific position failed because
<Ctrl+Right> doesn't behave the same on Windows and Linux. This changes
it to move the cursor using other keys.
2016-08-11 02:26:48 +02:00
Jan Verbeek
28430a4e43 Make test_insert_mode Windows-compatible 2016-08-11 01:36:03 +02:00
Michael Hoang
af97f9efae Add add_undo parameter for closing tabs
By default, closed tabs should be undoable, but when a tab is detached
:undo should not reopen that tab in the old window.
2016-08-11 07:44:11 +10:00
Jan Verbeek
d2d92c9f2e Fix docstring 2016-08-10 22:29:19 +02:00
Jan Verbeek
d6dff8b05e Regenerate asciidoc after 4a14ab5 2016-08-10 21:59:03 +02:00
Jan Verbeek
bfacbb9219 Merge https://github.com/The-Compiler/qutebrowser into insert-text 2016-08-10 21:57:16 +02:00
Jan Verbeek
4966debd61 Deprecate :paste-primary to :insert-text {primary} 2016-08-10 21:55:16 +02:00
Florian Bruhin
e7584b9e1e scroll.js: Add commented debug output 2016-08-10 21:44:16 +02:00
Florian Bruhin
4a14ab5c06 Hide all deprecated commands in src2asciidoc 2016-08-10 21:29:08 +02:00
Jan Verbeek
db0f8fffcd Merge https://github.com/The-Compiler/qutebrowser into insert-text 2016-08-10 20:54:54 +02:00
Florian Bruhin
3d4fe5dde1 Merge branch 'blyxxyz-clip' 2016-08-10 20:48:54 +02:00
Florian Bruhin
3336766034 Update docs 2016-08-10 20:48:33 +02:00
Florian Bruhin
57896dc00e Merge branch 'clip' of https://github.com/blyxxyz/qutebrowser into blyxxyz-clip 2016-08-10 20:38:54 +02:00
Florian Bruhin
9d510d744a tests: Implement Tab._install_event_filter 2016-08-10 20:37:38 +02:00
Florian Bruhin
b801d3316d Fix lint 2016-08-10 20:23:41 +02:00
Florian Bruhin
08d9243c3e Merge branch 'haasn-lastvisible' 2016-08-10 19:58:41 +02:00
Florian Bruhin
64afc562b6 Install MouseEventFilter on new WebEngine children
For some reason, when e.g. visiting duckduckgo and then heise.de,
QtWebEngine suddenly gets a new QOpenGLWidget as focusProxy.

We install an extra eventFilter observing the ChildAdded event and
re-adding the MouseEventFilter when that happens.
2016-08-10 19:44:06 +02:00
Jan Verbeek
efa53ac25e Add variable tests 2016-08-10 19:42:03 +02:00
Jakub Klinkovský
cdcc9996a0 hints: remove unused context attribute and duplicate initialization 2016-08-10 19:37:01 +02:00
Jakub Klinkovský
58ded41e5d hints: move _filterstr into _context 2016-08-10 18:48:10 +02:00
Jakub Klinkovský
efb680dfb1 hints: make HintManager.fire private
It's not called by other classes anymore, it shouldn't be part of public
API because wrong value to the keystr parameter causes KeyError.
2016-08-10 18:21:19 +02:00
Florian Bruhin
d4f30bd100 Merge branch 'airodactyl-feature/undo-to-old-pos' 2016-08-10 17:50:34 +02:00
Florian Bruhin
a07e520f6b Update docs 2016-08-10 17:50:24 +02:00
Florian Bruhin
3b34032b4b Merge branch 'feature/undo-to-old-pos' of https://github.com/airodactyl/qutebrowser into airodactyl-feature/undo-to-old-pos 2016-08-10 17:47:25 +02:00
Florian Bruhin
4205e1c95b Update docs 2016-08-10 17:40:27 +02:00
Florian Bruhin
7213850238 Merge branch 'lastvisible' of https://github.com/haasn/qutebrowser into haasn-lastvisible 2016-08-10 17:39:33 +02:00
Florian Bruhin
29b778b6d6 Use javascript.assemble for all functions 2016-08-10 17:27:34 +02:00
Niklas Haas
6293fad2eb Add general->new-instance-open-target.window=last-visible
I usually use my browser with a one-window-per-workspace flow. If I
click on a URL anywhere, I personally would prefer it to go to the
browser instance that's on the same workspace.

To this end, the easiest way to accomplish this is to simply track when
windows are made visible and register them as the last visible object.

(To get finer control for when you have multiple windows on the same
workspace, focus changes also update the last visible object - the
implication being here that focusing something also means you're looking
at it)

Not all users may like this behavior, so I consider it strictly optional.
2016-08-10 17:01:12 +02:00
Florian Bruhin
dcec71de19 Merge branch 'rcorre-buffer_idx_completion' 2016-08-10 16:58:43 +02:00
Florian Bruhin
082e8da144 Update changelog 2016-08-10 16:58:26 +02:00
Florian Bruhin
c0c3fb47dd Merge branch 'buffer_idx_completion' of https://github.com/rcorre/qutebrowser into rcorre-buffer_idx_completion 2016-08-10 16:57:51 +02:00
Florian Bruhin
289c04e9b0 Regenerate docs 2016-08-10 16:44:40 +02:00
Florian Bruhin
f908d29a5f Move mouse handling to an EventFilter 2016-08-10 16:44:40 +02:00
Ryan Roden-Corrent
1de465f42b Filter buffer completion by all columns.
In addition to the url and text column, also filter by the index column
so the user can enter a number to navigate to that tab.

Resolves #1830.
2016-08-10 10:20:04 -04:00
Jakub Klinkovský
073e5555ca add more tests for hints auto-follow 2016-08-10 16:12:09 +02:00
Jakub Klinkovský
24f8ed8ac1 hints: refactor auto-follow handling in the fire method 2016-08-10 16:09:37 +02:00
Florian Bruhin
85a4dc808e Add "# pragma: no cover" for ImportError 2016-08-10 15:57:01 +02:00
Florian Bruhin
f7cd426aaa Adjust PERFECT_FILES for history move 2016-08-10 15:48:34 +02:00
Florian Bruhin
b380b2f5be Try another objreg fix 2016-08-10 15:47:50 +02:00
Florian Bruhin
b337578274 QtWebEngine: Allow general->log-javascript-console 2016-08-10 15:44:47 +02:00
Florian Bruhin
1d6452ee53 Merge branch 'rcorre-complete-hidden-commands' 2016-08-10 15:40:12 +02:00
Florian Bruhin
42107dd3a0 Update changelog 2016-08-10 15:40:00 +02:00
Florian Bruhin
f3c32308d3 Merge branch 'complete-hidden-commands' of https://github.com/rcorre/qutebrowser into rcorre-complete-hidden-commands 2016-08-10 15:38:46 +02:00
Florian Bruhin
bf3579d5b9 Fix test_history for WebKit/WebEngine split 2016-08-10 15:19:12 +02:00
Florian Bruhin
144895d35e Mark test_invocations.test_optimize as not_frozen 2016-08-10 15:05:55 +02:00
Florian Bruhin
b488d7f9fd Make QtWebKit optional in utils.version 2016-08-10 15:05:15 +02:00
Florian Bruhin
5b2ae3cec7 Don't inherit AbstractWebInspector from QtWebKit 2016-08-10 14:55:50 +02:00
Florian Bruhin
33193d7dd4 Split up QtWebKit specific part in browser.history 2016-08-10 14:51:29 +02:00
Florian Bruhin
ad5008152c Move browser.webkit.history to browser.history 2016-08-10 14:45:52 +02:00
Florian Bruhin
a35b6e2279 Fix testprocess test for custom environment 2016-08-10 14:02:04 +02:00
Florian Bruhin
f6d4e0d32c Try working around AttributeError in objreg 2016-08-10 13:58:41 +02:00
Florian Bruhin
c5a363c66c tests: Add requested argument to FakeWebTab.url 2016-08-10 13:54:52 +02:00
Michael Hoang
66dcc391ba Add tests to check :undo opens in the old position 2016-08-10 21:52:02 +10:00
Florian Bruhin
e51b763c93 testproc: Pass through full system environment
Let's just rely on tox for environment isolation, otherwise we just
break stuff on Windows.
2016-08-10 13:23:15 +02:00
Florian Bruhin
393178262e Add history support for QtWebEngine 2016-08-10 13:15:34 +02:00
Florian Bruhin
77531d09df Move history triggering out of WebView 2016-08-10 13:14:38 +02:00
Jakub Klinkovský
605e90a222 simplify hints auto-follow tests 2016-08-10 13:14:21 +02:00
Florian Bruhin
eed3460317 Add tab.url(requested=True) to get original URL 2016-08-10 13:14:07 +02:00
Jakub Klinkovský
f69c02a2b1 tests: fix hints auto-follow tests 2016-08-10 13:05:53 +02:00
Jakub Klinkovský
0d4322b1f2 fix braces in boolean assignments 2016-08-10 13:01:41 +02:00
Ryan Roden-Corrent
0c43ca9f09 Don't sort command completions in models.
The sortfilter already handles sorting, there is no reason to pre-sort
the entries in the model.
2016-08-10 06:58:34 -04:00
Ryan Roden-Corrent
97a971624b Show bindings for aliases in completion.
Command completions for `:bind` and `:` will now show bindings for
aliases. The binding is only included if it is bound to that alias, not
if it is bound to the command the alias points to.
2016-08-10 06:56:44 -04:00
Ryan Roden-Corrent
051a00804b Use regular dict in get_reverse_bindings_for.
Returning a defaultdict made the caller's code look confusing, as it
wasn't clear why there wouldn't be a Keyerror in some cases. Instead,
let the caller explicitly use `get`.
2016-08-10 06:56:44 -04:00
Ryan Roden-Corrent
709470fbe6 Clean up miscmodels and test_models.
- Split up a long conditional into multiple variables.
- Fix a small typo in a related test.
- Remove a trailing comma from an argument list.
2016-08-10 06:56:44 -04:00
Ryan Roden-Corrent
8dbc368d08 Refactor duplicate code for command completion.
Consolidate the logic used to generate the command completion category
into one place. This is shared by CommandCompletionModel,
HelpCompletionModel, and BindCompletionModel.
2016-08-10 06:56:44 -04:00
Ryan Roden-Corrent
0ea61d5f15 Show hidden commands in completion for :bind.
There is a fair amount of duplicate code around command completion that
could probably be refactored.

Resolves #1707.
2016-08-10 06:56:44 -04:00
Ryan Roden-Corrent
dd9470af94 Show hidden commands in help completion.
Hidden commands are not shown in command completion as they typically
would not be run directly. However, a user might still might like to see
help for them if, for example, they are writing a script or creating a
binding.

Addresses #1707.
2016-08-10 06:55:46 -04:00
Jakub Klinkovský
a31565f46e hints: make auto-follow a quadruple option instead of binary 2016-08-10 12:40:16 +02:00
Jan Verbeek
63b9b61e75 Add ClipboardError superexception 2016-08-10 12:33:01 +02:00
Michael Hoang
cc5667f268 Add code to save and restore the old tab position 2016-08-10 19:28:34 +10:00
Florian Bruhin
81eb53a152 test reqs: Update pytest-rerunfailures to 2.0.1
- Prepare CLI options to pytest 3.0, to avoid a deprecation warning.
- Fix error due to missing CHANGES.rst when creating the source
  distribution by adding a MANIFEST.in.
2016-08-10 11:26:19 +02:00
Florian Bruhin
a39e38e29b requiremnents-tests-git: Pin Flask to 0.11.0
This wasn't actually an issue while testing as we turned off BDD tests
due to pytest-bdd not being pytest 3.0 compatible.
2016-08-10 11:22:37 +02:00
Jakub Klinkovský
7be942fadc hints: fix leaving filter in number mode 2016-08-10 11:18:11 +02:00
Florian Bruhin
75bdd1f797 quteproc: pass through QT_QPA_PLATFORM_PLUGIN_PATH 2016-08-10 10:33:26 +02:00
Florian Bruhin
83b15be206 Merge branch 'haasn-hinttags' 2016-08-10 09:53:41 +02:00
Florian Bruhin
4f1a542328 Update docs 2016-08-10 09:53:30 +02:00
Florian Bruhin
a734a324ed Merge branch 'hinttags' of https://github.com/haasn/qutebrowser into haasn-hinttags 2016-08-10 09:52:35 +02:00
Florian Bruhin
5fc8d57958 Merge branch 'rcorre-bind-alias' 2016-08-10 09:43:11 +02:00
Florian Bruhin
bf29c2a753 Import keyconf at file scope again in config.py
Various code (like src2asciidoc.py) relies on all @cmdutils.register
decorators being called when qutebrowser.app is imported.

Moving the keyconf import to _init_key_config broke that assumption, as
keyconf isn't imported anywhere anymore - which caused :bind and :unbind
to vanish from the generated documentation.

In the long run we should perhaps use venusian:
http://docs.pylonsproject.org/projects/venusian/

But for now, this is the easiest solution.
2016-08-10 09:40:38 +02:00
Florian Bruhin
7c5d0eea44 Update changelog 2016-08-10 09:38:17 +02:00
Florian Bruhin
cc0579bd1a Merge branch 'bind-alias' of https://github.com/rcorre/qutebrowser into rcorre-bind-alias 2016-08-10 09:35:28 +02:00
Florian Bruhin
9aa6c8cf36 Automatically terminate quteproc_new after a test
This means we don't get a QProcess message because of test_no_loglines
not sending :quit, and we don't need to do so in test_ascii_locale as
there's nothing we need to wait for.
2016-08-10 09:30:24 +02:00
Florian Bruhin
a24391d40d Fix lint 2016-08-10 09:20:30 +02:00
Florian Bruhin
b025ea9da2 Merge branch 'haasn-lastfocus' 2016-08-10 09:13:50 +02:00
Florian Bruhin
4576fd9840 Update docs 2016-08-10 09:13:35 +02:00
Florian Bruhin
153b9db8c2 Fix new-instance-open-target.window valid_values 2016-08-10 09:11:26 +02:00
Florian Bruhin
61c031ff23 Merge branch 'lastfocus' of https://github.com/haasn/qutebrowser into haasn-lastfocus 2016-08-10 09:09:58 +02:00
Florian Bruhin
15b9e4d2bd Merge branch 'lejenome-pythonoptimize-fix' 2016-08-10 09:05:36 +02:00
Florian Bruhin
f0b3d03072 Regenerate authors 2016-08-10 09:05:30 +02:00
Florian Bruhin
f0133624bf Add some tests for -OO logging 2016-08-10 09:05:04 +02:00
Florian Bruhin
26af2b3089 Fix grammar mistake 2016-08-10 08:48:04 +02:00
Florian Bruhin
dfd58d456a Merge branch 'pythonoptimize-fix' of https://github.com/lejenome/qutebrowser into lejenome-pythonoptimize-fix 2016-08-10 08:47:34 +02:00
Ryan Roden-Corrent
30d2403b7f Avoid config/keyconf circular import. 2016-08-09 21:37:12 -04:00
Ryan Roden-Corrent
91ec5cc356 Update command completion on setting an alias.
Wire up the config change event to update command completion on
changing aliases, so the new aliases will be included.

Fixes #1814.

Currently we do not have tests at a high enough level to test whether
signals are wired up correctly to update completions.
2016-08-09 21:37:12 -04:00
Ryan Roden-Corrent
245212efa1 Allow binding to an alias.
Fix #1813: Cannot :bind to alias
2016-08-09 21:37:12 -04:00
Niklas Haas
e0f069f7ca Extract hint tags from <textarea>
This is similar to <input> and also often uses a placeholder or name to
identify itself.
2016-08-10 02:07:33 +02:00
Niklas Haas
6d181e5c6f Add new-instance-open-target.window setting
This adds the ability to open new tabs in the last-focused window
instead, which fixes #1801.

Right now the only other option is probably not that useful for human
users but it's required to make tests behave deterministically and
consistently. (But with #881 on the roadmap, I would implement this as
another choice)

To this end, also make the test framework set this option to preserve
the invariant against which existing tests are written: that spawning a
new window would effectively also focus it.
2016-08-10 00:06:12 +02:00
Niklas Haas
2223a285ef Remove ui -> hide-mouse-cursor setting
This was currently almost completely broken, yet nobody complained. The
new behavior (in the previous commit) makes this always hide the mouse
cursor, even when an input field has focus.

Since the only two easy options to implement are "never hide" and
"always hide", combined with the fact that both are sort of useless to
an end-user, just remove the option until somebody wants it back.
2016-08-09 23:32:17 +02:00
Niklas Haas
16c2268d09 Fix last-focused-main-window's behavior
Right now, get('last-focused-main-window') essentially returns the same
as qApp.activeWindow(), since it's None when no window is focused. This
seems somewhat contrary to its original intent, so I've changed it to
only ever update the object.

This actually fixes another bug as well: on_focus_changed's new is not
always a MainWindow - in fact it's a WebView on my end. To fix this,
directly use the QApplication.activeWindow() to find the current focus.

That second bit in particular actually some related bugs that probably
nobody ever noticed or bothered reporting:

* _maybe_hide_mouse_cursor currently pretty much never gets called
* :adblock-update doesn't actually show any downloads
* ... probably more
2016-08-09 22:41:40 +02:00
Florian Bruhin
c54f1fe1bb test requirements: Update pytest-xvfb to 0.2.1
This uses /tmp as hardcoded temp dir like X11 does.
2016-08-09 22:11:45 +02:00
Florian Bruhin
3b8189d638 test requirements: Update pytest-repeat to 0.4.0
Fix deprecation warning present in pytest 3.0 for type argument in addoption
2016-08-09 20:53:37 +02:00
Jan Verbeek
7d0064ff86 Fix docstrings 2016-08-09 19:23:38 +02:00
Marshall Lochbaum
8da8441623 Merge auto-open option into show 2016-08-09 13:11:32 -04:00
Marshall Lochbaum
d98c81c9d6 Correct widget behavior when there is no completion 2016-08-09 13:03:38 -04:00
Jakub Klinkovský
108d735e07 hints: fix corner-case in _hint_strings 2016-08-09 18:12:07 +02:00
Jakub Klinkovský
ec5387c674 hints: fix docstrings 2016-08-09 18:09:50 +02:00
Jakub Klinkovský
9841b01d0d hints: generalize auto-follow for any unique match
fixes #1809
2016-08-09 18:09:50 +02:00
Jakub Klinkovský
1d2a34812b hints: refactor handling of auto-follow option 2016-08-09 18:09:50 +02:00
Jakub Klinkovský
cdcde09b80 hints: refactor filter_hints method 2016-08-09 18:09:47 +02:00
Florian Bruhin
fb3da578c5 Fix lint 2016-08-09 17:28:14 +02:00
Florian Bruhin
2cbb147e33 tox: Get flake8 to run again
Seems like when not passing a file path, flake8 does less (or nothing?!)
2016-08-09 17:12:42 +02:00
Florian Bruhin
1980dbb529 Merge branch 'lahwaacz-fix_hiding_hints' 2016-08-09 16:45:23 +02:00
Florian Bruhin
cf519bd528 Update docs 2016-08-09 16:44:00 +02:00
Florian Bruhin
809f8e90df Merge branch 'fix_hiding_hints' of https://github.com/lahwaacz/qutebrowser into lahwaacz-fix_hiding_hints 2016-08-09 16:42:11 +02:00
Jan Verbeek
7e634a1e52 Make vars declarative, new function for URL lists 2016-08-09 16:20:02 +02:00
Florian Bruhin
513a02b545 Merge branch 'haasn-hintmodes' 2016-08-09 16:16:09 +02:00
Florian Bruhin
5066606ddc Remove spaces inside docstrings 2016-08-09 16:15:23 +02:00
Florian Bruhin
6f074049c2 Update docs 2016-08-09 16:14:58 +02:00
Florian Bruhin
13f80e3f63 Merge branch 'hintmodes' of https://github.com/haasn/qutebrowser into haasn-hintmodes 2016-08-09 16:14:07 +02:00
Florian Bruhin
fefea4944a QtWebEngine: Make :open-editor work 2016-08-09 16:00:59 +02:00
Florian Bruhin
ca67e2be3c QtWebEngine js: Get rid of webelem.get_element()
Let's do separate JS functions instead so we can easily access them via
utils.javascript.assemble.
2016-08-09 16:00:20 +02:00
Florian Bruhin
1e5b6caa4b QtWebEngine js: Save element in focus_element() 2016-08-09 15:59:57 +02:00
Niklas Haas
62e58c0ab9 Add a --mode flag to :hints
This allows a specific keybinding, for whatever reason, to override the
default mode. Examples of when this could be useful:

* :hint --rapid --mode=word  (to type them more rapidly)
* :hint --mode=letter input  (if the default mode is number)

Also reword the description of 'group' to make the distinction between
'group' and 'mode' clearer.
2016-08-09 15:34:13 +02:00
Florian Bruhin
9f770adc78 Lower-case WebEngineElement.tag_name() correctly 2016-08-09 15:19:57 +02:00
Florian Bruhin
2d48a8013f tests: Don't set ssl-strict with QtWebEngine 2016-08-09 15:13:26 +02:00
Jan Verbeek
8e4733f483 Merge https://github.com/The-Compiler/qutebrowser into clip 2016-08-09 14:36:01 +02:00
Florian Bruhin
c8d39e8934 tox: Fix vulture environment
We set PYTHONPATH so we can import qutebrowser.app in run_vulture.py
without installing it.

We also need to make sure all dependencies are installed so we can
actually import qutebrowser.
2016-08-09 13:54:54 +02:00
Florian Bruhin
c0a407235c Remove unused import 2016-08-09 13:51:18 +02:00
Florian Bruhin
74b279e5a9 Adjust .eslint* paths in MANIFEST.in 2016-08-09 13:38:55 +02:00
Florian Bruhin
b82823d76a js: Don't leak to global ns in position_caret.js 2016-08-09 13:36:46 +02:00
Florian Bruhin
c8a92a0851 Fix test_assemble 2016-08-09 13:23:46 +02:00
Florian Bruhin
1307d8e9a2 Simplify utils.javascript.assemble 2016-08-09 13:21:44 +02:00
Florian Bruhin
4046615b37 WebEngineScroller: Set position to (0,0) initially
Since we now use QWebEngineScript, we can't easily know when the script
finished running and we can access window._qutebrowser.scroll.

We instead assume the initial position (if we don't get a
scrollPositionChanged) will always be (0, 0), and explicitly set it
to (None, None) (displaying ???) if we can't connect that signal.
2016-08-09 13:18:33 +02:00
Florian Bruhin
6b7a39685e Modularize javascript code
We now load the JS code as a QWebEngineScript, which sets up
window._qutebrowser with various "modules". That means we don't have to
pass the whole module every time we want to execute something.
2016-08-09 13:17:44 +02:00
Florian Bruhin
00673ef7da tox: Only install pip as dep when needed
misc/eslint don't actually install anything, so no point in updating pip
there.

pyroma/check-manifest should install pip though.
2016-08-09 11:10:50 +02:00
Florian Bruhin
a4585bb3d5 tox: Don't install any deps for eslint 2016-08-09 11:09:15 +02:00
Florian Bruhin
2a2c49f507 tox: Set skipsdist = true
Since our tests don't actually run against the installed package, no
point in waiting for an sdist to be built.
2016-08-09 11:08:19 +02:00
Florian Bruhin
5a1910e24d tox: Enforce colors for eslint 2016-08-09 11:05:08 +02:00
Florian Bruhin
1d9113124b Move .eslintrc to qutebrowser/javascript 2016-08-09 11:04:50 +02:00
Jakub Klinkovský
70570f22b0 add manual test for hiding unmatched rapid hints 2016-08-09 11:02:21 +02:00
Jakub Klinkovský
7271955c56 make hiding unmatched rapid hints configurable 2016-08-09 11:01:58 +02:00
Florian Bruhin
4da53480c2 Re-enable and reconfigure eslint 2016-08-09 11:00:26 +02:00
Florian Bruhin
80016006c4 Use and enforce "use strict"; for JS 2016-08-09 09:55:14 +02:00
Florian Bruhin
686d49b578 Merge branch 'haasn-hinttags' 2016-08-09 08:43:47 +02:00
Florian Bruhin
998a4d8fc3 Regenerate authors 2016-08-09 08:43:40 +02:00
Florian Bruhin
c3690bce0d Merge branch 'hinttags' of https://github.com/haasn/qutebrowser into haasn-hinttags 2016-08-09 08:43:32 +02:00
Marshall Lochbaum
b2067ef186 Remove unused _signals_connected 2016-08-08 18:15:13 -04:00
Florian Bruhin
ee24bdb1c8 flake8 requirements: Update pyparsing to 2.1.6
- *Major packrat upgrade*, inspired by patch provided by Tal Einat -
  many, many, thanks to Tal for working on this! Tal's tests show
  faster parsing performance (2X in some tests), *and* memory reduction
  from 3GB down to ~100MB! Requires no changes to existing code using
  packratting. (Uses OrderedDict, available in Python 2.7 and later.
  For Python 2.6 users, will attempt to import from ordereddict
  backport. If not present, will implement pure-Python Fifo dict.)

- Minor API change - to better distinguish between the flexible
  numeric types defined in pyparsing_common, I've changed "numeric"
  (which parsed numbers of different types and returned int for ints,
  float for floats, etc.) and "number" (which parsed numbers of int
  or float type, and returned all floats) to "number" and "fnumber"
  respectively. I hope the "f" prefix of "fnumber" will be a better
  indicator of its internal conversion of parsed values to floats,
  while the generic "number" is similar to the flexible number syntax
  in other languages. Also fixed a bug in pyparsing_common.numeric
  (now renamed to pyparsing_common.number), integers were parsed and
  returned as floats instead of being retained as ints.

- Fixed bug in upcaseTokens and downcaseTokens introduced in 2.1.5,
  when the parse action was used in conjunction with results names.
  Reported by Steven Arcangeli from the dql project, thanks for your
  patience, Steven!

- Major change to docs! After seeing some comments on reddit about
  general issue with docs of Python modules, and thinking that I'm a
  little overdue in doing some doc tuneup on pyparsing, I decided to
  following the suggestions of the redditor and add more inline examples
  to the pyparsing reference documentation. I hope this addition
  will clarify some of the more common questions people have, especially
  when first starting with pyparsing/Python.

- Deprecated ParseResults.asXML. I've never been too happy with this
  method, and it usually forces some unnatural code in the parsers in
  order to get decent tag names. The amount of guesswork that asXML
  has to do to try to match names with values should have been a red
  flag from day one. If you are using asXML, you will need to implement
  your own ParseResults->XML serialization. Or consider migrating to
  a more current format such as JSON (which is very easy to do:
  results_as_json = json.dumps(parse_result.asDict()) Hopefully, when
  I remove this code in a future version, I'll also be able to simplify
  some of the craziness in ParseResults, which IIRC was only there to try
  to make asXML work.

- Updated traceParseAction parse action decorator to show the repr
  of the input and output tokens, instead of the str format, since
  str has been simplified to just show the token list content.

  (The change to ParseResults.__str__ occurred in pyparsing 2.0.4, but
  it seems that didn't make it into the release notes - sorry! Too
  many users, especially beginners, were confused by the
  "([token_list], {names_dict})" str format for ParseResults, thinking
  they were getting a tuple containing a list and a dict. The full form
  can be seen if using repr().)

  For tracing tokens in and out of parse actions, the more complete
  repr form provides important information when debugging parse actions.
2016-08-08 23:54:42 +02:00
Florian Bruhin
2aa5804418 requirements: Update requests to 2.11.0
Improvements

- Added support for the ALL_PROXY environment variable.
- Reject header values that contain leading whitespace or newline characters to
  reduce risk of header smuggling.

Bugfixes

- Fixed occasional TypeError when attempting to decode a JSON response that
  occurred in an error case. Now correctly returns a ValueError.
- Requests would incorrectly ignore a non-CIDR IP address in the NO_PROXY
  environment variables: Requests now treats it as a specific IP.
- Fixed a bug when sending JSON data that could cause us to encounter obscure
  OpenSSL errors in certain network conditions (yes, really).
- Added type checks to ensure that iter_content only accepts integers and None
  for chunk sizes.
- Fixed issue where responses whose body had not been fully consumed would have
  the underlying connection closed but not returned to the connection pool,
  which could cause Requests to hang in situations where the HTTPAdapter had
  been configured to use a blocking connection pool.

Miscellaneous

- Updated bundled urllib3 to 1.16.
- Some previous releases accidentally accepted integers as acceptable header
  values. This release does not.
2016-08-08 23:52:49 +02:00
Marshall Lochbaum
80db69904d Move auto-open handling to CompletionView from Completer 2016-08-08 16:56:11 -04:00
Florian Bruhin
ec21041516 Add a warning header to commands/settings.asciidoc
See #1802
2016-08-08 22:54:07 +02:00
Florian Bruhin
5668a5e71a Merge branch 'addictedtoflames-patch-1' 2016-08-08 19:56:34 +02:00
Florian Bruhin
e97765c1c5 Regenerate docs 2016-08-08 19:56:24 +02:00
Florian Bruhin
9fc44e54a4 Fix long line 2016-08-08 19:56:11 +02:00
Jakub Klinkovský
1819b46fe0 suppress hiding hints in rapid mode
fixes #1799
2016-08-08 18:41:25 +02:00
addictedtoflames
b750d93891 add time units to timeout descriptions
Changed the description for the 'hints/auto-follow-timeout', 'input/timeout' and 'input/partial-timeout' settings to specify that the time should be given in milliseconds
2016-08-08 17:32:41 +01:00
Niklas Haas
6e279f1b1e Extract hint tags from <button> text
This is useful for some styled buttons, including some of those found on
GitHub.
2016-08-08 17:49:35 +02:00
Niklas Haas
cf26201e86 Extract hint tags from <input placeholder="text">
This is useful for very many input fields, especially prominent on
GitHub itself.
2016-08-08 17:49:18 +02:00
Florian Bruhin
af8302b678 Remove unused import 2016-08-08 16:32:23 +02:00
Florian Bruhin
9a17591fb7 Start getting :open-editor to work with WebEngine
It doesn't actually work yet (as it claims the field is not editable),
but at least does not crash when the backend limitation for the command
is removed.
2016-08-08 16:24:34 +02:00
Florian Bruhin
58fb41ab9d tests: Fix webkitelem test for tagName 2016-08-08 15:34:45 +02:00
Florian Bruhin
8187a334f7 Merge branch 'rcorre-completion-item-focus' 2016-08-08 15:23:08 +02:00
Florian Bruhin
7c689d83bf Update docs 2016-08-08 15:22:57 +02:00
Florian Bruhin
9d43becc25 Merge branch 'completion-item-focus' of https://github.com/rcorre/qutebrowser into rcorre-completion-item-focus 2016-08-08 15:21:35 +02:00
Florian Bruhin
ded2143761 test requirements: Update pytest-cov to 2.3.1
- Fixed regression causing spurious errors when xdist was used.
- Fixed DeprecationWarning about incorrect addoption use.
- Fixed deprecated use of funcarg fixture API.
2016-08-08 15:20:04 +02:00
Florian Bruhin
3c573ac187 Fix upper-case tag names for WordHinter 2016-08-08 15:13:30 +02:00
Florian Bruhin
b8e2d5f8f6 Add initial WebEngineElement implementation
This allows :navigate prev/next to work correctly via the javascript
bridge.
2016-08-08 15:02:58 +02:00
Florian Bruhin
1c73751fd9 Always lowercase tagName 2016-08-08 14:11:01 +02:00
Florian Bruhin
9bcce37ff3 WebEngine: Allow :navigate up/decrement/increment 2016-08-08 14:09:28 +02:00
Florian Bruhin
0b16a36120 Clean up handling of focus element
Also fixes #1359.
2016-08-08 14:05:30 +02:00
Florian Bruhin
27330bd4d1 Fix :search-prev with QtWebEngine
Fixes #1797
2016-08-08 13:51:42 +02:00
Florian Bruhin
92049155af Whoops... 2016-08-08 13:42:37 +02:00
Ryan Roden-Corrent
7038db6b17 Combine completion-item-{prev,next}.
- Use a single command completion-item-focus with a next/prev argument.
- Add a rule to translate old configs.
- Regenerate the docs.

See #1095.
2016-08-08 07:37:53 -04:00
Florian Bruhin
bac263d8a5 Adjust PERFECT_FILES for webelem split 2016-08-08 13:28:15 +02:00
Florian Bruhin
dfbadaf7c2 Split WebElementWrapper into abstract/webkit parts 2016-08-08 13:04:53 +02:00
Moez Bouhlel
c04adb94b2 DocstringParser - support python with optimizations on 2016-08-08 10:01:50 +01:00
Florian Bruhin
743d2dc327 Merge branch 'blyxxyz-title_change' 2016-08-08 09:43:30 +02:00
Florian Bruhin
5b1ff84e71 Update changelog 2016-08-08 09:43:15 +02:00
Florian Bruhin
4505d74ae3 Add tests/manual/completion/changing_title.html 2016-08-08 09:42:08 +02:00
Florian Bruhin
734216bc40 Merge branch 'title_change' of https://github.com/blyxxyz/qutebrowser into blyxxyz-title_change 2016-08-08 09:41:29 +02:00
Florian Bruhin
64566fff35 Set maximum value for auto-save-interval correctly 2016-08-08 08:47:21 +02:00
Florian Bruhin
627f743c26 Handle float in _convert_js_arg
This fixes 'gg' with QtWebEngine.
2016-08-08 08:04:55 +02:00
Jan Verbeek
6bbde59de7 Rebuild buffer completion when tab title changes 2016-08-07 16:15:24 +02:00
Jan Verbeek
864c95007f Unhide :insert-text and allow outside insert mode
:insert-text works if a text element is focused, even outside insert
mode.
2016-08-07 14:29:52 +02:00
Jan Verbeek
ebfe23c376 Merge https://github.com/The-Compiler/qutebrowser into clip
Also make it possible to use multiple variables in one argument.
2016-08-07 13:14:46 +02:00
Florian Bruhin
96087bd554 Fix up pretty URL yanking 2016-08-07 11:40:26 +02:00
Florian Bruhin
a18104529a tox requirements: Update virtualenv to 15.0.3 2016-08-07 11:38:22 +02:00
Florian Bruhin
8206efc0c2 requirements: Update setuptools to 25.1.6 2016-08-07 11:37:19 +02:00
Florian Bruhin
e0d2f5afa8 Merge branch 'blyxxyz-better-variables' 2016-08-07 11:35:06 +02:00
Florian Bruhin
5a22852521 Update docs 2016-08-07 11:34:52 +02:00
Florian Bruhin
b6fbd3ce3a Merge branch 'better-variables' of https://github.com/blyxxyz/qutebrowser into blyxxyz-better-variables 2016-08-07 11:33:01 +02:00
Florian Bruhin
126ce0cf2c Merge branch 'rcorre-refactor_command_completion' 2016-08-07 11:30:34 +02:00
Florian Bruhin
26e0383d45 Merge branch 'refactor_command_completion' of https://github.com/rcorre/qutebrowser into rcorre-refactor_command_completion 2016-08-07 11:29:50 +02:00
Florian Bruhin
d8e9a607a7 Merge branch 'Kingdread-fix-windows-editor' 2016-08-07 11:19:23 +02:00
Florian Bruhin
d1eef5d1dc Update changelog 2016-08-07 11:19:03 +02:00
Florian Bruhin
eb2f682e20 Merge branch 'fix-windows-editor' of https://github.com/Kingdread/qutebrowser into Kingdread-fix-windows-editor 2016-08-07 11:17:21 +02:00
Florian Bruhin
1b3664d9c8 keyconfig: Validate commands *after* transforming
Otherwise we'd still get an error when e.g. transforming :yank-selected
to :yank selection as :yank-selected got removed.
2016-08-07 11:10:59 +02:00
Florian Bruhin
a7ffc2c6c0 Merge branch 'mlochbaum-yank-refactor' 2016-08-07 11:09:32 +02:00
Florian Bruhin
ef0b2e1488 Update docs 2016-08-07 11:09:16 +02:00
Florian Bruhin
88d3e86259 Use "what != 'url-pretty'" 2016-08-07 11:02:50 +02:00
Florian Bruhin
efada0a44c Merge branch 'yank-refactor' of https://github.com/mlochbaum/qutebrowser into mlochbaum-yank-refactor 2016-08-07 11:02:24 +02:00
Florian Bruhin
99bd6ae78e Merge branch 'rcorre-sortfilter_tests' 2016-08-07 10:46:41 +02:00
Florian Bruhin
0b93272786 Merge branch 'sortfilter_tests' of https://github.com/rcorre/qutebrowser into rcorre-sortfilter_tests 2016-08-07 10:46:28 +02:00
Florian Bruhin
126e3fd01b tests: Add webkitinspector.py to WHITELISTED_FILES
When running with --no-xvfb, this file has 100% coverage due to the
inspector tests in misc.feature.

See #1771.
2016-08-07 10:42:37 +02:00
Ryan Roden-Corrent
adc428e525 Perfect coverage for sortfilter.
Mark an area of sortfilter with `#pragma no coverage` and add it to
perfect_files.
2016-08-06 20:48:21 -04:00
Jan Verbeek
dc69a90e69 Add :insert-text command
See #1790.
:paste-primary now calls :insert-text and can be deprecated by
:insert-text {primary} after #1791 is merged.
2016-08-07 02:46:10 +02:00
Marshall Lochbaum
7bfa46fb50 Add tests for yank migrations 2016-08-06 20:36:13 -04:00
Marshall Lochbaum
006a934913 Migrate yank keybindings 2016-08-06 20:35:49 -04:00
Marshall Lochbaum
28485b0731 Migrate -p to -s for :yank selection keybinding 2016-08-06 20:35:06 -04:00
Marshall Lochbaum
47969362e1 Fix minor conditional issues in yank 2016-08-06 20:15:51 -04:00
Marshall Lochbaum
a90662ef83 Fix combined yank documentation 2016-08-06 20:13:50 -04:00
Jan Verbeek
38508274e0 Improve clipboard exceptions, migrate bindings 2016-08-07 00:46:23 +02:00
Daniel Schadt
4d00b8fce9 tests: fix tests for misc.editor
Due to the change to NamedTemporaryFile, the _filename attribute was
removed. We now have to use _file.name.
2016-08-07 00:18:22 +02:00
Daniel Schadt
9a4655443f os.unlink -> os.remove
The functions do the same, but remove sounds better.
2016-08-07 00:11:58 +02:00
Jan Verbeek
96146c55af Remove useless clipboard target information 2016-08-06 22:25:08 +02:00
Jan Verbeek
0177dafbd0 Add {clipboard} and {primary} to replace :paste
:paste is deprecated and replaced by equivalents using :open and the
new variables, and :open supports opening newline-separated lists of
URLs.
2016-08-06 22:03:50 +02:00
Daniel Schadt
f23a28079c editor: fix external editor on windows
On windows, only one process can open a file in write mode at once. We
didn't close the handle we got (self._oshandle) before _cleanup, which
means that we had the file open the whole time, which means that the
external editor couldn't write back the changes.

This patch closes the file while the external editor is running and only
opens it once the editor is closed. We re-opened the file anyway, so
this shouldn't be a huge change. Additionally, tempfile.NamedTemporaryFile
is used instead of mkstemp, as we don't have to deal with os-level file
handles that way.
2016-08-06 20:04:25 +02:00
Ryan Roden-Corrent
66358e5b0f Remove usertypes.Completion.empty.
Completion.empty existed to fill a slot in the old Command.completions
interface if the first positional arg had no completions but the second
did, as is the case for the `bind` command. Now that
`Command.completions` is replaced by `Command.get_pos_arg_info`, this
is no longer needed.
2016-08-06 12:01:09 -04:00
Ryan Roden-Corrent
c792ffda67 Remove Command.completion.
Command completion types are now identified by ArgInfo, so just use
that directly and cut out the middle-man. This shouldn't change any
completion behavior.

Adds a test for get_pos_arg_info to test_cmdutils.

Modifies test_completer to test the use of get_pos_arg_info. Instead of
using FakeCommand, real Command objects are used, to validate that the
Completer works with the real Command interface. This also cleans out
some test cases that were testing things already covered by other cases.
2016-08-06 11:59:04 -04:00
Marshall Lochbaum
54ba27cf77 Merge :yank-selected into :yank (fixes #820)
Changes :yank's flag arguments to a positional "what" argument
specifying the object to be yanked. Including "selection" as a
possibility allows for the replacement of :yank-selected with
:yank selection.
2016-08-05 22:01:17 -04:00
Jan Verbeek
1e97247c63 Revert spawn's splitting, blacklist from doc
Blacklist spawn from getting the no_replace_variables doc note.
2016-08-05 18:04:14 +02:00
Florian Bruhin
778ccad39f Move most :navigate code to browser.navigate 2016-08-05 17:28:48 +02:00
Florian Bruhin
68595e1736 Make sure base URL for resolve_url is absolute 2016-08-05 17:12:09 +02:00
Florian Bruhin
7a65559cce Move hints._resolve_url to a WebElement method 2016-08-05 17:09:52 +02:00
Jan Verbeek
8a527b5faf Make :spawn parse normally without maxsplit 2016-08-05 16:52:47 +02:00
Florian Bruhin
4541f19195 Fix crash when doing :<space><enter>
Introduced in #1577.
Fixes #1773.
2016-08-05 15:42:03 +02:00
Florian Bruhin
30c7e4a152 Merge branch 'knaggita-issue#53' 2016-08-05 15:13:59 +02:00
Florian Bruhin
8cc9f30eba Add a BDD test for :debug-log-capacity 2016-08-05 15:13:36 +02:00
Florian Bruhin
ec2ba032a8 Update docs 2016-08-05 15:07:10 +02:00
knaggita
d25e1fde04 Add :debug-log-capacity command 2016-08-05 15:05:27 +02:00
Ryan Roden-Corrent
3e1409b1f5 Dedupe code in test_sortfilter.
Add helper functions to create and parse completion models, as this was
repeated in many tests.
2016-08-05 08:47:52 -04:00
Florian Bruhin
323b181227 Automatically skip BDD tests on pytest 3.0
See https://github.com/pytest-dev/pytest-bdd/pull/193
This at least allows us to play with pytest 3.0 a bit...
2016-08-05 14:36:32 +02:00
Florian Bruhin
747be14118 Also add qutebrowser dependencies to tests-git req 2016-08-05 14:32:41 +02:00
Ryan Roden-Corrent
ed69ef86ab Unit test CompletionFilterModel.sort. 2016-08-05 08:29:29 -04:00
Florian Bruhin
959b076236 Add requirements-test-git.txt
This is useful to track some breakage in test dependencies before stuff
actually goes haywire.
2016-08-05 14:29:00 +02:00
Ryan Roden-Corrent
83b621b0e6 Test CompletionFilterModel.set_pattern.
This is a more rigorous test than filterAcceptsRow as it tests behavior
with multiple columns and different sort settings. In addition, it
tests intelligentLessThan which is not tested in the filterAcceptsRow
test (as lessThan is never called if there is only 1 item to filter).
2016-08-05 07:20:31 -04:00
Ryan Roden-Corrent
8e7002db7a Test CompletionFilterModel.count 2016-08-05 07:20:31 -04:00
Ryan Roden-Corrent
f19b818b58 Test CompletionFilterModel.set_source_model 2016-08-05 07:20:31 -04:00
Ryan Roden-Corrent
b13153aa77 Test CompletionFilterModel.first/last. 2016-08-05 07:20:31 -04:00
Florian Bruhin
2114230739 requirements: Update setuptools to 25.1.4 2016-08-05 12:42:08 +02:00
Florian Bruhin
e2ae133757 Split up HintActions from HintManager 2016-08-05 12:37:25 +02:00
Florian Bruhin
d8521f43ee Change tab.find_all_elements() to be async 2016-08-05 12:37:25 +02:00
Florian Bruhin
0169f3a24f Add _qutebrowser_ prefix for custom JS functions
With QtWebKit or QtWebEngine with Qt < 5.7, the functions end up in the
page's namespace. We can't easily avoid this, but at least we can name
them in a way which reduces conflicts.
2016-08-05 10:31:07 +02:00
Florian Bruhin
ab0d9ca499 Remove another unneeded FIXME
Closes #112.
[ci skip]
2016-08-05 09:35:06 +02:00
Florian Bruhin
2a328bcea1 Remove unneeded fixme
Nothing gets stuff from the config outside of config.get anyways.
Closes #107.
2016-08-05 09:33:28 +02:00
Florian Bruhin
2b496a81ef tests: Use parametrize for parse_fatal_stacktrace 2016-08-05 09:01:09 +02:00
Florian Bruhin
b00e90defb Remove SelectionRequest blacklist for pytest
It's now hidden globally anyways.
See #1287.
2016-08-05 08:32:23 +02:00
Florian Bruhin
da6118bd8d Hide "QXcbClipboard: SelectionRequest too old"
Fixes #1287.
2016-08-05 08:31:44 +02:00
Florian Bruhin
9a50daafee Improve GitHub issue template
See #1379.
2016-08-05 07:47:50 +02:00
Florian Bruhin
94cf3fa4ff QtWebEngine: Restore Qt 5.6 compatibility 2016-08-04 21:33:53 +02:00
Florian Bruhin
029ea2e5a7 Add miscwidgets.WrapperLayout.wrap
This makes it easier for an user of WrapperLayout to wrap a widget.
2016-08-04 19:22:44 +02:00
Florian Bruhin
57ed5ae876 Merge branch 'nanjekyejoannah-end2endTest4@844' 2016-08-04 18:22:09 +02:00
Florian Bruhin
59d8264c56 Regenerate authors 2016-08-04 18:22:03 +02:00
Florian Bruhin
466a87af6a Merge branch 'end2endTest4@844' of https://github.com/nanjekyejoannah/qutebrowser into nanjekyejoannah-end2endTest4@844 2016-08-04 18:21:43 +02:00
Florian Bruhin
2077cf3a7e Merge branch 'engelju-patch-1' 2016-08-04 18:17:35 +02:00
Florian Bruhin
740e109328 Regenerate authors 2016-08-04 18:17:29 +02:00
Florian Bruhin
6f8524ba45 Merge branch 'patch-1' of https://github.com/engelju/qutebrowser into engelju-patch-1 2016-08-04 18:17:18 +02:00
Florian Bruhin
74b9b0ba90 Remove unneeded lambda 2016-08-04 18:15:29 +02:00
Florian Bruhin
7b211e0b65 QtWebEngine: Run javascript in ApplicationWorld
This means the JS context will be isolated from the webpage itself, and
the webpage won't be able to access things we define.
2016-08-04 18:14:29 +02:00
Florian Bruhin
a8ef956726 Add quotes for strings in javascript.assemble 2016-08-04 17:58:40 +02:00
Florian Bruhin
08b70f0f4c Add qutebrowser.utils.javascript
webelem.javascript_escape got renamed to javascript.string_escape, and a
new javascript.assemble got added to make it easier to call a function
inside a .js file.
2016-08-04 17:53:13 +02:00
Jan Verbeek
7999c493ac Remove unnecessary import, split long line 2016-08-04 15:16:35 +02:00
nanjekyejoannah
6431cd2395 added closing body tag 2016-08-04 15:43:58 +03:00
Julie Engel
4705ac2ea8 Correct link to DebugDiag in stacktrace.asciidoc 2016-08-04 14:27:21 +02:00
Jan Verbeek
8b9f37cc84 Use raw string for asciidoc backslashes 2016-08-04 13:45:46 +02:00
Jan Verbeek
827de1743d Document no_replace_variables, misc fixes
Add no_replace_variables to the asciidoc, improve its description in
the decorator, remove now unnecessary argument parsing in set-cmd-text
2016-08-04 13:21:19 +02:00
Florian Bruhin
10dd3135a7 Merge branch 'Kingdread-open-download-fixes' 2016-08-04 12:52:25 +02:00
Florian Bruhin
2143641d14 Update docs 2016-08-04 12:48:02 +02:00
nanjekyejoannah
04b007986f end2end testcase for #844 2016-08-04 13:47:14 +03:00
Florian Bruhin
6021dc6394 Merge branch 'open-download-fixes' of https://github.com/Kingdread/qutebrowser into Kingdread-open-download-fixes 2016-08-04 12:46:44 +02:00
Florian Bruhin
764c232033 Split inspector into web{engine,kit}inspector 2016-08-04 12:44:46 +02:00
Florian Bruhin
ee68a58001 Hide QtWebEngine web inspector warning 2016-08-04 12:09:16 +02:00
Daniel Schadt
d21b42662d Minor Text Fixes
default (program) -> default application
surround {} with backticks
mention that the filename will be appended in the docstrings
2016-08-04 12:07:51 +02:00
Daniel Schadt
017bfc9b9c open-download: append filename if no {} is found
This allows shortcuts like ":download-open gvim" instead of
":download-open gvim {}" to work.
2016-08-04 11:50:35 +02:00
Daniel Schadt
8730dc6f8e tests: use :hint instead of :hint all download
:hint all download does not use the response headers to determine the
filename (the prompt is shown before a request is even done), so our
long filename was pretty useless.

:hint works because it does a request first and uses the right filename,
but we need to wait until the prompt is shown before we can do
:prompt-open-download, since the request is a bit slower and would fail
otherwise.
2016-08-04 11:16:43 +02:00
Daniel Schadt
b9b3bdf9dd Minor Text Fixes 2016-08-04 11:03:05 +02:00
Jan Verbeek
c7c5a98506 Allow {url} and {url:pretty} as parts of arguments
This makes commands like `:open web.archive.org/web/{url}` possible.
This commit also adds a no_replace_variables command register argument
that stops the replacement from happening, which is important for
commands like `:bind` and `:spawn` that take a command as an argument.
2016-08-04 02:43:02 +02:00
Daniel Schadt
e21bdab2c0 rename function to remove duplicate 2016-08-04 02:14:46 +02:00
Daniel Schadt
47b455957f tests: actually download file
Otherwise the :prompt-open-download will throw an error since the
request is not fast enough.
2016-08-04 01:47:02 +02:00
Daniel Schadt
8f4377937d use shlex.quote instead of "{}" 2016-08-04 01:41:50 +02:00
Daniel Schadt
cbe60b0638 add tests for download with special characters
See issue 1726.
2016-08-04 01:24:08 +02:00
Daniel Schadt
d2107498a2 add a test for downloads with long filenames
See issue #1725.
2016-08-04 01:06:42 +02:00
Daniel Schadt
5ca8f77fca lint fixes 2016-08-03 18:16:28 +02:00
Daniel Schadt
1400a27508 more tests for OpenFileDownloadTarget 2016-08-03 18:14:45 +02:00
Daniel Schadt
71102cceb0 docstring & documentation fixes 2016-08-03 18:06:28 +02:00
Daniel Schadt
afa7494c5f add tests for download-open/prompt-open-download
This has tests for
* standard :download-open
* standard :prompt-open-download
* :prompt-open-download + cancel the download (issue #1728)
2016-08-03 17:59:32 +02:00
Daniel Schadt
e8bfc25bbc downloads: replace placeholder in cmdline
This allows commands like --file={} to work properly.
2016-08-03 17:59:32 +02:00
Daniel Schadt
a85227fa25 download-open: add cmdline parameter 2016-08-03 17:59:32 +02:00
Daniel Schadt
fa6c552d7b add an application param for prompt-open-download 2016-08-03 17:59:32 +02:00
Daniel Schadt
716ce701f5 utils: move elide_filename to own function
Also increase the elide limit in TempDownloadManager to 50, since that's
probably still enough for all systems.
2016-08-03 17:59:32 +02:00
nanjekyejoannah
4e93e04468 end2end testcase for issue #844 2016-08-03 18:55:33 +03:00
Florian Bruhin
2f50d100e9 Regenerate docs 2016-08-03 17:43:49 +02:00
Florian Bruhin
33677a8449 More pylint pragmas for QtWebEngine 2016-08-03 17:43:22 +02:00
Florian Bruhin
54ae106789 default key config: Bind J to :tab-next again
This was originally added in #868, but since then we changed the default
binding for gt (for :buffers).

It also accidentally shadowed the T binding which should be bound to
:tab-focus. See #1753.
2016-08-03 17:25:53 +02:00
Florian Bruhin
23ce4561c8 Fix lint 2016-08-03 16:48:48 +02:00
Florian Bruhin
0ddb27709d Re-add geometry saving code to WebEngine inspector 2016-08-03 16:29:46 +02:00
Florian Bruhin
61e0c8327a Don't access QWES.globalSettings() on module-level
Otherwise we implicitly create a webengine context, which means setting
QTWEBENGINE_REMOTE_DEBUGGING won't work anymore.
2016-08-03 15:32:56 +02:00
Florian Bruhin
614893bdd6 Initial broken inspector support for QtWebEngine 2016-08-03 15:23:32 +02:00
Florian Bruhin
9851a13981 Add utils.random_port() 2016-08-03 13:08:55 +02:00
Florian Bruhin
dbccb12b49 Move WrapperLayout to miscwidgets 2016-08-03 13:08:25 +02:00
Florian Bruhin
fa7f9955a3 Add test for BackendError 2016-08-03 12:18:15 +02:00
Florian Bruhin
5f5b395343 pylint: Ignore failing QtWebEngineWidgets import 2016-08-03 12:16:13 +02:00
Florian Bruhin
43c81cc3a4 Fix KeyError with unknown options 2016-08-03 11:58:42 +02:00
Florian Bruhin
11e7f7c334 Remove unused imports 2016-08-03 11:37:05 +02:00
Florian Bruhin
cae7eead6f QtWebEngine: Basic settings support 2016-08-03 11:35:08 +02:00
Florian Bruhin
2ee95df9e7 Change the default hint implemenation to Python
This only affects drawing hints, JS is still used if possible to
actually click them.

It seems like for many people, the JS implementation was a lot slower
than the Python one...
2016-08-03 09:40:05 +02:00
Florian Bruhin
7b7ff53fc1 test requirements: Update pytest-mock to 1.2
- Try to import mock first instead of unittest.mock. This gives the user
  flexibility to install a newer mock version from PyPI instead of using
  the one available in the Python distribution.
- mock.sentinel is now aliased as mocker.sentinel for convenience.
2016-08-03 09:27:50 +02:00
Florian Bruhin
d3192077b4 test requirements: Update beautifulsoup4 to 4.5.1
* Fixed a reported (but not duplicated) bug involving processing
  instructions fed into the lxml HTML parser.
2016-08-03 09:27:24 +02:00
Florian Bruhin
2e75c9c300 Merge branch 'mlochbaum-tab-open-implicit' 2016-08-03 09:23:09 +02:00
Florian Bruhin
6b14fa49f2 Update docs 2016-08-03 09:22:59 +02:00
Florian Bruhin
1fb4aa3532 Merge branch 'tab-open-implicit' of https://github.com/mlochbaum/qutebrowser into mlochbaum-tab-open-implicit 2016-08-03 09:16:49 +02:00
Florian Bruhin
79d2116b18 Remove unneeded 'return' 2016-08-03 09:07:12 +02:00
Florian Bruhin
a49c524b00 tests: Ensure LogLine gets the right json type 2016-08-03 09:06:58 +02:00
Florian Bruhin
0f79027a0e Merge branch 'mlochbaum-arg-or-count' 2016-08-03 09:05:47 +02:00
Florian Bruhin
77dd2a105f Add cmdutils.check_overflow in _set_current_index 2016-08-03 08:57:05 +02:00
Florian Bruhin
641a2d9b42 Update docs 2016-08-03 08:56:02 +02:00
Florian Bruhin
b00abbf1d5 Merge branch 'arg-or-count' of https://github.com/mlochbaum/qutebrowser into mlochbaum-arg-or-count 2016-08-03 08:54:18 +02:00
Florian Bruhin
8f14cac565 Fix changelog 2016-08-03 06:51:21 +02:00
Florian Bruhin
53b0cf85ef pylint requirements: Add github3.py 2016-08-02 22:45:08 +02:00
Florian Bruhin
32282cad58 Update CONTRIBUTING
[ci skip]
2016-08-02 22:31:55 +02:00
Florian Bruhin
195b17c1ad Add release uploading to build_release.py
Closes #1738
2016-08-02 22:26:25 +02:00
Florian Bruhin
eee1c7391c Add download_release.sh
See #1738
2016-08-02 22:26:01 +02:00
Marshall Lochbaum
af9e956cb6 Remove config update code for --implicit flag 2016-08-02 15:29:18 -04:00
Marshall Lochbaum
97a249d8a6 Rewrite tests in open.feature 2016-08-02 15:27:26 -04:00
Marshall Lochbaum
299d4865d0 Move --implicit flag argument to the end of _open 2016-08-02 15:26:49 -04:00
Marshall Lochbaum
feed1ccda4 Change gO, xO, and ;O keybindings to open an implicit tab 2016-08-02 14:10:36 -04:00
Marshall Lochbaum
66adbc9323 Add --implicit flag to :open 2016-08-02 13:49:25 -04:00
Florian Bruhin
f92a426c5b Update changelog for v0.8.2 2016-08-02 18:32:36 +02:00
Marshall Lochbaum
c19e1947f8 Remove tests for cmdutils.arg_or_count (fixes #1735 with previous commits) 2016-08-02 12:02:40 -04:00
Marshall Lochbaum
d30da4f905 Update tab_focus docstring 2016-08-02 11:50:21 -04:00
Marshall Lochbaum
8a127f2839 Remove cmdutils.arg_or_count 2016-08-02 11:31:03 -04:00
Florian Bruhin
0345e62348 requirements: Update setuptools to 25.1.3 2016-08-02 16:34:35 +02:00
Florian Bruhin
a177acf4fd Merge branch 'Kingdread-open-download-fixes' 2016-08-02 16:16:10 +02:00
Florian Bruhin
48067f0c76 Update changelog 2016-08-02 16:15:30 +02:00
Florian Bruhin
a3047008dd Bump up filename length limit to 50
The usual limit seems to be 255 bytes, so even when assuming 5-byte
UTF-8 chars for every letter, 50 should be fine.

http://serverfault.com/questions/9546/filename-length-limits-on-linux/9548#9548
2016-08-02 16:12:09 +02:00
Florian Bruhin
b8ef6fa44e Merge branch 'open-download-fixes' of https://github.com/Kingdread/qutebrowser into Kingdread-open-download-fixes 2016-08-02 16:11:34 +02:00
Florian Bruhin
e53de02e69 Update changelog
[ci skip]
2016-08-02 15:57:09 +02:00
Florian Bruhin
0f5e6abc11 freeze.py: Copy plugin folders on Windows
This makes HTML5 video work.
Fixes #1068.
2016-08-02 15:56:16 +02:00
Florian Bruhin
ecf358b53a Update changelog
[ci skip]
2016-08-02 15:25:20 +02:00
Florian Bruhin
424758a6d1 Use HTML content for localstorage test
JS logging is disabled by QtWebKit in private browsing mode
2016-08-02 15:18:25 +02:00
Florian Bruhin
66709ed1b9 Update changelog 2016-08-02 14:22:01 +02:00
Florian Bruhin
43ff1b0d97 Tunnel private-browsing to QtWebKit correctly 2016-08-02 14:19:31 +02:00
Florian Bruhin
4a5b5c496f Fix using a relative path with --basedir 2016-08-02 14:08:28 +02:00
Florian Bruhin
5af93a2a8e Add .venv* to .gitignore 2016-08-02 12:47:16 +02:00
Florian Bruhin
483072d842 Don't use QSignalSpy in IPC test
Fixes #1727.

For another testcase in the same file we still need to use it until
pytest-qt has a MultiSignalBlocker.args.
2016-08-02 12:45:30 +02:00
Florian Bruhin
b51640f26d Merge branch 'rcorre-fix_completion_crashes' 2016-08-02 12:03:56 +02:00
Florian Bruhin
b17296db0d Return with invalid index 2016-08-02 12:03:29 +02:00
Florian Bruhin
b8aeb9f80e Fix lint 2016-08-02 12:03:29 +02:00
Florian Bruhin
fc6e600e6d Merge branch 'fix_completion_crashes' of https://github.com/rcorre/qutebrowser into rcorre-fix_completion_crashes 2016-08-02 10:33:54 +02:00
Florian Bruhin
04148ed1c6 Appveyor: Also handle IOError
This is on Python 2.7 where they are separate
2016-08-02 09:55:12 +02:00
Florian Bruhin
e99d75c18d requirements: Update setuptools to 25.1.2 2016-08-02 09:45:11 +02:00
Florian Bruhin
082c06eb4a Merge branch 'tjanson-patch-1' 2016-08-02 08:32:46 +02:00
Florian Bruhin
a06cd55216 Regenerate authors 2016-08-02 08:32:39 +02:00
Florian Bruhin
4d50067d18 Merge branch 'patch-1' of https://github.com/tjanson/qutebrowser into tjanson-patch-1 2016-08-02 08:32:24 +02:00
Ryan Roden-Corrent
a393adc6c7 Don't crash completion with auto-open/show False.
If both are false, the selectionModel may be None.
In this case, don't try to move the index.
Resolves #1722.
2016-08-01 22:36:04 -04:00
Ryan Roden-Corrent
6e2d78b826 Don't crash on tab with no completions.
first_item and last_item return an invalid index when there are no
items in the completion, and the completionwidget will throw on an
invalid index. However, setting an invalid index on the selection view
is fine, so just remove the assertion.

Resolves #1731.
2016-08-01 22:16:55 -04:00
Daniel Schadt
57ceaeeb55 open-download: don't crash on download cancel
Fixes #1728.
2016-08-02 01:10:40 +02:00
Daniel Schadt
b187b680cb open-download: force encoding for filename
Fixes #1726.
2016-08-02 01:00:57 +02:00
Daniel Schadt
abcdaa9cce open-download: make sure the name is not too long
Fixes #1725.

Make sure that the temporary filename is not too long by restricting the
suggested part to 20 characters.
2016-08-02 00:57:22 +02:00
Daniel Schadt
9973cd5037 downloads: don't crash on OSError in open-download
Fixes the crash in #1725, but does not provide a solution. The browser
won't crash, but the file won't be downloaded and opened either.
2016-08-02 00:46:59 +02:00
Tom Janson
677e1a3417 Mac OS install: add Homebrew Cask instructions 2016-08-01 23:46:06 +02:00
Florian Bruhin
c496cca306 Release v0.8.1 2016-08-01 22:50:58 +02:00
Florian Bruhin
ef439bb916 Fix ;o/;O default bindings 2016-08-01 18:19:34 +02:00
Florian Bruhin
49699be44e Ignore TypeError on contents_size_changed cleanup 2016-08-01 17:40:41 +02:00
Florian Bruhin
81d0d64731 QtWebEngine: Fix crash when closing/reopening tabs 2016-08-01 17:25:55 +02:00
Florian Bruhin
5ec39b7540 Fix crash when opening http://foo%40bar@baz 2016-08-01 17:18:14 +02:00
Florian Bruhin
1f930a579a Merge branch 'blyxxyz-rss' 2016-08-01 16:30:39 +02:00
Florian Bruhin
e378ec7877 Regenerate authors 2016-08-01 16:30:38 +02:00
Florian Bruhin
d195592837 Merge branch 'rss' of https://github.com/blyxxyz/qutebrowser into blyxxyz-rss 2016-08-01 16:30:23 +02:00
Florian Bruhin
693210920c Fix completion widget unit tests 2016-08-01 16:29:47 +02:00
Florian Bruhin
15863065cb Fix <input /> test in test_webelem 2016-08-01 16:28:54 +02:00
Florian Bruhin
220a387d2d Merge branch 'mlochbaum-generalize-list-type' 2016-08-01 16:22:49 +02:00
Florian Bruhin
45abcbb972 Update authors 2016-08-01 16:22:22 +02:00
Florian Bruhin
68b273de87 Merge branch 'generalize-list-type' of https://github.com/mlochbaum/qutebrowser into mlochbaum-generalize-list-type 2016-08-01 16:22:13 +02:00
Florian Bruhin
8dacf7b4ce Merge branch 'mlochbaum-tab-move-index' 2016-08-01 16:18:23 +02:00
Florian Bruhin
ad05296e1b Update docs 2016-08-01 16:18:08 +02:00
Florian Bruhin
4414f5fea9 Merge branch 'tab-move-index' of https://github.com/mlochbaum/qutebrowser into mlochbaum-tab-move-index 2016-08-01 16:17:09 +02:00
Marshall Lochbaum
a7f9461d1f Correct valid_values handling for asciidoc 2016-08-01 10:15:51 -04:00
Florian Bruhin
9488cc61ef Merge branch 'rcorre-completer_tests' 2016-08-01 16:03:03 +02:00
Florian Bruhin
62f9161d03 Merge branch 'completer_tests' of https://github.com/rcorre/qutebrowser into rcorre-completer_tests 2016-08-01 16:02:53 +02:00
Florian Bruhin
149e0d7b05 Update changelog 2016-08-01 15:56:39 +02:00
Jan Verbeek
141e79f297 Add rss userscript 2016-08-01 15:55:13 +02:00
Florian Bruhin
86669600ff Consider input elements without type for hinting 2016-08-01 15:49:50 +02:00
Marshall Lochbaum
5accef963d Move _show_inner_type class variables before __init 2016-08-01 09:31:59 -04:00
Marshall Lochbaum
aa40ff6dd4 Remove none_ok from startpage config type 2016-08-01 09:30:26 -04:00
Florian Bruhin
81ad3bdcdc appveyor: Try to re-download PyQt on failure 2016-08-01 15:10:23 +02:00
Florian Bruhin
c421f44f4e Specify completion category font in HTML
It seems like specifying a font for QTreeView::item in a Qt stylesheet
doesn't actually do anything.
2016-08-01 14:56:51 +02:00
Florian Bruhin
fca3c28134 Merge branch 'nanjekyejoannah-master' 2016-08-01 14:38:11 +02:00
Florian Bruhin
cc94383785 Update docs 2016-08-01 14:37:58 +02:00
Florian Bruhin
1bba1e3ea9 Remove whitespace 2016-08-01 14:35:57 +02:00
Florian Bruhin
3d1f28ac9c Merge branch 'master' of https://github.com/nanjekyejoannah/qutebrowser into nanjekyejoannah-master 2016-08-01 14:35:06 +02:00
nanjekyejoannah
3d4e76b1a4 commit resolving issue#1395 2016-08-01 15:20:44 +03:00
nanjekyejoannah
4d3cbe659d refactor for configdatap.py resolving #1395 2016-08-01 14:30:20 +03:00
nanjekyejoannah
633c95bca6 resolving style things in commit resolving issue #1395 2016-08-01 14:14:15 +03:00
nanjekyejoannah
1e94685653 Refactoring to resolve issue #1395 2016-08-01 14:00:30 +03:00
Florian Bruhin
2baadaf565 Remove now useless pylint suppressions 2016-08-01 12:47:19 +02:00
Florian Bruhin
13269ef388 Wrap long lines 2016-08-01 12:46:47 +02:00
Florian Bruhin
a772e8a2c3 Mark :set-mark/:jump-mark as hidden
Fixes #1708.
2016-08-01 12:21:18 +02:00
Florian Bruhin
9eec3f25fb Merge branch 'rcorre-unix_filename_rubout' 2016-08-01 11:01:44 +02:00
Florian Bruhin
77f9696a96 Update docs 2016-08-01 11:01:33 +02:00
Florian Bruhin
7f311a46ae Merge branch 'unix_filename_rubout' of https://github.com/rcorre/qutebrowser into rcorre-unix_filename_rubout 2016-08-01 10:40:34 +02:00
Florian Bruhin
4c02717fa3 Merge branch 'LadyClaire-master' 2016-08-01 10:35:49 +02:00
Florian Bruhin
858fb77e19 Regenerate authors 2016-08-01 10:34:58 +02:00
Florian Bruhin
0865527631 Merge branch 'master' of https://github.com/LadyClaire/qutebrowser into LadyClaire-master 2016-08-01 10:29:58 +02:00
nanjekyejoannah
212d5fe932 commit resolving issue #1395 2016-08-01 11:28:27 +03:00
Florian Bruhin
12f506073a flake8/pylint reqs: Update mccabe to 0.5.2
When opening files ourselves, make sure we always name the file variable
2016-08-01 10:06:08 +02:00
Claire C.C
046eec9136 Remove extra "available" 2016-08-01 00:43:46 -07:00
Claire Cavanaugh
f261490dab Fix minor errors and improve flow of text 2016-07-31 21:43:54 -07:00
Ryan Roden-Corrent
86a08d17c2 Dedupe code in test_readline.
Many of the tests repeated the same block of logic, so consolidate it
into one function.
2016-07-30 22:00:12 -04:00
Ryan Roden-Corrent
a086095954 Implement unix_filename_rubout.
unix_filename_rubout deletes to the previous slash or whitespace,
unlike the previously implemented backwards-kill-word which treats and
non-alphanumeric character as a boundary.

To illustrate, given the text 'foo/bar.baz', unix_filename_rubout will
delete 'bar.baz' while backwards-kill-word will delete only 'baz'.

See #1710.
2016-07-30 19:34:38 -04:00
Florian Bruhin
57f256e80d Merge branch 'rcorre-backward-kill-word' 2016-07-30 18:49:58 +02:00
Florian Bruhin
09418d77a0 Update changelog 2016-07-30 18:49:10 +02:00
Ryan Roden-Corrent
6bcdacf1ce Implement readline's backward-kill-word.
This restores the previous behavior of `unix-word-rubout` as
`backward-kill-word`, which is closer to the naming used in readline.
It is bound to <Alt-Backspace> by default, though <Ctrl-Backspace> will
also work due to a builtin binding.

Resolves #1698.
2016-07-30 07:27:29 -04:00
Marshall Lochbaum
a7438f4f15 Extend tab-move's direction argument to take an index (fixes #1701) 2016-07-29 23:06:51 -04:00
Marshall Lochbaum
b22634e2eb Correct qutebrowser.conf documentation for list types 2016-07-29 16:08:42 -04:00
Ryan Roden-Corrent
fbadc5e668 Remove second arg from on_selection_changed.
The deselected argument was unused, so remove it from the signal and
the slot.
2016-07-29 08:48:24 -04:00
Florian Bruhin
f9c09a1f43 Merge branch 'lahwaacz-completion_trivial' 2016-07-29 12:08:28 +02:00
Florian Bruhin
b80ea14557 Regenerate authors 2016-07-29 12:08:23 +02:00
Florian Bruhin
14eabc7160 Merge branch 'completion_trivial' of https://github.com/lahwaacz/qutebrowser into lahwaacz-completion_trivial 2016-07-29 12:08:10 +02:00
Florian Bruhin
066c9bf4dc Split websettings into web{kit,engine,}settings 2016-07-29 12:01:22 +02:00
Florian Bruhin
c40059715a Fix long line 2016-07-29 10:43:53 +02:00
Florian Bruhin
08a9786a73 Add a stub for WebEnginePage.createWindow
See #1699.
2016-07-29 10:35:14 +02:00
Florian Bruhin
cffe2281b1 Use qtmodeltester for completion model tests
See http://pytest-qt.readthedocs.io/en/latest/modeltester.html
See #1702
2016-07-29 10:26:55 +02:00
Jakub Klinkovský
2a70146db1 Remove unneeded invalidateFilter call.
First done in b5781f0ed3 and later
reverted in a6f1bf29ae because it had
broken "completion->shrink", but that is no longer the case.
2016-07-29 10:15:21 +02:00
Jakub Klinkovský
119f9c0e18 completion: get rid of model-specific sort method (see #545) 2016-07-29 10:13:32 +02:00
Jakub Klinkovský
49327dfcbb completion: highlight only the matched terms
closes #1650
2016-07-29 10:13:32 +02:00
Jakub Klinkovský
caf5937585 completion: get rid of custom_filter (see #545) 2016-07-29 10:13:27 +02:00
Florian Bruhin
4bf94f3c24 Use order='strict' with qtbot.waitSignals
See #1702
2016-07-29 09:12:06 +02:00
Florian Bruhin
a7e9b4e5d7 Get rid of extend=True for qt_log_ignore
This is now the default, see #1702
2016-07-29 09:12:06 +02:00
Florian Bruhin
e5e2a6a943 pytest.ini: Get rid of qt_wait_signal_raising
This is now the default; see #1702
2016-07-29 09:12:06 +02:00
Florian Bruhin
2e40bd3a36 tox: Update pytest-qt to 2.0.0
See #1702.

Breaking Changes

With pytest-qt 2.0, we changed some defaults to values we think are much
better, however this required some backwards-incompatible changes:

- pytest-qt now defaults to using PyQt5 if PYTEST_QT_API is not set.
  Before, it preferred PySide which is using the discontinued Qt4.
- Python 3 versions prior to 3.4 are no longer supported.
- The @pytest.mark.qt_log_ignore mark now defaults to extend=True, i.e.
  extends the patterns defined in the config file rather than overriding
  them. You can pass extend=False to get the old behaviour of overriding
  the patterns.
- qtbot.waitSignal now defaults to raising=True and raises an exception
  on timeouts. You can set qt_wait_signal_raising = false in your config
  to get back the old behaviour.
- PYTEST_QT_FORCE_PYQT environment variable is no longer supported. Set
  PYTEST_QT_API to the appropriate value instead or the new qt_api
  configuration option in your pytest.ini file.

New Features

- From this version onward, pytest-qt is licensed under the MIT license.
- New qtmodeltester fixture to test QAbstractItemModel subclasses.
- waitSignal and waitSignals can receive an optional callback that can
  evaluate if the arguments of emitted signals should resume execution
  or not.
- Now which Qt binding pytest-qt will use can be configured by the
  qt_api config option.
- While pytestqt.qt_compat is an internal module and shouldn't be
  imported directly, it is known that some test suites did import it.
  This module now uses a lazy-load mechanism to load Qt classes and
  objects, so the old symbols (QtCore, QApplication, etc.) are no longer
  available from it.

Other Changes

- Exceptions caught by pytest-qt in sys.excepthook are now also printed
  to stderr, making debugging them easier from within an IDE.
2016-07-29 09:12:06 +02:00
Florian Bruhin
baca1bcde2 travis: Remove testing on Ubuntu Wily 2016-07-29 09:10:02 +02:00
Florian Bruhin
81ca5cbe44 Merge branch 'LadyClaire-master' 2016-07-29 09:06:16 +02:00
Florian Bruhin
88b2c20421 Update docs 2016-07-29 09:06:04 +02:00
Florian Bruhin
af704439d9 Remove trailing newline 2016-07-29 09:05:25 +02:00
Florian Bruhin
943cd6ff48 Merge branch 'master' of https://github.com/LadyClaire/qutebrowser into LadyClaire-master 2016-07-29 09:04:52 +02:00
Florian Bruhin
f218d5d4b6 Try harder to pin pip/setuptools 2016-07-29 09:03:31 +02:00
Claire Cavanaugh
e409eafe2a Add test for opening a quickmark 2016-07-28 23:36:05 -07:00
Claire Cavanaugh
3d258df23a Heil PEP8 :P 2016-07-28 23:24:34 -07:00
Claire Cavanaugh
bf44636a24 :open opens quickmark when given a quckmark name 2016-07-28 22:50:10 -07:00
Ryan Roden-Corrent
e8f73b0fe6 Break up MainWindow.__init__.
Split out initialization of a few areas into private functions so
pylint won't complain about a long method.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
dd827332c0 Clean up unused imports from completion refactor. 2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
f31e890862 Move completion_item_{next,prev} to CompletionView.
These commands are more closely tied to the CompletionView than
Completer. This removes the need for an extra signal tying the
CompletionView to the Completer.

The call to _open_completion_if_needed was moved to
on_selection_changed, as this will already be called when a new item is
selected.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
ffc5a42d04 Don't use objreg to get CompletionView.
The CompletionView is the parent of the Completer, so there's no need
to use objreg to get it.
See #640.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
b9cf9d180b Decouple Completer and CompletionView.
Rather than having a CompletionView instantiate and register a
Completer, instantiate both in MainWindow. The CompletionView is the
parent of the Completer, and communicates by emitting
selection_changed, meaning it no longer needs to contain a reference to
the Completer.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
d836fcb118 Code review for completion tests.
- clean up docstring typos
- use _ to name an unused loop variable
- parent the filter model to avoid an issue with disposal
- use mocker.patch instead of monkeypatch to mock Completer creation
- use is instead of == to compare by identity
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
415ad7a638 Unit test completion view. 2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
a740f99607 Register the fake statusbar command in objreg.
The CompletionView looks in objreg for 'status-cmd', so move it from a
private fixture in test_completer to a public fixture that handles
objreg registration/deletion.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
e5da179ebf Limit the public interface of Completer.
Only schedule_completion_update and selection_changed are used
externally, so mark the rest of the API as private.
2016-07-28 12:20:24 -04:00
Ryan Roden-Corrent
aedf5b930a Test Completer.schedule_completion_update.
update_completion is only used internally, so instead test the real
public entry point which is schedule_completion_update.

This required mocking out QTimer to fire immediately so the test didn't
have to do flaky artificial delays.
2016-07-28 12:20:24 -04:00
Florian Bruhin
b48b7eddc8 Add no-cover pragma for _rect_on_view_js 2016-07-28 17:33:04 +02:00
Florian Bruhin
80d4af0da2 Add test webelem.__eq__ with other type 2016-07-28 17:29:45 +02:00
Florian Bruhin
56515321dd Handle failing javascript in webelem.rect_on_view
Fixes #1641.
2016-07-28 17:10:31 +02:00
Florian Bruhin
5463e133ee Split webelem.rect_for_view into two methods 2016-07-28 17:09:07 +02:00
Florian Bruhin
d6b6afdf11 Fix WebElementWrapper.__eq__ 2016-07-28 15:57:25 +02:00
Florian Bruhin
3aa5eb86fb requirements: Update mccabe to 0.5.1
- Set default maximum complexity to -1 on the class itself
2016-07-28 15:55:41 +02:00
Florian Bruhin
1213b91b66 Fix ALL the contentsSizeChanged connections! 2016-07-28 15:29:56 +02:00
Florian Bruhin
9cbf9eaa76 Disconnect contents_size_changed during cleanup 2016-07-28 14:59:23 +02:00
Florian Bruhin
21c1dec59a Actually handle contents_size_changed correctly 2016-07-28 14:56:42 +02:00
Florian Bruhin
a0ae96d43e Add more WebElementWrapper tests 2016-07-28 14:46:32 +02:00
Florian Bruhin
d357ccf403 Add some more WebElementWrapper tests 2016-07-28 14:25:53 +02:00
Florian Bruhin
b0a0984fe7 Add missing check_vanished in remove_blank_target 2016-07-28 13:13:21 +02:00
Florian Bruhin
c674bda43c Add new tests for test_webelem.test_vanished
This also adds test IDs for easier debugging.
2016-07-28 13:12:47 +02:00
Florian Bruhin
a1fd161a4a Merge branch 'webelem' 2016-07-28 12:38:37 +02:00
Florian Bruhin
41e6a2392a QtWebEngine: Add stub for find_all_elements 2016-07-28 12:36:09 +02:00
Florian Bruhin
631109e5eb Fix raising of WebTabError 2016-07-28 12:36:09 +02:00
Florian Bruhin
d87840e254 Fix lint 2016-07-28 12:36:09 +02:00
Florian Bruhin
8d7baea9ae Fix test_passed_geometry 2016-07-28 12:36:09 +02:00
Florian Bruhin
ebc72c9b5f Fix TestRemoveBlankTarget.test_no_link 2016-07-28 12:36:09 +02:00
Florian Bruhin
540c62c232 Add only_visible to find_all_elements 2016-07-28 12:36:09 +02:00
Florian Bruhin
5b943a431e Fix WebElementWrapper.text 2016-07-28 12:36:09 +02:00
Florian Bruhin
49f57a5d7e Fix userscripts 2016-07-28 12:36:09 +02:00
Florian Bruhin
5eca6e11a5 Fix editor/paste-primary 2016-07-28 12:36:09 +02:00
Florian Bruhin
e051de4843 Fix word hinting 2016-07-28 12:36:09 +02:00
Florian Bruhin
ffdaf8d470 Move webelem.is_visible/.rect_on_view to methods 2016-07-28 12:36:09 +02:00
Florian Bruhin
4318604c57 Don't use javascript in webelem.set_text for hints 2016-07-28 12:36:09 +02:00
Florian Bruhin
193c755637 Refactor WebElement API, part 2
Now we don't get a crash, but not any hints either...
2016-07-28 12:35:59 +02:00
Florian Bruhin
c5a91004f5 Add contents_size_changed to tab API 2016-07-28 12:35:56 +02:00
Florian Bruhin
c764733472 Refactor QWebElement API, part 1 2016-07-28 12:35:49 +02:00
Florian Bruhin
243ba02f5f Revert "Add -bb for pytest python invocations"
This reverts commit 285cf105f0.

This is currently blocked by
https://github.com/HypothesisWorks/hypothesis-python/pull/350
2016-07-28 09:10:25 +02:00
Florian Bruhin
016c13a998 Use repr() for rfc2622 logging 2016-07-28 07:28:21 +02:00
Florian Bruhin
190db8bf5e Also pass -bb to python for end2end tests 2016-07-28 07:19:59 +02:00
Florian Bruhin
79b3f26de8 Decode HTML in test_filescheme
Otherwise we get a BytesWarning inside BeautifulSoup
2016-07-28 07:19:09 +02:00
Florian Bruhin
caab826e8a Use repr() for IPC logging messages 2016-07-28 07:14:54 +02:00
Florian Bruhin
285cf105f0 Add -bb for pytest python invocations
This means Python will show an error if bytes/str are compared or str()
is used on a bytes object.
2016-07-28 07:06:13 +02:00
Florian Bruhin
dfb7ba29fd Adjust PyPEG2 install instructions for Debian 2016-07-27 22:43:40 +02:00
Florian Bruhin
b5d3fa763a Add pytest_warnings to run_frozen_tests.py 2016-07-27 20:44:21 +02:00
Marshall Lochbaum
2c37de3ac1 Revert startpage config type to String instead of Url 2016-07-27 14:21:25 -04:00
Florian Bruhin
ed43e12c3e Add (unreleased) to changelog 2016-07-27 19:45:37 +02:00
Florian Bruhin
73cd0e01ef Fix deleting of quickmarks with ctrl-d 2016-07-27 19:44:34 +02:00
Florian Bruhin
263ecee1a3 flake8 reqs: Update flake8-string-format to 0.2.3
Properly register with Flake8 so it will be selected on Flake8 3.x by
default and it can be selected on Flake8 2.x.
2016-07-27 19:41:24 +02:00
Marshall Lochbaum
d51b1733e4 Add List to test_configtypes_hypothesis 2016-07-27 13:14:51 -04:00
Marshall Lochbaum
642abac634 Remove BaseList type 2016-07-27 13:06:15 -04:00
Marshall Lochbaum
b205ad500b Add tests for configtypes.Url 2016-07-27 12:44:10 -04:00
Marshall Lochbaum
b4fec256dc Merge LengthList into List 2016-07-27 12:39:03 -04:00
Florian Bruhin
7605a4fb0c tests: Use pytest-warnings to handle warnings 2016-07-27 18:28:08 +02:00
Florian Bruhin
1ebf2bab1c Whoops, remove conflict marker 2016-07-27 12:43:15 +02:00
Florian Bruhin
48fc89ca88 Whoops, remove conflict marker 2016-07-27 12:42:53 +02:00
Florian Bruhin
d8153f7010 Whoops, remove conflict marker 2016-07-27 12:42:22 +02:00
Florian Bruhin
04aa98d7fb Release v0.8.1 2016-07-27 12:41:40 +02:00
Florian Bruhin
0eb74dcc1b Hide harfbuzz warning if frozen 2016-07-27 12:15:10 +02:00
Florian Bruhin
7b82d81784 Improve error message on OS X without QtWebEngine 2016-07-27 12:13:22 +02:00
Florian Bruhin
9ff006746f Handle empty command in CommandRunner.parse_all
Sicne we now call self._get_alias there, we also need to make sure it's
not an empty string before that.

Introduced in #1577. Fixes #1690.
2016-07-27 11:19:01 +02:00
Florian Bruhin
be609d5779 Improve logging for BaseKeyParser
See #1653
2016-07-27 10:27:53 +02:00
Florian Bruhin
b98d970393 Merge branch 'flv0-savefile_open-flush' 2016-07-27 10:11:51 +02:00
Florian Bruhin
fbac4cb95f Regenerate authors 2016-07-27 10:11:44 +02:00
Florian Bruhin
ccbd47a0cd Merge branch 'savefile_open-flush' of https://github.com/flv0/qutebrowser into flv0-savefile_open-flush 2016-07-27 10:11:33 +02:00
Florian Bruhin
2970bbcf03 codeov/test requirements: Update coverage to 4.2
Version 4.2
------------

- Since concurrency=multiprocessing uses subprocesses, options specified
  on the coverage.py command line will not be communicated down to them.
  Only options in the configuration file will apply to the subprocesses.
  Previously, the options didn't apply to the subprocesses, but there
  was no indication. Now it is an error to use
  --concurrency=multiprocessing and other run-affecting options on the
  command line. This prevents failures like those reported in issue 495.
- Filtering the HTML report is now faster, thanks to Ville Skyttä.

Version 4.2b1
-------------

Work from the PyCon 2016 Sprints!

- BACKWARD INCOMPATIBILITY: the coverage combine command now ignores an
  existing .coverage data file. It used to include that file in its
  combining. This caused confusing results, and extra tox "clean" steps.
  If you want the old behavior, use the new coverage combine --append
  option.
- The concurrency option can now take multiple values, to support
  programs using multiprocessing and another library such as eventlet.
  This is only possible in the configuration file, not from the command
  line. The configuration file is the only way for sub-processes to all
  run with the same options.
- Using a concurrency setting of multiprocessing now implies --parallel
  so that the main program is measured similarly to the sub-processes.
- When using automatic subprocess measurement, running coverage commands
  would create spurious data files. This is now fixed.
- A new configuration option, report:sort, controls what column of the
  text report is used to sort the rows.
- The HTML report has a more-visible indicator for which column is being
  sorted.
- If the HTML report cannot find the source for a file, the message now
  suggests using the -i flag to allow the report to continue.
- When reports are ignoring errors, there's now a warning if a file
  cannot be parsed, rather than being silently ignored.
- A new option for coverage debug is available: coverage debug config
  shows the current configuration.
- Running coverage as a module (python -m coverage) no longer shows the
  program name as __main__.py.
- The test_helpers module has been moved into a separate pip-installable
  package: unittest-mixins.
2016-07-27 06:37:02 +02:00
Florian Bruhin
94f006a675 pylint requirements: Update astroid to 1.4.8
* Add `returns` into the proper order in FunctionDef._astroid_fields

  The order is important, since it determines the last child,
  which in turn determines the last line number of a scoped node.
2016-07-27 06:32:29 +02:00
Marshall Lochbaum
a3c7ed51d4 Create LengthList to remove WebKitBytesList and refactor Padding 2016-07-26 23:59:55 -04:00
Marshall Lochbaum
083baf1222 Remove unnecessary List subclasses 2016-07-26 23:05:42 -04:00
Marshall Lochbaum
9e86933913 Replace List with BaseList and rename GenList to List 2016-07-26 23:02:10 -04:00
Marshall Lochbaum
d77145a5b8 Add GenList type and refactor *List types to use GenList 2016-07-26 21:34:50 -04:00
Florian Bruhin
f460a225ef Merge branch 'paretje-focuspass' 2016-07-27 00:15:38 +02:00
Florian Bruhin
5da67a677d Regenerate authors 2016-07-27 00:15:27 +02:00
Florian Bruhin
8f42fcf627 Merge branch 'focuspass' of https://github.com/paretje/qutebrowser into paretje-focuspass 2016-07-27 00:15:15 +02:00
Florian Bruhin
cd905841e0 Don't log on_focus_changed warning if new is None 2016-07-26 23:27:20 +02:00
Florian Bruhin
2121865bdd Show jsret value in update_scroll_pos callback 2016-07-26 23:26:20 +02:00
Florian Bruhin
414f09f648 Merge branch 'mlochbaum-bookmark-load-delete' 2016-07-26 21:28:24 +02:00
Florian Bruhin
0405a05d34 Update docs 2016-07-26 21:28:14 +02:00
Kevin Velghe
8d091b2ae8 Drop focus after field has been filled 2016-07-26 21:25:04 +02:00
Marshall Lochbaum
826d0befe0 Update number files 2016-07-26 13:57:35 -04:00
Marshall Lochbaum
b2c2d5a4f4 Add --delete option to bookmark-load 2016-07-26 13:49:17 -04:00
Florian Bruhin
1ac45d8971 travis: Switch bot to #qutebrowser-dev 2016-07-26 18:18:53 +02:00
Florian Bruhin
55f4777d72 build_release: Fix call_tox with no python on Win 2016-07-26 17:55:26 +02:00
Florian Bruhin
24f3703615 Merge branch 'mlochbaum-bookmark-add-toggle' 2016-07-26 17:30:17 +02:00
Florian Bruhin
29fd292aa4 Update docs 2016-07-26 17:30:07 +02:00
Florian Bruhin
84cfbced05 Merge branch 'bookmark-add-toggle' of https://github.com/mlochbaum/qutebrowser into mlochbaum-bookmark-add-toggle 2016-07-26 17:27:40 +02:00
Florian Bruhin
311f531d88 build_release: Fix tox call 2016-07-26 17:00:32 +02:00
Florian Bruhin
a6af9d7d35 flake8 reqs: Undo accidental pep8 downgrade 2016-07-26 16:51:45 +02:00
Florian Bruhin
d19c7012a5 flake8 reqs: Update flake8-docstrings to 1.0.2
- Use pycodestyle to get standard-in.
2016-07-26 16:51:19 +02:00
Florian Bruhin
180d113914 build_release: Fix running smoke test on OS X 2016-07-26 16:49:44 +02:00
Florian Bruhin
901ccebca6 Revert "build_release: Use -quiet for hdiutil"
This reverts commit e2ea04691e.

Otherwise we don't get any information on errors...
2016-07-26 16:49:07 +02:00
Florian Bruhin
e2ea04691e build_release: Use -quiet for hdiutil 2016-07-26 16:39:10 +02:00
Florian Bruhin
86bd42ec93 build_release: Rebuild tox environments
This way we can be sure we have updated dependencies installed.
2016-07-26 16:38:32 +02:00
Florian Bruhin
12007dd0d0 DMG Makefile: Don't generate template.dmg.bz2
Let's not have this in the workingdir, instead just regenerate it every
time.
2016-07-26 16:30:34 +02:00
Florian Bruhin
ed67b988f9 DMG Makefile: Increase template size to 300 MB
Otherwise QtWebEngine wouldn't fit.
2016-07-26 16:29:29 +02:00
Florian Bruhin
b30773aa68 flake8 requirements: Add comment for pep8 pin 2016-07-26 16:14:21 +02:00
Florian Bruhin
54b9ead0d0 flake8 reqs: Update flake8-docstrings to 1.0.1
1.0.1
-----

Make sure this works out of the box (is enabled by default) with
Flake8 3.0

1.0.0
-----

Switch dependency name to pydocstyle. pep257 was renamed to pydocstyle,
this update switches the requirement to that new package name. Since
we’re swapping out dependencies, we’ve issued a major version bump.
2016-07-26 16:12:23 +02:00
Kevin Velghe
e9e780ac56 Focus fields before filling them 2016-07-26 16:12:19 +02:00
Florian Bruhin
fb20352e3f build_release: Add smoke test for OS X
This should prevent something like #1686 in the future.
2016-07-26 16:10:25 +02:00
Marshall Lochbaum
d9247c15a4 Coding style fixes 2016-07-26 09:48:35 -04:00
Marshall Lochbaum
ae7fe2ee33 Update number files 2016-07-26 09:14:51 -04:00
Marshall Lochbaum
28842c90b6 Add --toggle flag to bookmark-add (fixes #1667) 2016-07-26 09:07:21 -04:00
Patric Schmitz
217b912f3c revert custom exception throwing in savefile_open
instead adapt test_failing_flush to catch correct exception (ValueError).
2016-06-28 15:03:23 +02:00
Patric Schmitz
a33978ee89 fix error handling in savefile_open and tests 2016-06-28 12:59:00 +02:00
Patric Schmitz
69ce9a942c move savefile flush into try: block
it seems flush might throw which will not be caught inside the (try-)
else branch. (hopefully) fixes config corruption when no space
available.
2016-06-28 00:58:56 +02:00
413 changed files with 46306 additions and 14085 deletions

View File

@@ -1 +0,0 @@
qutebrowser/3rdparty/pdfjs/*

View File

@@ -1,49 +0,0 @@
# vim: ft=yaml
env:
browser: true
rules:
block-scoped-var: 2
dot-location: 2
default-case: 2
guard-for-in: 2
no-div-regex: 2
no-param-reassign: 2
no-eq-null: 2
no-floating-decimal: 2
no-self-compare: 2
no-throw-literal: 2
no-void: 2
radix: 2
wrap-iife: [2, "inside"]
brace-style: [2, "1tbs", {"allowSingleLine": true}]
comma-style: [2, "last"]
consistent-this: [2, "self"]
func-style: [2, "declaration"]
indent: [2, 4, {"SwitchCase": 1}]
linebreak-style: [2, "unix"]
max-nested-callbacks: [2, 3]
no-lonely-if: 2
no-multiple-empty-lines: [2, {"max": 2}]
no-nested-ternary: 2
no-unneeded-ternary: 2
operator-assignment: [2, "always"]
operator-linebreak: [2, "after"]
keyword-spacing: 2
space-before-blocks: [2, "always"]
space-before-function-paren: [2, {"anonymous": "never", "named": "never"}]
object-curly-spacing: [2, "never"]
array-bracket-spacing: [2, "never"]
computed-property-spacing: [2, "never"]
space-in-parens: [2, "never"]
space-unary-ops: [2, {"words": true, "nonwords": false}]
spaced-comment: [2, "always"]
max-depth: [2, 5]
max-len: [2, 79, 4]
max-params: [2, 5]
max-statements: [2, 30]
no-bitwise: 2
quote-props: [2, "always"]
global-strict: 0
quotes: 0

15
.flake8
View File

@@ -6,6 +6,9 @@ exclude = .*,__pycache__,resources.py
# E501: Line too long
# E402: module level import not at top of file
# E266: too many leading '#' for block comment
# E722: do not use bare except
# E731: do not assign a lambda expression, use a def
# (for pytest's __tracebackhide__)
# F401: Unused import
# N802: function name should be lowercase
# P101: format string does contain unindexed parameters
@@ -21,18 +24,12 @@ exclude = .*,__pycache__,resources.py
# D402: First line should not be function's signature (false-positives)
# D403: First word of the first line should be properly capitalized
# (false-positives)
# H101: Use TODO(NAME)
# H201: bare except
# H238: Use new-stule classes
# H301: one import per line
# H306: imports not in alphabetical order
ignore =
E128,E226,E265,E501,E402,E266,
E128,E226,E265,E501,E402,E266,E722,E731,
F401,
N802,
P101,P102,P103,
D102,D103,D104,D105,D209,D211,D402,D403,
H101,H201,H238,H301,H306
D102,D103,D104,D105,D209,D211,D402,D403
min-version = 3.4.0
max-complexity = 12
putty-auto-ignore = True
@@ -41,6 +38,8 @@ putty-ignore =
/# pylint: disable=wildcard-import/ : +F403
/# pragma: no mccabe/ : +C901
tests/*/test_*.py : +D100,D101,D401
tests/unit/browser/webkit/test_history.py : +N806
tests/helpers/fixtures.py : +N806
tests/unit/browser/webkit/http/test_content_disposition.py : +D400
scripts/dev/ci/appveyor_install.py : +FI53
copyright-check = True

View File

@@ -1,4 +1,2 @@
Please remember to mention your version info (qutebrowser, Qt, PyQt,
OS/distribution) from the `qute:version` page or `qutebrowser --version`
---
<!-- If this is a bug report, please remember to mention your version info from
the `qute:version` page or `qutebrowser --version` -->

13
.gitignore vendored
View File

@@ -20,7 +20,7 @@ __pycache__
/FAQ.html
/INSTALL.html
/qutebrowser/html/doc/
/.venv
/.venv*
/.coverage
/htmlcov
/coverage.xml
@@ -33,7 +33,12 @@ __pycache__
/prof
/venv
TODO
/scripts/testbrowser_cpp/Makefile
/scripts/testbrowser_cpp/main.o
/scripts/testbrowser_cpp/testbrowser
/scripts/testbrowser_cpp/webkit/Makefile
/scripts/testbrowser_cpp/webkit/main.o
/scripts/testbrowser_cpp/webkit/testbrowser
/scripts/testbrowser_cpp/webkit/.qmake.stash
/scripts/testbrowser_cpp/webengine/Makefile
/scripts/testbrowser_cpp/webengine/main.o
/scripts/testbrowser_cpp/webengine/testbrowser
/scripts/testbrowser_cpp/webengine/.qmake.stash
/scripts/dev/pylint_checkers/qute_pylint.egg-info

View File

@@ -68,9 +68,12 @@ max-args=10
valid-metaclass-classmethod-first-arg=cls
[TYPECHECK]
# WORKAROUND for https://github.com/PyCQA/astroid/pull/357
ignored-modules=pytest
# MsgType added as WORKAROUND for
# https://bitbucket.org/logilab/pylint/issues/690/
# UnsetObject because pylint infers any objreg.get(...) as UnsetObject.
ignored-classes=qutebrowser.utils.objreg.UnsetObject,
qutebrowser.browser.webkit.webelem.WebElementWrapper,
scripts.dev.check_coverage.MsgType
scripts.dev.check_coverage.MsgType,
qutebrowser.browser.downloads.UnsupportedAttribute

View File

@@ -13,13 +13,33 @@ matrix:
env: DOCKER=archlinux
services: docker
- os: linux
env: DOCKER=ubuntu-wily
env: DOCKER=archlinux-webengine QUTE_BDD_WEBENGINE=true
services: docker
- os: linux
env: DOCKER=archlinux-ng
services: docker
- os: linux
env: DOCKER=ubuntu-xenial
services: docker
- os: linux
language: python
python: 3.6
env: TESTENV=py36-pyqt571
- os: linux
language: python
python: 3.5
env: TESTENV=py35-pyqt58
- os: linux
language: python
python: 3.6
env: TESTENV=py36-pyqt58
- os: osx
env: TESTENV=py35
env: TESTENV=py36 OSX=elcapitan
osx_image: xcode7.3
# https://github.com/qutebrowser/qutebrowser/issues/2013
# - os: osx
# env: TESTENV=py35 OSX=yosemite
# osx_image: xcode6.4
- os: linux
env: TESTENV=pylint
- os: linux
@@ -38,12 +58,14 @@ matrix:
env: TESTENV=eslint
allow_failures:
- os: osx
env: TESTENV=py35
env: TESTENV=py36 OSX=elcapitan
osx_image: xcode7.3
fast_finish: true
cache:
directories:
- $HOME/.cache/pip
- $HOME/build/The-Compiler/qutebrowser/.cache
- $HOME/build/qutebrowser/qutebrowser/.cache
before_install:
# We need to do this so we pick up the system-wide python properly
@@ -63,8 +85,8 @@ notifications:
- https://buildtimetrend.herokuapp.com/travis
irc:
channels:
- "chat.freenode.net#qutebrowser"
on_success: change
- "chat.freenode.net#qutebrowser-dev"
on_success: always
on_failure: always
skip_join: true
template:

View File

@@ -14,6 +14,320 @@ This project adheres to http://semver.org/[Semantic Versioning].
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
v0.10.0
-------
Added
~~~~~
- Userscripts now have a new `$QUTE_COMMANDLINE_TEXT` environment variable, containing the current commandline contents
- New `ripbang` userscript to create a searchengine from a duckduckgo bang
- link:https://github.com/annulen/webkit/wiki[QtWebKit Reloaded] (also called QtWebKit-NG) is now fully supported
- Various new functionality with the QtWebEngine backend:
* Printing support with Qt >= 5.8
* Proxy support with Qt >= 5.8
* Tor the `general -> print-element-backgrounds` option with Qt >= 5.8
* The `content -> cookies-store` option
* The `storage -> cache-size` option
* The `colors -> webpage.bg` option
* The HTML5 fullscreen API (e.g. youtube videos) with QtWebEngine
* `:download --mhtml`
- New `qute:history` URL and `:history` command to show the browsing history
- Open tabs are now auto-saved on each successful load and restored in case of a crash
- `:jseval` now has a `--file` flag so you can pass a javascript file
- `:session-save` now has a `--only-active-window` flag to only save the active window
- OS X builds are back, and built with QtWebEngine
Changed
~~~~~~~
- PyQt 5.7/Qt 5.7.1 is now required for the QtWebEngine backend
- Scrolling with the scrollwheel while holding shift now scrolls sideways
- New way of clicking hints with which solves various small issues
- When yanking a mailto: link via hints, the mailto: prefix is now stripped
- Zoom level messages are now not stacked on top of each other anymore
- qutebrowser now automatically uses QtWebEngine if QtWebKit is unavailable
- :history-clear now asks for a confirmation, unless it's run with --force.
- `input -> mouse-zoom-divider` can now be 0 to disable zooming by mouse wheel
- `network -> proxy` can also be set to `pac+file://...` now to
use a local proxy autoconfig file (on QtWebKit)
Fixed
~~~~~
- Various bugs with Qt 5.8 and QtWebEngine:
* Segfault when closing a window
* Segfault with when closing a tab with a search active
* Fixed various mouse actions (like automatically entering insert mode) not working
* Fixed hints sometimes not working
* Segfault when opening a URL after a QtWebEngine renderer process crash
- Other QtWebEngine fixes:
* Insert mode now gets entered correctly with a non-100% zoom
* Crash reports are now re-enabled when using QtWebEngine
* Fixed crashes when closing tabs while hinting
* Using :undo or :tab-clone with a view-source:// or chrome:// tab is now prevented, as it segfaults
- `:enter-mode` now refuses to enter modes which can't be entered manually (which caused crashes)
- `:record-macro` (`q`) now doesn't try to record macros for special keys without a text
- Fixed PAC (proxy autoconfig) not working with QtWebKit
- `:download --mhtml` now uses the new file dialog
- Word hints are now upper-cased correctly when hints -> uppercase is true
- Font validation is now more permissive in the config, allowing e.g. "Terminus
(TTF)" as font name
- Fixed starting on newer PyQt/sip versions with LibreSSL
- When downloading files with QtWebKit, a User-Agent header is set when possible
- Fixed showing of keybindings in the :help completion
- `:navigate prev/next` now detects `rel` attributes on `<a>` elements, and
handles multiple `rel` attributes correctly
- Fixed a crash when hinting with target `userscript` and spawning a non-existing script
- Lines in Jupyter notebook now trigger insert mode
v0.9.1
------
Fixed
~~~~~
- Prevent websites from downloading files to a location outside of the download
folder with QtWebEngine.
v0.9.0
------
Added
~~~~~
- *New dependency:* qutebrowser now depends on the Qt QML module, which is
packaged separately in some distributions (as Qt Declarative/QML/Quick).
- New `:rl-backward-kill-word` command which does what `:rl-unix-word-rubout`
did before v0.8.0.
- New `:rl-unix-filename-rubout` command which is similar to readline's
`unix-filename-rubout`.
- New `fonts -> completion.category` setting to customize the font used for
completion category headers.
- New `:debug-log-capacity` command to adjust how many lines are logged into RAM
(to report bugs which are difficult to reproduce).
- New `hide-unmatched-rapid-hints` option to not hide hint unmatched hint labels
in rapid mode.
- New `{clipboard}` and `{primary}` replacements for the commandline which
replace the `:paste` command.
- New `:insert-text` command to insert a given text into a field on the page,
which replaces `:paste-primary` together with the `{primary}` replacement.
- New `:window-only` command to close all other windows.
- New `prev-category` and `next-category` arguments to `:completion-item-focus`
to focus the previous/next category in the completion (bound to `<Ctrl-Tab>`
and `<Ctrl-Shift-Tab>` by default).
- New `:click-element` command to fake a click on a element.
- New `:debug-log-filter` command to change console log filtering on-the-fly.
- New `:debug-log-level` command to change the console loglevel on-the-fly.
- New `general -> yank-ignored-url-parameters` option to configure which URL
parameters (like `utm_source` etc.) to strip off when yanking an URL.
- Support for the
https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API[HTML5 page visibility API]
- New `readability` userscript which shows a readable version of a page (using
the `readability-lxml` python package)
- New `cast` userscript to show a video on a Google Chromecast
- New `:run-with-count` command which replaces the (undocumented) `:count:command` syntax.
- New `:record-macro` (`q`) and `:run-macro` (`@`) commands for keyboard macros.
- New `ui -> hide-scrollbar` setting to hide the scrollbar independently of the
`user-stylesheet` setting.
- New `general -> default-open-dispatcher` setting to configure what to open
downloads with (instead of e.g. `xdg-open` on Linux).
- Support for PAC (proxy autoconfig) with QtWebKit
Changed
~~~~~~~
- Hints are now drawn natively in Qt instead of using web elements. This has a
few implications for users:
* The `hints -> opacity` setting does not exist anymore, but you can use
`rgba(r, g, b, alpha)` colors instead for `colors -> hints.bg`.
* The `hints -> font` setting is not affected by
`fonts -> web-family-fixed` anymore. Thus, a transformer got added to
change `Monospace` to `${_monospace}`.
* Gradients in hint colors can now be configured by using `qlineargradient`
and friends instead of `-webkit-gradient`. The most common cases get
migrated automatically, but if you drastically changed the defaults,
you'll need to manually adjust your config.
* Styling hints by styling `qutehint` elements in `user-stylesheet` was
never officially supported and does not work anymore.
* Hints are now not affected by the page's stylesheet or zoom anymore.
- `:bookmark-add` now has a `--toggle` flag which deletes the bookmark if it
already exists.
- `:bookmark-load` now has a `--delete` flag which deletes the bookmark after
loading it.
- `:open` now also accepts quickmark names instead of URLs
- `:tab-move` now optionally takes an index for absolute moving.
- Commands taking either an argument or a count (like `:zoom` or `:tab-focus`)
now prefer the count instead of showing an error message.
- `:open` now has an `--implicit` argument to treat the opened tab as implicit
(i.e. to open it at the position it would be opened if it was a clicked link)
- `:download-open` and `:prompt-open-download` now have an optional `cmdline`
argument to pass a commandline to open the download with.
- `:yank` now has a position argument to select what to yank instead of using
flags.
- Replacements like `{url}` can now also be used in the middle of an argument.
Consequently, commands taking another command (`:later`, `:repeat` and
`:bind`) now don't immediately evaluate variables.
- Tab titles in the `:buffer` completion now update correctly when a page's
title is changed via javascript.
- `:hint` now has a `--mode <mode>` flag to override the hint mode configured
using the `hints -> mode` setting.
- With `new-instance-open-target` set to a tab option, the tab is now opened in
the most recently focused (instead of the last opened) window. This can be
configured with the new `new-instance-open-target.window` setting.
It can also be set to `last-visible` to show the pages in the most recently
visible window, or `first-opened` to use the first (oldest) available window.
- Word hints now are more clever about getting the element text from some elements.
- Completions for `:help` and `:bind` now also show hidden commands
- The `:buffer` completion now also filters using the first column (id).
- `:undo` has been improved to reopen tabs at the position they were closed.
- `:navigate` now takes a count for `up`/`increment`/`decrement`.
- The `hints -> auto-follow` setting now can be set to
`always`/`full-match`/`unique-match`/`never` to more precisely control when
hints should be followed automatically.
- Counts can now be used with special keybindings (e.g. with modifiers).
This was already implemented for v0.7.0 originally, but got reverted because
it caused some issues and then never re-applied.
- Sending a command to an existing instance (via "qutebrowser :reload") now
doesn't mark it as urgent anymore.
- `tabs -> title-format` now treats an empty string as valid.
- Bindings for `:`, `/` and `?` are now configured explicitly and not hardcoded
anymore.
- The `completion -> show` setting can now be set to `always`, `auto` or
`never`.
- `:open-editor` can now be used in any mode.
- Lots of improvements to and bugfixes for the QtWebEngine backend, such as
working hints. However, using qutebrowser directly from git is still advised
when using `--backend webengine`.
- `content -> javascript-can-open-windows` got renamed to
`javascript-can-open-windows-automatically`.
- `:prompt-accept` now optionally accepts a value which overrides the one
entered in the input box. `yes` and `no` can be used as values for yes/no
questions.
- The new `--qt-arg` and `--qt-flag` arguments can be used to pass
arguments/flags to Qt's commandline.
- Error/warning/info messages are now shown stacked above the statusbar.
This also added various new settings:
* `colors -> messages.fg.error` (renamed from `statusbar.fg.error`)
* `colors -> messages.bg.error` (renamed from `statusbar.bg.error`)
* `colors -> messages.border.error`
* `colors -> messages.fg.warning` (renamed from `statusbar.fg.warning`)
* `colors -> messages.bg.warning` (renamed from `statusbar.bg.warning`)
* `colors -> messages.border.warning`
* `colors -> messages.fg.info`
* `colors -> messages.bg.info`
* `colors -> messages.border.info`
* `fonts -> messages.error`
* `fonts -> messages.warning`
* `fonts -> messages.info`
- The `qute:settings` page now also shows option descriptions.
- `qute:version` and `qutebrowser --version` now show various important paths
- `:spawn`/userscripts now show a nicer error when a script wasn't found
- Various functionality now works when javascript is disabled with QtWebKit
- Various commands/settings taking `left`/`right`/`previous` arguments now take
`prev`/`next`/`last-used` to remove ambiguity.
- The `ui -> user-stylesheet` setting now only takes filenames, not CSS snippets
- `ui -> window-title-format` now has a new `{backend} ` replacement
- `:hint` has a new `--add-history` argument to add the URL to the history for
yank/spawn targets.
- `:set` now cycles through values if more than one argument is given.
- `:open` now opens `default-page` without an URL even without `-t`/`-b`/`-w` given.
Deprecated
~~~~~~~~~~
- The `:paste` command got deprecated as `:open` with `{clipboard}` and
`{primary}` can be used instead.
- The `:paste-primary` command got deprecated as `:insert-text {primary}` can
be used instead.
- The `:prompt-yes` and `:prompt-no` commands got deprecated as
`:prompt-accept yes` and `:prompt-accept no` can be used instead.
Removed
~~~~~~~
- The `:yank-selected` command got merged into `:yank` as `:yank selection`
and thus removed.
- The `:completion-item-prev` and `:completion-item-next` commands got merged
into a new `:completion-focus {prev,next}` command and thus removed.
- The `ui -> hide-mouse-cursor` setting since it was completely broken and
nobody seemed to care.
- The `hints -> opacity` setting - see the "Changed" section for details.
- The `completion -> auto-open` setting got merged into `completion -> show` and
thus removed.
- All `--qt-*` arguments got replaced by `--qt-arg` and `--qt-flag` and thus
removed.
- The `-c`/`--confdir`, `--datadir` and `--cachedir` arguments got removed, as
`--basedir` should be sufficient.
Fixed
~~~~~
- `:undo` now doesn't undo tabs "closed" by `:tab-detach` anymore.
- Fixed an issue with hint chars not being cleared correctly when leaving hint
mode.
- `:tab-detach` now fails correctly when there's only one tab open.
- Various small issues with the command completion
- Fixed hang when using multiple spaces in a row with the URL completion
- qutebrowser now still starts with an incorrectly configured
`$XDG_RUNTIME_DIR`.
- Fixed crash when a userscript writes invalid unicode data to the FIFO
- Fixed crash when a included HTML was not found
v0.8.3
------
Fixed
~~~~~
- Fixed crash when doing `:<space><enter>`, another corner-case introduced in v0.8.0
- Fixed `:open-editor` (`<Ctrl-e>`) on Windows
- Fixed crash when setting `general -> auto-save-interval` to a too big value.
- Fixed crash when using hints on Void Linux.
- Fixed compatibility with Python 3.5.2+ on Debian unstable
- Compatibility with pdfjs v1.6.210
- `:bind` can now be used to bind to an alias (binding by editing `keys.conf`
already worked before)
- The command completion now updates correctly when changing aliases
- The tabbar now displays correctly with the Adwaita Qt theme
- The default `sk` keybinding now sets the commandline to `:bind` correctly
- Fixed crash when closing a window without focusing it
- Userscripts now can access QUTE_FIFO correctly on Windows
v0.8.2
------
Fixed
~~~~~
- Fixed `general -> private-browsing` not being set correctly until a restart
(which caused e.g. local storage to be enabled).
- When hinting input fields (`:t`), also consider input elements without a type.
- Fixed crash when opening an invalid URL with a percent-encoded and a real @ in it
- Fixed default `;o` and `;O` bindings
- Fixed local storage not working (and possible other bugs) when using a
relative path with `--basedir`.
- Fixed crash when deleting a quickmark with Ctrl-D
- Fixed HTML5 video playback on Windows
- Fixed crash when using `:prompt-open-download` with a file with chars not
encodable with the OS' filesystem encoding (e.g. with `LC_ALL=C`)
- Fixed `:prompt-open-download` with a too long filename (> 255 bytes)
- Fixed crash when cancelling a download after doing `:prompt-open-download`
- Fixed crash when writing a download to disk fails with
`:prompt-open-download`.
- Fixed `:restart` deleting the basedir when it was given with `--basedir`.
v0.8.1
------
Fixed
~~~~~
- Fix crash when pressing enter without a command
- Adjust error message to point out QtWebEngine is unsupported with the OS
X .app currently.
- Hide Harfbuzz warning with the OS X .app
v0.8.0
------
@@ -33,7 +347,7 @@ Added
`$QUTE_DOWNLOAD_DIR` available for userscripts.
- New option `ui` -> `status-position` to configure the position of the
status bar (top/bottom).
- New `--pdf <filename>` argument for `:print` which can be used to generate a
- New `--pdf <filename>` argument for `:print` WHICH can be used to generate a
PDF without a dialog.
Changed
@@ -108,7 +422,6 @@ Changed
- `:navigate` now clears the URL fragment
- `:completion-item-del` (`Ctrl-D`) can now be used in `:buffer` completion to
close a tab
- Counts can now be used with special keybindings (e.g. with modifiers)
- Various SSL ciphers are now disabled by default. With recent Qt/OpenSSL
versions those already all are disabled, but with older versions they might
not be.
@@ -568,7 +881,7 @@ Fixed
- Fixed horrible completion performance when the `shrink` option was set.
- Sessions now store zoom/scroll-position correctly.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.2.1[v0.2.1]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.2.1[v0.2.1]
-----------------------------------------------------------------------
Fixed
@@ -576,7 +889,7 @@ Fixed
- Added missing manpage (doc/qutebrowser.1.asciidoc) to archive.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.2.0[v0.2.0]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.2.0[v0.2.0]
-----------------------------------------------------------------------
Added
@@ -719,7 +1032,7 @@ Fixed
- Add a timeout to pastebin HTTP replies.
- Various other fixes for small/rare bugs.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.1.4[v0.1.4]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.1.4[v0.1.4]
-----------------------------------------------------------------------
Changed
@@ -763,7 +1076,7 @@ Security
* Stop the icon database from being created when private-browsing is set to true.
* Disable insecure SSL ciphers.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.1.3[v0.1.3]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.1.3[v0.1.3]
-----------------------------------------------------------------------
Changed
@@ -797,7 +1110,7 @@ Security
* Fix for HTTP passwords accidentally being written to debug log.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.1.2[v0.1.2]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.1.2[v0.1.2]
-----------------------------------------------------------------------
Changed
@@ -829,7 +1142,7 @@ Fixed
* Fix user-stylesheet setting with an empty value.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.1.1[v0.1.1]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.1.1[v0.1.1]
-----------------------------------------------------------------------
Added
@@ -887,7 +1200,7 @@ Fixed
* Ensure the docs get included in `freeze.py`.
* Fix crash with `:zoom`.
https://github.com/The-Compiler/qutebrowser/releases/tag/v0.1[v0.1]
https://github.com/qutebrowser/qutebrowser/releases/tag/v0.1[v0.1]
-------------------------------------------------------------------
Initial release.

View File

@@ -11,9 +11,9 @@ This document contains guidelines for contributing to qutebrowser, as well as
useful hints when doing so.
If anything mentioned here would prevent you from contributing, please let me
know, and contribute anyways! The guidelines are only meant to make life easier
for me, but if you don't follow anything in here, I won't be mad at you. I will
probably change it for you then, though.
know, and contribute anyways! The guidelines are meant to make life easier for
me, but if you don't follow everything in here, I won't be mad at you. In
fact, I will probably change it for you.
If you have any problems, I'm more than happy to help! You can get help in
several ways:
@@ -34,17 +34,17 @@ this. It might be a good idea to ask on the mailing list or IRC channel to make
sure nobody else started working on the same thing already.
If you want to find something useful to do, check the
https://github.com/The-Compiler/qutebrowser/issues[issue tracker]. Some
https://github.com/qutebrowser/qutebrowser/issues[issue tracker]. Some
pointers:
* https://github.com/The-Compiler/qutebrowser/labels/easy[Issues which should
* https://github.com/qutebrowser/qutebrowser/labels/easy[Issues which should
be easy to solve]
* https://github.com/The-Compiler/qutebrowser/labels/not%20code[Issues which
* https://github.com/qutebrowser/qutebrowser/labels/not%20code[Issues which
require little/no coding]
There are also some things to do if you don't want to write code:
* Help the community, e.g. on the mailinglist and the IRC channel.
* Help the community, e.g., on the mailinglist and the IRC channel.
* Improve the documentation.
* Help on the website and graphics (logo, etc.).
@@ -55,12 +55,12 @@ qutebrowser uses http://git-scm.com/[git] for its development. You can clone
the repo like this:
----
git clone https://github.com/The-Compiler/qutebrowser.git
git clone https://github.com/qutebrowser/qutebrowser.git
----
If you don't know git, a http://git-scm.com/[git cheatsheet] might come in
handy. Of course, if using git is the issue which prevents you from
contributing, feel free to send normal patches instead, e.g. generated via
contributing, feel free to send normal patches instead, e.g., generated via
`diff -Nur`.
Getting patches
@@ -77,7 +77,7 @@ based on your changes like this:
----
git format-patch origin/master <1>
----
<1> Replace `master` by the branch your work was based on, e.g.
<1> Replace `master` by the branch your work was based on, e.g.,
`origin/develop`.
Useful utilities
@@ -89,7 +89,7 @@ Checkers
qutebrowser uses http://tox.readthedocs.org/en/latest/[tox] to run its
unittests and several linters/checkers.
Currently, following tox environments are available:
Currently, the following tox environments are available:
* Tests using https://www.pytest.org[pytest]:
- `py34`: Run pytest for python-3.4.
@@ -117,18 +117,18 @@ Currently, following tox environments are available:
- VCS conflict markers
- common spelling mistakes
The default test suite is run with `tox`, the list of default
environments is obtained with `tox -l` .
The default test suite is run with `tox`; the list of default
environments is obtained with `tox -l`.
Please make sure the checks run without any warnings on your new contributions.
There's of course the possibility of false-positives, and the following
There's always the possibility of false positives; the following
techniques are useful to handle these:
* Use `_foo` for unused parameters, with `foo` being a descriptive name. Using
`_` is discouraged.
* If you think you have a good reason to suppress a message, add the following
comment:
* If you think you have a good reason to suppress a message, then add the
following comment:
+
----
# pylint: disable=message-name
@@ -186,10 +186,10 @@ the output in four different ways:
Debugging
~~~~~~~~~
In the `qutebrowser.utils.debug` module there are some useful functions for
debugging.
There are some useful functions for debugging in the `qutebrowser.utils.debug`
module.
When starting qutebrowser with the `--debug` flag you also get useful debug
When starting qutebrowser with the `--debug` flag, you also get useful debug
logs. You can add +--logfilter _category[,category,...]_+ to restrict logging
to the given categories.
@@ -276,10 +276,10 @@ Hints
Python and Qt objects
~~~~~~~~~~~~~~~~~~~~~
For many tasks, there are solutions in both Qt and the Python standard library
available.
For many tasks, there are solutions available in both Qt and the Python
standard library.
In qutebrowser, the policy is usually using the Python libraries, as they
In qutebrowser, the policy is usually to use the Python libraries, as they
provide exceptions and other benefits.
There are some exceptions to that:
@@ -292,7 +292,7 @@ slots.
When using Qt objects, two issues must be taken care of:
* Methods of Qt objects report their status by using their return values,
* Methods of Qt objects report their status with their return values,
instead of using exceptions.
+
If a function gets or returns a Qt object which has an `.isValid()`
@@ -304,13 +304,12 @@ on all such objects. It will raise
If a function returns something else on error, the return value should
carefully be checked.
* Methods of Qt objects have certain maximum values, based on their
* Methods of Qt objects have certain maximum values based on their
underlying C++ types.
+
When passing a numeric parameter to a Qt function, all numbers should
be range-checked using `qutebrowser.qtutils.check_overflow`, or
passing a value which is too large should be avoided by other means
(e.g. by setting a maximum value for a config object).
To avoid passing too large of a numeric parameter to a Qt function, all
numbers should be range-checked using `qutebrowser.qtutils.check_overflow`,
or by other means (e.g. by setting a maximum value for a config object).
[[object-registry]]
The object registry
@@ -339,8 +338,8 @@ window=_win-id_, tab=_tab-id_])+. The default scope is `global`.
All objects can be printed by starting with the `--debug` flag and using the
`:debug-all-objects` command.
The registry is mainly used for <<commands,command handlers>> but also can be
useful in places where using Qt's
The registry is mainly used for <<commands,command handlers>>, but it can
also be useful in places where using Qt's
http://doc.qt.io/qt-5/signalsandslots.html[signals and slots] mechanism would
be difficult.
@@ -350,7 +349,7 @@ Logging
Logging is used at various places throughout the qutebrowser code. If you add a
new feature, you should also add some strategic debug logging.
Unless other Python projects, qutebrowser doesn't use a logger per file,
Unlike other Python projects, qutebrowser doesn't use a logger per file,
instead it uses custom-named loggers.
The existing loggers are defined in `qutebrowser.utils.log`. If your feature
@@ -413,11 +412,11 @@ selects which object registry (global, per-tab, etc.) to use. See the
<<object-registry,object registry>> section for details.
There are also other arguments to customize the way the command is
registered, see the class documentation for `register` in
registered; see the class documentation for `register` in
`qutebrowser.commands.cmdutils` for details.
The types of the function arguments are inferred based on their default values,
e.g. an argument `foo=True` will be converted to a flag `-f`/`--foo` in
e.g., an argument `foo=True` will be converted to a flag `-f`/`--foo` in
qutebrowser's commandline.
The type can be overridden using Python's
@@ -435,11 +434,11 @@ Possible values:
value.
- A python enum type: All members of the enum are possible values.
- A `typing.Union` of multiple types above: Any of these types are valid
values, e.g. `typing.Union[str, int]`
values, e.g., `typing.Union[str, int]`
You can customize how an argument is handled using the `@cmdutils.argument`
decorator *after* `@cmdutils.register`. This can e.g. be used to customize the
flag an argument should get:
decorator *after* `@cmdutils.register`. This can, for example, be used to
customize the flag an argument should get:
[source,python]
----
@@ -482,13 +481,13 @@ qutebrowser handles two different types of URLs: URLs as a string, and URLs as
the Qt `QUrl` type. As this can get confusing quickly, please follow the
following guidelines:
* Convert a string to a QUrl object as early as possible, i.e. directly after
* Convert a string to a QUrl object as early as possible, i.e., directly after
the user did enter it.
- Use `utils.urlutils.fuzzy_url` if the URL is entered by the user
somewhere.
- Be sure you handle `utils.urlutils.FuzzyError` and display an error
message to the user.
* Convert a `QUrl` object to a string as late as possible, e.g. before
* Convert a `QUrl` object to a string as late as possible, i.e., before
displaying it to the user.
- If you want to display the URL to the user, use `url.toDisplayString()`
so password information is removed.
@@ -514,8 +513,8 @@ This is needed so valgrind handles self-modifying code correctly:
[quote]
____
This option controls Valgrind's detection of self-modifying code. If no
checking is done, if a program executes some code, then overwrites it with new
code, and executes the new code, Valgrind will continue to execute the
checking is done and a program executes some code, overwrites it with new
code, and then executes the new code, Valgrind will continue to execute the
translations it made for the old code. This will likely lead to incorrect
behavior and/or crashes.
@@ -527,6 +526,27 @@ generate code and subsequently overwrite part or all of it. Running with all
will slow Valgrind down noticeably.
____
Setting up a Windows Development Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Install https://www.python.org/downloads/release/python-344/[Python 3.4]
* Install https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/[PyQt 5.5]
* Create a file at `C:\Windows\system32\python3.bat` with the following content:
`@C:\Python34\python %*`
This will make the Python 3.4 interpreter available as `python3`, which is used by various development scripts.
* Install git from the https://git-scm.com/download/win[git-scm downloads page]
Try not to enable `core.autocrlf`, since that will cause `flake8` to complain a lot. Use an editor that can deal with plain line feeds instead.
* Clone your favourite qutebrowser repository.
* To install tox, open an elevated cmd, enter your working directory and run `pip install -rmisc/requirements/requirements-tox.txt`.
Note that the `flake8` tox env might not run due to encoding errors despite having LANG/LC_* set correctly.
Rebuilding the website
~~~~~~~~~~~~~~~~~~~~~~
If you want to rebuild the website, run `./scripts/asciidoc2html.py --website <outputdir>`.
Style conventions
-----------------
@@ -615,16 +635,8 @@ and make sure all bugs marked as resolved are actually fixed.
* Grep for `WORKAROUND` in the code and test if fixed stuff works without the
workaround.
* Check relevant
https://github.com/The-Compiler/qutebrowser/issues?q=is%3Aopen+is%3Aissue+label%3Aqt[qutebrowser
https://github.com/qutebrowser/qutebrowser/issues?q=is%3Aopen+is%3Aissue+label%3Aqt[qutebrowser
bugs] and check if they're fixed.
* As soon as Homebrew updated, update the custom OS X bottle:
- Update https://github.com/The-Compiler/homebrew-qt5-webkit/blob/master/Formula/qt5.rb[qt5.rb]
- `brew install --build-from-source --build-bottle --verbose qt5.rb`
- `brew bottle qt5.rb`
- `brew install --build-from-source --build-bottle --verbose pyqt5`
- `brew bottle pyqt5`
- Upload bottles to github
- Adjust `scripts/dev/ci/travis_install.sh`
New PyQt release
~~~~~~~~~~~~~~~~
@@ -632,11 +644,13 @@ New PyQt release
* See above
* Install new PyQt in Windows VM (32- and 64-bit)
* Download new installer and update PyQt installer path in `ci_install.py`.
* Update `tox.ini`/`.travis.yml`/`.appveyor.yml` to test new versions
qutebrowser release
~~~~~~~~~~~~~~~~~~~
* Make sure there are no unstaged changes and the tests are green.
* Run `x=... y=...` to set the respective shell variables
* Add newest config to `tests/unit/config/old_configs` and update `test_upgrade_version`
- `python -m qutebrowser --basedir conf :quit`
@@ -644,30 +658,20 @@ qutebrowser release
- `rm -r conf`
- commit
* Adjust `__version_info__` in `qutebrowser/__init__.py`.
* Remove *(unreleased)* from changelog.
* Update changelog (remove *(unreleased)*)
* Run tests again
* Run `asciidoc2html.py`.
* Commit
* Create annotated git tag (`git tag -s "v0.X.Y" -m "Release v0.X.Y"`)
* Create annotated git tag (`git tag -s "v0.$x.$y" -m "Release v0.$x.$y"`)
* `git push origin`; `git push origin v0.$x.$y`
* If committing on minor branch, cherry-pick release commit to master.
* `git push origin`; `git push origin v0.X.Y`
* Create release on github
* Mark the milestone at https://github.com/The-Compiler/qutebrowser/milestones
* Mark the milestone at https://github.com/qutebrowser/qutebrowser/milestones
as closed.
* Run `scripts/dev/build_release.py` on Linux to build an sdist
* Upload to PyPI: `twine upload dist/foo{,.asc}`
* Create Windows packages via `C:\Python34_x32\python scripts\dev\build_release.py --asciidoc C:\Python27\python C:\asciidoc-8.6.9\asciidoc.py`
* Upload to github
* Upload to qutebrowser.org with checksum/GPG
- On server: `sudo mkdir -p /srv/http/qutebrowser/releases/v0.X.Y/windows`
- `rsync -avPh dist/ tonks:`
- On server: `sudo mv qutebrowser-0.X.Y.tar.gz* /srv/http/qutebrowser/releases/v0.X.Y`
- Upload windows release:
- `scp bb-win8:proj/qutebrowser/qutebrowser-0.X.Y-windows.zip .`
- `aunpack qutebrowser-0.X.Y-windows.zip`
- `sudo mv qutebrowser-0.X.Y-windows/* /srv/http/qutebrowser/releases/v0.X.Y/windows`
* Linux: Run `python3 scripts/dev/build_release.py --upload v0.$x.$y`
* Windows: Run `C:\Python34_x32\python scripts\dev\build_release.py --asciidoc C:\Python27\python C:\asciidoc-8.6.9\asciidoc.py --upload v0.X.Y` (replace X/Y by hand)
* OS X: Run `python3 scripts/dev/build_release.py --upload v0.X.Y` (replace X/Y by hand)
* On server: Run `python3 scripts/dev/download_release.py v0.X.Y` (replace X/Y by hand)
* Update `qutebrowser-git` PKGBUILD if dependencies/install changed
* Announce to qutebrowser mailinglist
* Announce to qutebrowser and qutebrowser-announce mailinglist

View File

@@ -105,13 +105,25 @@ It also works nicely with rapid hints:
How do I use qutebrowser with mutt?::
Due to a Qt limitation, local files without `.html` extensions are
"downloaded" instead of displayed, see
https://github.com/The-Compiler/qutebrowser/issues/566[#566]. You can work
https://github.com/qutebrowser/qutebrowser/issues/566[#566]. You can work
around this by using this in your `mailcap`:
+
----
text/html; mv %s %s.html && qutebrowser %s.html >/dev/null 2>/dev/null; needsterminal;
----
What is the difference between bookmarks and quickmarks?::
Bookmarks will always use the title of the website as their name, but with quickmarks
you can set your own title.
+
For example, if you bookmark multiple food recipe websites and use `:open`,
you have to type the title or address of the website.
+
When using quickmark, you can give them all names, like
`foodrecipes1`, `foodrecipes2` and so on. When you type
`:open foodrecipes`, you will see a list of all the food recipe sites,
without having to remember the exact website title or address.
== Troubleshooting
Configuration not saved after modifying config.::
@@ -129,7 +141,7 @@ Experiencing freezing on sites like duckduckgo and youtube.::
This issue could be caused by stale plugin files installed by `mozplugger`
if mozplugger was subsequently removed.
Try exiting qutebrowser and removing `~/.mozilla/plugins/mozplugger*.so`.
See https://github.com/The-Compiler/qutebrowser/issues/357[Issue #357]
See https://github.com/qutebrowser/qutebrowser/issues/357[Issue #357]
for more details.
Experiencing segfaults (crashes) on Debian systems.::
@@ -143,7 +155,7 @@ Segfaults on Facebook, Medium, Amazon, ...::
visiting these sites. This is caused by various bugs in Qt which have been
fixed in Qt 5.4. However Debian and Ubuntu are slow to adopt or upgrade
some packages. On Debian Jessie, it's recommended to use the experimental
repos as described in https://github.com/The-Compiler/qutebrowser/blob/master/INSTALL.asciidoc#on-debian--ubuntu[INSTALL].
repos as described in https://github.com/qutebrowser/qutebrowser/blob/master/INSTALL.asciidoc#on-debian--ubuntu[INSTALL].
+
Since Ubuntu Trusty (using Qt 5.2.1),
https://bugreports.qt.io/browse/QTBUG-42417?jql=component%20%3D%20WebKit%20and%20resolution%20%3D%20Done%20and%20fixVersion%20in%20(5.3.0%2C%20%225.3.0%20Alpha%22%2C%20%225.3.0%20Beta1%22%2C%20%225.3.0%20RC1%22%2C%205.3.1%2C%205.3.2%2C%205.4.0%2C%20%225.4.0%20Alpha%22%2C%20%225.4.0%20Beta%22%2C%20%225.4.0%20RC%22)%20and%20priority%20in%20(%22P2%3A%20Important%22%2C%20%22P1%3A%20Critical%22%2C%20%22P0%3A%20Blocker%22)[over
@@ -154,7 +166,7 @@ https://bugreports.qt.io/browse/QTBUG-42417?jql=component%20%3D%20WebKit%20and%2
My issue is not listed.::
If you experience any segfaults or crashes, you can report the issue in
https://github.com/The-Compiler/qutebrowser/issues[the issue tracker] or
https://github.com/qutebrowser/qutebrowser/issues[the issue tracker] or
using the `:report` command.
If you are reporting a segfault, make sure you read the
link:doc/stacktrace.asciidoc[guide] on how to report them with all needed

View File

@@ -21,10 +21,12 @@ Using the packages
Install the dependencies via apt-get:
----
# apt-get install python3-lxml python-tox python3-pyqt5 python3-pyqt5.qtwebkit python3-sip python3-jinja2 python3-pygments python3-yaml
# apt-get install python3-lxml python-tox python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python3-sip python3-jinja2 python3-pygments python3-yaml
----
Get the packages from the https://github.com/The-Compiler/qutebrowser/releases[release page]
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].
Install the packages:
@@ -54,7 +56,7 @@ Then install the packages like this:
----
# apt-get update
# apt-get install -t experimental python3-pyqt5 python3-pyqt5.qtwebkit python3-sip python3-dev
# apt-get install -t experimental python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python3-sip python3-dev
# apt-get install python-tox
----
@@ -72,7 +74,7 @@ For distributions other than Debian or if you prefer to not use the
experimental repo:
----
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python-tox python3-sip python3-dev
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python-tox python3-sip python3-dev
----
To generate the documentation for the `:help` command, when using the git
@@ -185,6 +187,24 @@ Or add the repo manually:
# zypper install qutebrowser
----
On OpenBSD
----------
qutebrowser is in http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/www/qutebrowser/[OpenBSD ports].
Manual install:
----
# cd /usr/ports/www/qutebrowser
# make install
----
Or alternatively if you're using `-current` (or OpenBSD 6.1 once it's been released):
----
# pkg_add qutebrowser
----
On Windows
----------
@@ -194,7 +214,7 @@ Prebuilt binaries
~~~~~~~~~~~~~~~~~
Prebuilt standalone packages and MSI installers
https://github.com/The-Compiler/qutebrowser/releases[are built] for every
https://github.com/qutebrowser/qutebrowser/releases[are built] for every
release.
https://chocolatey.org/packages/qutebrowser[Chocolatey package]
@@ -229,41 +249,44 @@ Then <<tox,install qutebrowser via tox>>.
On OS X
-------
Prebuilt binary
~~~~~~~~~~~~~~~
The easiest way to install qutebrowser on OS X is to use the prebuilt `.app`
files from the
https://github.com/The-Compiler/qutebrowser/releases[release page].
https://github.com/qutebrowser/qutebrowser/releases[release page].
This binary is also available through the
https://caskroom.github.io/[Homebrew Cask] package manager:
----
$ brew cask install qutebrowser
----
Manual Install
~~~~~~~~~~~~~~
Alternatively, you can install the dependencies via a package manager (like
http://brew.sh/[Homebrew] or https://www.macports.org/[MacPorts]) and run
qutebrowser from source.
For Homebrew, a few extra steps are necessary since Homebrew dropped QtWebKit
from Qt 5.6 - however, some users reported this didn't work for them, so using
the `.app` is strongly encouraged.
This installs a Qt 5.5 and symlinks it so PyQt5 will work with it instead of Qt
5.6. This requires that `qt5` is not installed via Homebrew:
==== Homebrew
----
$ brew install python3 d-bus mysql sip xz
$ brew install homebrew/versions/qt55
$ brew install --ignore-dependencies pyqt5
$ ln -s /usr/local/opt/qt55 /usr/local/opt/qt5
$ pip3.5 install qutebrowser
$ brew install qt5
$ pip3 install qutebrowser
----
For MacPorts, run:
Homebrew's builds of Qt and PyQt no longer include QtWebKit - if you need
QtWebKit support, it is necessary to build from source. The build takes several
hours on an average laptop.
----
$ sudo port install python34 py34-jinja2 asciidoc py34-pygments py34-pyqt5
$ sudo pip3.4 install qutebrowser
$ brew install qt5 --with-qtwebkit
$ brew install -s pyqt5
$ pip3 install qutebrowser
----
The preferences for qutebrowser are stored in
`~/Library/Preferences/qutebrowser`, the application data is stored in
`~/Library/Application Support/qutebrowser`.
Packagers
---------
@@ -282,7 +305,7 @@ First of all, clone the repository using http://git-scm.org/[git] and switch
into the repository folder:
----
$ git clone https://github.com/The-Compiler/qutebrowser.git
$ git clone https://github.com/qutebrowser/qutebrowser.git
$ cd qutebrowser
----
@@ -294,6 +317,12 @@ https://docs.python.org/3/library/venv.html[virtual environment]:
$ tox -e mkvenv
----
On Windows, run tox with the 'mkvenv-win' option, however make sure that ONLY Python3 is in your PATH before running tox.
----
$ tox -e mkvenv-win
----
This installs all needed Python dependencies in a `.venv` subfolder. The
system-wide Qt5/PyQt5 installations are symlinked into the virtual environment.

View File

@@ -35,8 +35,8 @@ exclude pytest.ini
exclude qutebrowser.rcc
exclude .coveragerc
exclude .pylintrc
exclude .eslintrc
exclude .eslintignore
exclude qutebrowser/javascript/.eslintrc.yaml
exclude qutebrowser/javascript/.eslintignore
exclude doc/help
exclude .appveyor.yml
exclude .travis.yml

View File

@@ -1,26 +1,26 @@
// If you are reading this in plaintext or on PyPi:
//
// A rendered version is available at:
// https://github.com/The-Compiler/qutebrowser/blob/master/README.asciidoc
// https://github.com/qutebrowser/qutebrowser/blob/master/README.asciidoc
qutebrowser
===========
// QUTE_WEB_HIDE
image:icons/qutebrowser-64x64.png[qutebrowser logo] *A keyboard-driven, vim-like browser based on PyQt5 and QtWebKit.*
image:icons/qutebrowser-64x64.png[qutebrowser logo] *A keyboard-driven, vim-like browser based on PyQt5 and Qt.*
image:https://img.shields.io/pypi/l/qutebrowser.svg?style=flat["license badge",link="https://github.com/The-Compiler/qutebrowser/blob/master/COPYING"]
image:https://img.shields.io/pypi/l/qutebrowser.svg?style=flat["license badge",link="https://github.com/qutebrowser/qutebrowser/blob/master/COPYING"]
image:https://img.shields.io/pypi/v/qutebrowser.svg?style=flat["version badge",link="https://pypi.python.org/pypi/qutebrowser/"]
image:https://requires.io/github/The-Compiler/qutebrowser/requirements.svg?branch=master["requirements badge",link="https://requires.io/github/The-Compiler/qutebrowser/requirements/?branch=master"]
image:https://travis-ci.org/The-Compiler/qutebrowser.svg?branch=master["Build Status", link="https://travis-ci.org/The-Compiler/qutebrowser"]
image:https://ci.appveyor.com/api/projects/status/9gmnuip6i1oq7046?svg=true["AppVeyor build status", link="https://ci.appveyor.com/project/The-Compiler/qutebrowser"]
image:https://codecov.io/github/The-Compiler/qutebrowser/coverage.svg?branch=master["coverage badge",link="https://codecov.io/github/The-Compiler/qutebrowser?branch=master"]
image:https://requires.io/github/qutebrowser/qutebrowser/requirements.svg?branch=master["requirements badge",link="https://requires.io/github/qutebrowser/qutebrowser/requirements/?branch=master"]
image:https://travis-ci.org/qutebrowser/qutebrowser.svg?branch=master["Build Status", link="https://travis-ci.org/qutebrowser/qutebrowser"]
image:https://ci.appveyor.com/api/projects/status/5pyauww2k68bbow2/branch/master?svg=true["AppVeyor build status", link="https://ci.appveyor.com/project/qutebrowser/qutebrowser"]
image:https://codecov.io/github/qutebrowser/qutebrowser/coverage.svg?branch=master["coverage badge",link="https://codecov.io/github/qutebrowser/qutebrowser?branch=master"]
link:http://www.qutebrowser.org[website] | link:http://blog.qutebrowser.org[blog] | link:https://github.com/The-Compiler/qutebrowser/releases[releases]
link:https://www.qutebrowser.org[website] | link:https://blog.qutebrowser.org[blog] | link:https://github.com/qutebrowser/qutebrowser/releases[releases]
// QUTE_WEB_HIDE_END
qutebrowser is a keyboard-focused browser with a minimal GUI. It's based
on Python, PyQt5 and QtWebKit and free software, licensed under the GPL.
on Python and PyQt5 and free software, licensed under the GPL.
It was inspired by other browsers/addons like dwb and Vimperator/Pentadactyl.
@@ -35,7 +35,7 @@ image:doc/img/hints.png["screenshot 4",width=300,link="doc/img/hints.png"]
Downloads
---------
See the https://github.com/The-Compiler/qutebrowser/releases[github releases
See the https://github.com/qutebrowser/qutebrowser/releases[github releases
page] for available downloads (currently a source archive, and standalone
packages as well as MSI installers for Windows).
@@ -48,9 +48,10 @@ Documentation
In addition to the topics mentioned in this README, the following documents are
available:
* A http://qutebrowser.org/img/cheatsheet-big.png[key binding cheatsheet]: +
image:http://qutebrowser.org/img/cheatsheet-small.png["qutebrowser key binding cheatsheet",link="http://qutebrowser.org/img/cheatsheet-big.png"]
* A https://qutebrowser.org/img/cheatsheet-big.png[key binding cheatsheet]: +
image:https://qutebrowser.org/img/cheatsheet-small.png["qutebrowser key binding cheatsheet",link="https://qutebrowser.org/img/cheatsheet-big.png"]
* link:doc/quickstart.asciidoc[Quick start guide]
* A https://www.shortcutfoo.com/app/dojos/qutebrowser[free training course] to remember those key bindings.
* link:FAQ.asciidoc[Frequently asked questions]
* link:CONTRIBUTING.asciidoc[Contributing to qutebrowser]
* link:INSTALL.asciidoc[INSTALL]
@@ -69,6 +70,9 @@ message to the
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[mailinglist] at
mailto:qutebrowser@lists.qutebrowser.org[].
There's also a https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[announce-only mailinglist]
at mailto:qutebrowser-announce@lists.qutebrowser.org[].
Contributions / Bugs
--------------------
@@ -86,7 +90,7 @@ https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[mailinglist] at
mailto:qutebrowser@lists.qutebrowser.org[].
For security bugs, please contact me directly at mail@qutebrowser.org, GPG ID
http://www.the-compiler.org/pubkey.asc[0xFD55A072].
https://www.the-compiler.org/pubkey.asc[0xFD55A072].
Requirements
------------
@@ -95,7 +99,7 @@ The following software and libraries are required to run qutebrowser:
* http://www.python.org/[Python] 3.4 or newer
* http://qt.io/[Qt] 5.2.0 or newer (5.5.1 recommended)
* QtWebKit
* QtWebKit (old or link:https://github.com/annulen/webkit/wiki[reloaded]/NG) or QtWebEngine
* http://www.riverbankcomputing.com/software/pyqt/intro[PyQt] 5.2.0 or newer
(5.5.1 recommended) for Python 3
* https://pypi.python.org/pypi/setuptools/[pkg_resources/setuptools]
@@ -142,47 +146,64 @@ Contributors, sorted by the number of commits in descending order:
* Florian Bruhin
* Daniel Schadt
* Ryan Roden-Corrent
* Jan Verbeek
* Jakub Klinkovský
* Antoni Boucher
* Lamar Pavel
* Marshall Lochbaum
* Bruno Oliveira
* Alexander Cogneau
* Felix Van der Jeugt
* Daniel Karbach
* Martin Tournoij
* Jakub Klinkovský
* Kevin Velghe
* Raphael Pierzina
* Joel Torstensson
* Jan Verbeek
* Tarcisio Fedrizzi
* Patric Schmitz
* Tarcisio Fedrizzi
* Claude
* Corentin Julé
* meles5
* Philipp Hansch
* Imran Sobir
* Panagiotis Ktistakis
* Artur Shaik
* Nathan Isom
* Thorsten Wißmann
* Kevin Velghe
* Austin Anderson
* Fritz Reichwald
* Jimmy
* Marshall Lochbaum
* Niklas Haas
* Maciej Wołczyk
* Spreadyy
* Alexey "Averrin" Nabrodov
* nanjekyejoannah
* avk
* ZDarian
* Milan Svoboda
* John ShaggyTwoDope Jenkins
* Peter Vilim
* Clayton Craft
* Peter Vilim
* knaggita
* Oliver Caldwell
* Julian Weigt
* Tomasz Kramkowski
* Sebastian Frysztak
* Nikolay Amiantov
* Julie Engel
* Jonas Schürmann
* error800
* Michael Hoang
* Liam BEGUIN
* Daniel Fiser
* skinnay
* Zach-Button
* Tomasz Kramkowski
* Samuel Walladge
* Peter Rice
* Ismail S
* Halfwit
* David Vogt
* Claire Cavanaugh
* rikn00
* kanikaa1234
* haitaka
@@ -190,9 +211,12 @@ Contributors, sorted by the number of commits in descending order:
* Michał Góral
* Michael Ilsaas
* Martin Zimmermann
* Fritz Reichwald
* Jussi Timperi
* Cosmin Popescu
* Brian Jackson
* thuck
* sbinix
* rsteube
* neeasade
* jnphilipp
* Tobias Patzl
@@ -200,37 +224,51 @@ Contributors, sorted by the number of commits in descending order:
* Samuel Loury
* Peter Michely
* Panashe M. Fundira
* Lucas Hoffmann
* Link
* Larry Hynes
* Kirill A. Shutemov
* Johannes Altmanninger
* Jeremy Kaplan
* Ismail
* Edgar Hipp
* Daryl Finlay
* pkill9
* arza
* adam
* Samir Benmendil
* Regina Hug
* Mathias Fussenegger
* Marcelo Santos
* Joel Bradshaw
* Jean-Louis Fuchs
* Fritz V155 Reichwald
* Franz Fellner
* Eric Drechsel
* zwarag
* xd1le
* rmortens
* oniondreams
* issue
* haxwithaxe
* evan
* dylan araps
* addictedtoflames
* Xitian9
* Tomas Orsava
* Tom Janson
* Tobias Werth
* Tim Harder
* Thiago Barroso Perrotta
* Sorokin Alexei
* Simon Désaulniers
* Rok Mandeljc
* Noah Huesser
* Moez Bouhlel
* Matthias Lisin
* Marcel Schilling
* Lazlow Carmichael
* Kevin Wang
* Ján Kobezda
* Johannes Martinsson
* Jean-Christophe Petkovich
* Jay Kamat
@@ -239,10 +277,12 @@ Contributors, sorted by the number of commits in descending order:
* Gregor Pohl
* Eivind Uggedal
* Dietrich Daroch
* Derek Sivers
* Daniel Lu
* Arseniy Seroka
* Andy Balaam
* Andreas Fischer
* Akselmo
// QUTE_AUTHORS_END
The following people have contributed graphics:

View File

@@ -1,5 +1,23 @@
// DO NOT EDIT THIS FILE DIRECTLY!
// It is autogenerated from docstrings by running:
// $ python3 scripts/dev/src2asciidoc.py
= Commands
In qutebrowser, all keybindings are mapped to commands.
Some commands are hidden, which means they don't show up in the command
completion when pressing `:`, as they're typically not useful to run by hand.
For command arguments, there are also some variables you can use:
- `{url}` expands to the URL of the current page
- `{url:pretty}` expands to the URL in decoded format
- `{clipboard}` expands to the clipboard contents
- `{primary}` expands to the primary selection contents
It is possible to run or bind multiple commands by separating them with `;;`.
== Normal commands
.Quick reference
[options="header",width="75%",cols="25%,75%"]
@@ -26,26 +44,28 @@
|<<fullscreen,fullscreen>>|Toggle fullscreen mode.
|<<help,help>>|Show help about a command or setting.
|<<hint,hint>>|Start hinting.
|<<history,history>>|Show browsing history.
|<<history-clear,history-clear>>|Clear all browsing history.
|<<home,home>>|Open main startpage in current tab.
|<<insert-text,insert-text>>|Insert text at cursor position.
|<<inspector,inspector>>|Toggle the web inspector.
|<<jseval,jseval>>|Evaluate a JavaScript string.
|<<jump-mark,jump-mark>>|Jump to the mark named by `key`.
|<<later,later>>|Execute a command after some time.
|<<messages,messages>>|Show a log of past messages.
|<<navigate,navigate>>|Open typical prev/next links or navigate using the URL path.
|<<open,open>>|Open a URL in the current/[count]th tab.
|<<paste,paste>>|Open a page from the clipboard.
|<<print,print>>|Print the current/[count]th tab.
|<<quickmark-add,quickmark-add>>|Add a new quickmark.
|<<quickmark-del,quickmark-del>>|Delete a quickmark.
|<<quickmark-load,quickmark-load>>|Load a quickmark.
|<<quickmark-save,quickmark-save>>|Save the current page as a quickmark.
|<<quit,quit>>|Quit qutebrowser.
|<<record-macro,record-macro>>|Start or stop recording a macro.
|<<reload,reload>>|Reload the current/[count]th tab.
|<<repeat,repeat>>|Repeat a given command.
|<<report,report>>|Report a bug in qutebrowser.
|<<restart,restart>>|Restart qutebrowser while keeping existing tabs open.
|<<run-macro,run-macro>>|Run a recorded macro.
|<<save,save>>|Save configs and state.
|<<search,search>>|Search for a text on the current page. With no text, clear results.
|<<session-delete,session-delete>>|Delete a session.
@@ -53,23 +73,22 @@
|<<session-save,session-save>>|Save a session.
|<<set,set>>|Set an option.
|<<set-cmd-text,set-cmd-text>>|Preset the statusbar to some text.
|<<set-mark,set-mark>>|Set a mark at the current scroll position in the current tab.
|<<spawn,spawn>>|Spawn a command in a shell.
|<<stop,stop>>|Stop loading in the current/[count]th tab.
|<<tab-clone,tab-clone>>|Duplicate the current tab.
|<<tab-close,tab-close>>|Close the current/[count]th tab.
|<<tab-detach,tab-detach>>|Detach the current tab to its own window.
|<<tab-focus,tab-focus>>|Select the tab given as argument/[count].
|<<tab-move,tab-move>>|Move the current tab.
|<<tab-move,tab-move>>|Move the current tab according to the argument and [count].
|<<tab-next,tab-next>>|Switch to the next tab, or switch [count] tabs forward.
|<<tab-only,tab-only>>|Close all tabs except for the current one.
|<<tab-prev,tab-prev>>|Switch to the previous tab, or switch [count] tabs back.
|<<unbind,unbind>>|Unbind a keychain.
|<<undo,undo>>|Re-open a closed tab (optionally skipping [count] closed tabs).
|<<view-source,view-source>>|Show the source of the current page.
|<<view-source,view-source>>|Show the source of the current page in a new tab.
|<<window-only,window-only>>|Close all windows except for the current one.
|<<wq,wq>>|Save open pages and quit.
|<<yank,yank>>|Yank the current URL/title to the clipboard or primary selection.
|<<yank-selected,yank-selected>>|Yank the selected text to the clipboard or primary selection.
|<<yank,yank>>|Yank something to the clipboard or primary selection.
|<<zoom,zoom>>|Set the zoom level for the current tab.
|<<zoom-in,zoom-in>>|Increase the zoom level for the current tab.
|<<zoom-out,zoom-out>>|Decrease the zoom level for the current tab.
@@ -78,7 +97,7 @@
=== adblock-update
Update the adblock block lists.
This updates ~/.local/share/qutebrowser/blocked-hosts with downloaded host lists and re-reads ~/.config/qutebrowser/blocked-hosts.
This updates `~/.local/share/qutebrowser/blocked-hosts` with downloaded host lists and re-reads `~/.config/qutebrowser/blocked-hosts`.
[[back]]
=== back
@@ -113,10 +132,11 @@ Bind a key to a command.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
* This command does not replace variables like +\{url\}+.
[[bookmark-add]]
=== bookmark-add
Syntax: +:bookmark-add ['url'] ['title']+
Syntax: +:bookmark-add [*--toggle*] ['url'] ['title']+
Save the current page as a bookmark, or a specific url.
@@ -126,6 +146,10 @@ If no url and title are provided, then save the current page as a bookmark. If a
* +'url'+: url to save as a bookmark. If None, use url of current page.
* +'title'+: title of the new bookmark.
==== optional arguments
* +*-t*+, +*--toggle*+: remove the bookmark instead of raising an error if it already exists.
[[bookmark-del]]
=== bookmark-del
Syntax: +:bookmark-del ['url']+
@@ -141,7 +165,7 @@ Delete a bookmark.
[[bookmark-load]]
=== bookmark-load
Syntax: +:bookmark-load [*--tab*] [*--bg*] [*--window*] 'url'+
Syntax: +:bookmark-load [*--tab*] [*--bg*] [*--window*] [*--delete*] 'url'+
Load a bookmark.
@@ -152,6 +176,7 @@ Load a bookmark.
* +*-t*+, +*--tab*+: Load the bookmark in a new tab.
* +*-b*+, +*--bg*+: Load the bookmark in a new background tab.
* +*-w*+, +*--window*+: Load the bookmark in a new window.
* +*-d*+, +*--delete*+: Whether to delete the bookmark afterwards.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
@@ -212,11 +237,24 @@ The index of the download to delete.
[[download-open]]
=== download-open
Syntax: +:download-open ['cmdline']+
Open the last/[count]th download.
If no specific command is given, this will use the system's default application to open the file.
==== positional arguments
* +'cmdline'+: The command which should be used to open the file. A `{}` is expanded to the temporary file name. If no `{}` is
present, the filename is automatically appended to the
cmdline.
==== count
The index of the download to open.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[download-remove]]
=== download-remove
Syntax: +:download-remove [*--all*]+
@@ -282,8 +320,13 @@ How many pages to go forward.
[[fullscreen]]
=== fullscreen
Syntax: +:fullscreen [*--leave*]+
Toggle fullscreen mode.
==== optional arguments
* +*-l*+, +*--leave*+: Only leave fullscreen if it was entered by the page.
[[help]]
=== help
Syntax: +:help [*--tab*] [*--bg*] [*--window*] ['topic']+
@@ -304,12 +347,13 @@ Show help about a command or setting.
[[hint]]
=== hint
Syntax: +:hint [*--rapid*] ['group'] ['target'] ['args' ['args' ...]]+
Syntax: +:hint [*--rapid*] [*--mode* 'mode'] [*--add-history*]
['group'] ['target'] ['args' ['args' ...]]+
Start hinting.
==== positional arguments
* +'group'+: The hinting mode to use.
* +'group'+: The element types to hint.
- `all`: All clickable elements.
- `links`: Only links.
@@ -360,20 +404,59 @@ Start hinting.
* +*-r*+, +*--rapid*+: Whether to do rapid hinting. This is only possible with targets `tab` (with background-tabs=true), `tab-bg`,
`window`, `run`, `hover`, `userscript` and `spawn`.
* +*-m*+, +*--mode*+: The hinting mode to use.
- `number`: Use numeric hints.
- `letter`: Use the chars in the hints->chars settings.
- `word`: Use hint words based on the html elements and the
extra words.
* +*-a*+, +*--add-history*+: Whether to add the spawned or yanked link to the browsing history.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[history]]
=== history
Syntax: +:history [*--tab*] [*--bg*] [*--window*]+
Show browsing history.
==== optional arguments
* +*-t*+, +*--tab*+: Open in a new tab.
* +*-b*+, +*--bg*+: Open in a background tab.
* +*-w*+, +*--window*+: Open in a new window.
[[history-clear]]
=== history-clear
Syntax: +:history-clear [*--force*]+
Clear all browsing history.
Note this only clears the global history (e.g. `~/.local/share/qutebrowser/history` on Linux) but not cookies, the back/forward history of a tab, cache or other persistent data.
==== optional arguments
* +*-f*+, +*--force*+: Don't ask for confirmation.
[[home]]
=== home
Open main startpage in current tab.
[[insert-text]]
=== insert-text
Syntax: +:insert-text 'text'+
Insert text at cursor position.
==== positional arguments
* +'text'+: The text to insert.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[inspector]]
=== inspector
Toggle the web inspector.
@@ -382,29 +465,23 @@ Note: Due a bug in Qt, the inspector will show incorrect request headers in the
[[jseval]]
=== jseval
Syntax: +:jseval [*--quiet*] 'js-code'+
Syntax: +:jseval [*--file*] [*--quiet*] [*--world* 'world'] 'js-code'+
Evaluate a JavaScript string.
==== positional arguments
* +'js-code'+: The string to evaluate.
* +'js-code'+: The string/file to evaluate.
==== optional arguments
* +*-f*+, +*--file*+: Interpret js-code as a path to a file.
* +*-q*+, +*--quiet*+: Don't show resulting JS object.
* +*-w*+, +*--world*+: Ignored on QtWebKit. On QtWebEngine, a world ID or name to run the snippet in.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
[[jump-mark]]
=== jump-mark
Syntax: +:jump-mark 'key'+
Jump to the mark named by `key`.
==== positional arguments
* +'key'+: mark identifier; capital indicates a global mark
[[later]]
=== later
Syntax: +:later 'ms' 'command'+
@@ -418,6 +495,7 @@ Execute a command after some time.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
* This command does not replace variables like +\{url\}+.
[[messages]]
=== messages
@@ -460,16 +538,24 @@ This tries to automatically click on typical _Previous Page_ or _Next Page_ link
* +*-b*+, +*--bg*+: Open in a background tab.
* +*-w*+, +*--window*+: Open in a new window.
==== count
For `increment` and `decrement`, the number to change the URL by. For `up`, the number of levels to go up in the URL.
[[open]]
=== open
Syntax: +:open [*--bg*] [*--tab*] [*--window*] ['url']+
Syntax: +:open [*--implicit*] [*--bg*] [*--tab*] [*--window*] ['url']+
Open a URL in the current/[count]th tab.
If the URL contains newlines, each line gets opened in its own tab.
==== positional arguments
* +'url'+: The URL to open.
==== optional arguments
* +*-i*+, +*--implicit*+: If opening a new tab, treat the tab as implicit (like clicking on a link).
* +*-b*+, +*--bg*+: Open in a new background tab.
* +*-t*+, +*--tab*+: Open in a new tab.
* +*-w*+, +*--window*+: Open in a new window.
@@ -480,20 +566,6 @@ The tab index to open the URL in.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[paste]]
=== paste
Syntax: +:paste [*--sel*] [*--tab*] [*--bg*] [*--window*]+
Open a page from the clipboard.
If the pasted text contains newlines, each line gets opened in its own tab.
==== optional arguments
* +*-s*+, +*--sel*+: Use the primary selection instead of the clipboard.
* +*-t*+, +*--tab*+: Open in a new tab.
* +*-b*+, +*--bg*+: Open in a background tab.
* +*-w*+, +*--window*+: Open in new window.
[[print]]
=== print
Syntax: +:print [*--preview*] [*--pdf* 'file']+
@@ -558,6 +630,15 @@ Save the current page as a quickmark.
=== quit
Quit qutebrowser.
[[record-macro]]
=== record-macro
Syntax: +:record-macro ['register']+
Start or stop recording a macro.
==== positional arguments
* +'register'+: Which register to store the macro in.
[[reload]]
=== reload
Syntax: +:reload [*--force*]+
@@ -583,6 +664,7 @@ Repeat a given command.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
* This command does not replace variables like +\{url\}+.
[[report]]
=== report
@@ -592,6 +674,18 @@ Report a bug in qutebrowser.
=== restart
Restart qutebrowser while keeping existing tabs open.
[[run-macro]]
=== run-macro
Syntax: +:run-macro ['register']+
Run a recorded macro.
==== positional arguments
* +'register'+: Which macro to run.
==== count
How many times to run the macro.
[[save]]
=== save
Syntax: +:save ['what' ['what' ...]]+
@@ -647,7 +741,8 @@ Load a session.
[[session-save]]
=== session-save
Syntax: +:session-save [*--current*] [*--quiet*] [*--force*] ['name']+
Syntax: +:session-save [*--current*] [*--quiet*] [*--force*] [*--only-active-window*]
['name']+
Save a session.
@@ -659,10 +754,11 @@ Save a session.
* +*-c*+, +*--current*+: Save the current session instead of the default.
* +*-q*+, +*--quiet*+: Don't show confirmation message.
* +*-f*+, +*--force*+: Force saving internal sessions (starting with an underline).
* +*-o*+, +*--only-active-window*+: Saves only tabs of the currently active window.
[[set]]
=== set
Syntax: +:set [*--temp*] [*--print*] ['section'] ['option'] ['value']+
Syntax: +:set [*--temp*] [*--print*] ['section'] ['option'] ['values' ['values' ...]]+
Set an option.
@@ -671,7 +767,7 @@ If the option name ends with '?', the value of the option is shown instead. If t
==== positional arguments
* +'section'+: The section where the option is in.
* +'option'+: The name of the option.
* +'value'+: The value to set.
* +'values'+: The value to set, or the values to cycle through.
==== optional arguments
* +*-t*+, +*--temp*+: Set value temporarily.
@@ -683,8 +779,6 @@ Syntax: +:set-cmd-text [*--space*] [*--append*] 'text'+
Preset the statusbar to some text.
You can use the `{url}` and `{url:pretty}` variables here which will get replaced by the encoded/decoded URL.
==== positional arguments
* +'text'+: The commandline to set.
@@ -695,23 +789,12 @@ You can use the `{url}` and `{url:pretty}` variables here which will get replace
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[set-mark]]
=== set-mark
Syntax: +:set-mark 'key'+
Set a mark at the current scroll position in the current tab.
==== positional arguments
* +'key'+: mark identifier; capital indicates a global mark
[[spawn]]
=== spawn
Syntax: +:spawn [*--userscript*] [*--verbose*] [*--detach*] 'cmdline'+
Spawn a command in a shell.
Note the `{url}` and `{url:pretty}` variables might be useful here. `{url}` gets replaced by the URL in fully encoded format and `{url:pretty}` uses a "pretty form" with most percent-encoded characters decoded.
==== positional arguments
* +'cmdline'+: The commandline to execute.
@@ -747,13 +830,13 @@ Duplicate the current tab.
[[tab-close]]
=== tab-close
Syntax: +:tab-close [*--left*] [*--right*] [*--opposite*]+
Syntax: +:tab-close [*--prev*] [*--next*] [*--opposite*]+
Close the current/[count]th tab.
==== optional arguments
* +*-l*+, +*--left*+: Force selecting the tab to the left of the current tab.
* +*-r*+, +*--right*+: Force selecting the tab to the right of the current tab.
* +*-p*+, +*--prev*+: Force selecting the tab before the current tab.
* +*-n*+, +*--next*+: Force selecting the tab after the current tab.
* +*-o*+, +*--opposite*+: Force selecting the tab in the opposite direction of what's configured in 'tabs->select-on-remove'.
@@ -770,11 +853,12 @@ Syntax: +:tab-focus ['index']+
Select the tab given as argument/[count].
If neither count nor index are given, it behaves like tab-next.
If neither count nor index are given, it behaves like tab-next. If both are given, use count.
==== positional arguments
* +'index'+: The tab index to focus, starting with 1. The special value `last` focuses the last focused tab. Negative indexes
counts from the end, such that -1 is the last tab.
* +'index'+: The tab index to focus, starting with 1. The special value `last` focuses the last focused tab (regardless of count).
Negative indices count from the end, such that -1 is the
last tab.
==== count
@@ -782,16 +866,20 @@ The tab index to focus, starting with 1.
[[tab-move]]
=== tab-move
Syntax: +:tab-move ['direction']+
Syntax: +:tab-move ['index']+
Move the current tab.
Move the current tab according to the argument and [count].
If neither is given, move it to the first position.
==== positional arguments
* +'direction'+: `+` or `-` for relative moving, not given for absolute moving.
* +'index'+: `+` or `-` to move relative to the current tab by count, or a default of 1 space.
A tab index to move to that index.
==== count
If moving absolutely: New position (default: 0) If moving relatively: Offset.
If moving relatively: Offset. If moving absolutely: New position (default: 0). This
overrides the index argument, if given.
[[tab-next]]
@@ -803,13 +891,13 @@ How many tabs to switch forward.
[[tab-only]]
=== tab-only
Syntax: +:tab-only [*--left*] [*--right*]+
Syntax: +:tab-only [*--prev*] [*--next*]+
Close all tabs except for the current one.
==== optional arguments
* +*-l*+, +*--left*+: Keep tabs to the left of the current.
* +*-r*+, +*--right*+: Keep tabs to the right of the current.
* +*-p*+, +*--prev*+: Keep tabs before the current.
* +*-n*+, +*--next*+: Keep tabs after the current.
[[tab-prev]]
=== tab-prev
@@ -835,7 +923,11 @@ Re-open a closed tab (optionally skipping [count] closed tabs).
[[view-source]]
=== view-source
Show the source of the current page.
Show the source of the current page in a new tab.
[[window-only]]
=== window-only
Close all windows except for the current one.
[[wq]]
=== wq
@@ -848,25 +940,25 @@ Save open pages and quit.
[[yank]]
=== yank
Syntax: +:yank [*--title*] [*--sel*] [*--domain*] [*--pretty*]+
Syntax: +:yank [*--sel*] [*--keep*] ['what']+
Yank the current URL/title to the clipboard or primary selection.
Yank something to the clipboard or primary selection.
==== optional arguments
* +*-t*+, +*--title*+: Yank the title instead of the URL.
* +*-s*+, +*--sel*+: Use the primary selection instead of the clipboard.
* +*-d*+, +*--domain*+: Yank only the scheme, domain, and port number.
* +*-p*+, +*--pretty*+: Yank the URL in pretty decoded form.
==== positional arguments
* +'what'+: What to yank.
- `url`: The current URL.
- `pretty-url`: The URL in pretty decoded form.
- `title`: The current page's title.
- `domain`: The current scheme, domain, and port number.
- `selection`: The selection under the cursor.
[[yank-selected]]
=== yank-selected
Syntax: +:yank-selected [*--sel*] [*--keep*]+
Yank the selected text to the clipboard or primary selection.
==== optional arguments
* +*-s*+, +*--sel*+: Use the primary selection instead of the clipboard.
* +*-k*+, +*--keep*+: If given, stay in visual mode after yanking.
* +*-k*+, +*--keep*+: Stay in visual mode after yanking the selection.
[[zoom]]
=== zoom
@@ -874,7 +966,7 @@ Syntax: +:zoom ['zoom']+
Set the zoom level for the current tab.
The zoom can be given as argument or as [count]. If neither of both is given, the zoom is set to the default zoom.
The zoom can be given as argument or as [count]. If neither is given, the zoom is set to the default zoom. If both are given, use [count].
==== positional arguments
* +'zoom'+: The zoom percentage to set.
@@ -903,16 +995,17 @@ How many steps to zoom out.
|==============
|Command|Description
|<<clear-keychain,clear-keychain>>|Clear the currently entered key chain.
|<<click-element,click-element>>|Click the element matching the given filter.
|<<command-accept,command-accept>>|Execute the command currently in the commandline.
|<<command-history-next,command-history-next>>|Go forward in the commandline history.
|<<command-history-prev,command-history-prev>>|Go back in the commandline history.
|<<completion-item-del,completion-item-del>>|Delete the current completion item.
|<<completion-item-next,completion-item-next>>|Select the next completion item.
|<<completion-item-prev,completion-item-prev>>|Select the previous completion item.
|<<completion-item-focus,completion-item-focus>>|Shift the focus of the completion menu to another item.
|<<drop-selection,drop-selection>>|Drop selection and keep selection mode enabled.
|<<enter-mode,enter-mode>>|Enter a key mode.
|<<follow-hint,follow-hint>>|Follow a hint.
|<<follow-selected,follow-selected>>|Follow the selected text.
|<<jump-mark,jump-mark>>|Jump to the mark named by `key`.
|<<leave-mode,leave-mode>>|Leave the mode we're currently in.
|<<message-error,message-error>>|Show an error message in the statusbar.
|<<message-info,message-info>>|Show an info message in the statusbar.
@@ -933,14 +1026,13 @@ How many steps to zoom out.
|<<move-to-start-of-next-block,move-to-start-of-next-block>>|Move the cursor or selection to the start of next block.
|<<move-to-start-of-prev-block,move-to-start-of-prev-block>>|Move the cursor or selection to the start of previous block.
|<<open-editor,open-editor>>|Open an external editor with the currently selected form field.
|<<paste-primary,paste-primary>>|Paste the primary selection at cursor position.
|<<prompt-accept,prompt-accept>>|Accept the current prompt.
|<<prompt-no,prompt-no>>|Answer no to a yes/no prompt.
|<<prompt-item-focus,prompt-item-focus>>|Shift the focus of the prompt file completion menu to another item.
|<<prompt-open-download,prompt-open-download>>|Immediately open a download.
|<<prompt-yes,prompt-yes>>|Answer yes to a yes/no prompt.
|<<repeat-command,repeat-command>>|Repeat the last executed command.
|<<rl-backward-char,rl-backward-char>>|Move back a character.
|<<rl-backward-delete-char,rl-backward-delete-char>>|Delete the character before the cursor.
|<<rl-backward-kill-word,rl-backward-kill-word>>|Remove chars from the cursor to the beginning of the word.
|<<rl-backward-word,rl-backward-word>>|Move back to the start of the current or previous word.
|<<rl-beginning-of-line,rl-beginning-of-line>>|Move to the start of the line.
|<<rl-delete-char,rl-delete-char>>|Delete the character after the cursor.
@@ -949,21 +1041,41 @@ How many steps to zoom out.
|<<rl-forward-word,rl-forward-word>>|Move forward to the end of the next word.
|<<rl-kill-line,rl-kill-line>>|Remove chars from the cursor to the end of the line.
|<<rl-kill-word,rl-kill-word>>|Remove chars from the cursor to the end of the current word.
|<<rl-unix-filename-rubout,rl-unix-filename-rubout>>|Remove chars from the cursor to the previous path separator.
|<<rl-unix-line-discard,rl-unix-line-discard>>|Remove chars backward from the cursor to the beginning of the line.
|<<rl-unix-word-rubout,rl-unix-word-rubout>>|Remove chars from the cursor to the beginning of the word.
|<<rl-yank,rl-yank>>|Paste the most recently deleted text.
|<<run-with-count,run-with-count>>|Run a command with the given count.
|<<scroll,scroll>>|Scroll the current tab in the given direction.
|<<scroll-page,scroll-page>>|Scroll the frame page-wise.
|<<scroll-perc,scroll-perc>>|Scroll to a specific percentage of the page.
|<<scroll-px,scroll-px>>|Scroll the current tab by 'count * dx/dy' pixels.
|<<search-next,search-next>>|Continue the search to the ([count]th) next term.
|<<search-prev,search-prev>>|Continue the search to the ([count]th) previous term.
|<<set-mark,set-mark>>|Set a mark at the current scroll position in the current tab.
|<<toggle-selection,toggle-selection>>|Toggle caret selection mode.
|==============
[[clear-keychain]]
=== clear-keychain
Clear the currently entered key chain.
[[click-element]]
=== click-element
Syntax: +:click-element [*--target* 'target'] [*--force-event*] 'filter' 'value'+
Click the element matching the given filter.
The given filter needs to result in exactly one element, otherwise, an error is shown.
==== positional arguments
* +'filter'+: How to filter the elements. id: Get an element based on its ID.
* +'value'+: The value to filter for.
==== optional arguments
* +*-t*+, +*--target*+: How to open the clicked element (normal/tab/tab-bg/window).
* +*-f*+, +*--force-event*+: Force generating a fake click event.
[[command-accept]]
=== command-accept
Execute the command currently in the commandline.
@@ -980,13 +1092,14 @@ Go back in the commandline history.
=== completion-item-del
Delete the current completion item.
[[completion-item-next]]
=== completion-item-next
Select the next completion item.
[[completion-item-focus]]
=== completion-item-focus
Syntax: +:completion-item-focus 'which'+
[[completion-item-prev]]
=== completion-item-prev
Select the previous completion item.
Shift the focus of the completion menu to another item.
==== positional arguments
* +'which'+: 'next', 'prev', 'next-category', or 'prev-category'.
[[drop-selection]]
=== drop-selection
@@ -1019,6 +1132,15 @@ Follow the selected text.
==== optional arguments
* +*-t*+, +*--tab*+: Load the selected link in a new tab.
[[jump-mark]]
=== jump-mark
Syntax: +:jump-mark 'key'+
Jump to the mark named by `key`.
==== positional arguments
* +'key'+: mark identifier; capital indicates a global mark
[[leave-mode]]
=== leave-mode
Leave the mode we're currently in.
@@ -1041,6 +1163,9 @@ Show an info message in the statusbar.
==== positional arguments
* +'text'+: The text to show.
==== count
How many times to show the message
[[message-warning]]
=== message-warning
Syntax: +:message-warning 'text'+
@@ -1149,25 +1274,41 @@ Open an external editor with the currently selected form field.
The editor which should be launched can be configured via the `general -> editor` config option.
[[paste-primary]]
=== paste-primary
Paste the primary selection at cursor position.
[[prompt-accept]]
=== prompt-accept
Syntax: +:prompt-accept ['value']+
Accept the current prompt.
[[prompt-no]]
=== prompt-no
Answer no to a yes/no prompt.
==== positional arguments
* +'value'+: If given, uses this value instead of the entered one. For boolean prompts, "yes"/"no" are accepted as value.
[[prompt-item-focus]]
=== prompt-item-focus
Syntax: +:prompt-item-focus 'which'+
Shift the focus of the prompt file completion menu to another item.
==== positional arguments
* +'which'+: 'next', 'prev'
[[prompt-open-download]]
=== prompt-open-download
Syntax: +:prompt-open-download ['cmdline']+
Immediately open a download.
[[prompt-yes]]
=== prompt-yes
Answer yes to a yes/no prompt.
If no specific command is given, this will use the system's default application to open the file.
==== positional arguments
* +'cmdline'+: The command which should be used to open the file. A `{}` is expanded to the temporary file name. If no `{}` is
present, the filename is automatically appended to the
cmdline.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
[[repeat-command]]
=== repeat-command
@@ -1188,6 +1329,12 @@ Delete the character before the cursor.
This acts like readline's backward-delete-char.
[[rl-backward-kill-word]]
=== rl-backward-kill-word
Remove chars from the cursor to the beginning of the word.
This acts like readline's backward-kill-word. Any non-alphanumeric character is considered a word delimiter.
[[rl-backward-word]]
=== rl-backward-word
Move back to the start of the current or previous word.
@@ -1236,6 +1383,12 @@ Remove chars from the cursor to the end of the current word.
This acts like readline's kill-word.
[[rl-unix-filename-rubout]]
=== rl-unix-filename-rubout
Remove chars from the cursor to the previous path separator.
This acts like readline's unix-filename-rubout.
[[rl-unix-line-discard]]
=== rl-unix-line-discard
Remove chars backward from the cursor to the beginning of the line.
@@ -1246,7 +1399,7 @@ This acts like readline's unix-line-discard.
=== rl-unix-word-rubout
Remove chars from the cursor to the beginning of the word.
This acts like readline's unix-word-rubout.
This acts like readline's unix-word-rubout. Whitespace is used as a word delimiter.
[[rl-yank]]
=== rl-yank
@@ -1254,6 +1407,26 @@ Paste the most recently deleted text.
This acts like readline's yank.
[[run-with-count]]
=== run-with-count
Syntax: +:run-with-count 'count-arg' 'command'+
Run a command with the given count.
If run_with_count itself is run with a count, it multiplies count_arg.
==== positional arguments
* +'count-arg'+: The count to pass to the command.
* +'command'+: The command to run, with optional args.
==== count
The count that run_with_count itself received.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
* This command does not replace variables like +\{url\}+.
[[scroll]]
=== scroll
Syntax: +:scroll 'direction'+
@@ -1330,6 +1503,15 @@ Continue the search to the ([count]th) previous term.
==== count
How many elements to ignore.
[[set-mark]]
=== set-mark
Syntax: +:set-mark 'key'+
Set a mark at the current scroll position in the current tab.
==== positional arguments
* +'key'+: mark identifier; capital indicates a global mark
[[toggle-selection]]
=== toggle-selection
Toggle caret selection mode.
@@ -1348,6 +1530,9 @@ These commands are mainly intended for debugging. They are hidden if qutebrowser
|<<debug-console,debug-console>>|Show the debugging console.
|<<debug-crash,debug-crash>>|Crash for debugging purposes.
|<<debug-dump-page,debug-dump-page>>|Dump the current page's content to a file.
|<<debug-log-capacity,debug-log-capacity>>|Change the number of log lines to be stored in RAM.
|<<debug-log-filter,debug-log-filter>>|Change the log filter for console logging.
|<<debug-log-level,debug-log-level>>|Change the log level for console logging.
|<<debug-pyeval,debug-pyeval>>|Evaluate a python string and display the results as a web page.
|<<debug-set-fake-clipboard,debug-set-fake-clipboard>>|Put data into the fake clipboard and enable logging, used for tests.
|<<debug-trace,debug-trace>>|Trace executed code via hunter.
@@ -1390,6 +1575,33 @@ Dump the current page's content to a file.
==== optional arguments
* +*-p*+, +*--plain*+: Write plain text instead of HTML.
[[debug-log-capacity]]
=== debug-log-capacity
Syntax: +:debug-log-capacity 'capacity'+
Change the number of log lines to be stored in RAM.
==== positional arguments
* +'capacity'+: Number of lines for the log.
[[debug-log-filter]]
=== debug-log-filter
Syntax: +:debug-log-filter 'filters'+
Change the log filter for console logging.
==== positional arguments
* +'filters'+: A comma separated list of logger names.
[[debug-log-level]]
=== debug-log-level
Syntax: +:debug-log-level 'level'+
Change the log level for console logging.
==== positional arguments
* +'level'+: The log level to set.
[[debug-pyeval]]
=== debug-pyeval
Syntax: +:debug-pyeval [*--quiet*] 's'+

View File

@@ -6,13 +6,13 @@ Documentation
The following help pages are currently available:
* link:quickstart.html[Quick start guide]
* link:FAQ.html[Frequently asked questions]
* link:CHANGELOG.html[Change Log]
* link:../quickstart.html[Quick start guide]
* link:../../FAQ.html[Frequently asked questions]
* link:../../CHANGELOG.html[Change Log]
* link:commands.html[Documentation of commands]
* link:settings.html[Documentation of settings]
* link:userscripts.html[How to write userscripts]
* link:CONTRIBUTING.html[Contributing to qutebrowser]
* link:../userscripts.html[How to write userscripts]
* link:../../CONTRIBUTING.html[Contributing to qutebrowser]
Getting help
------------

View File

@@ -1,3 +1,7 @@
// DO NOT EDIT THIS FILE DIRECTLY!
// It is autogenerated from docstrings by running:
// $ python3 scripts/dev/src2asciidoc.py
= Settings
.Quick reference for section ``general''
@@ -6,6 +10,8 @@
|Setting|Description
|<<general-ignore-case,ignore-case>>|Whether to find text on a page case-insensitively.
|<<general-startpage,startpage>>|The default page(s) to open at the start, separated by commas.
|<<general-yank-ignored-url-parameters,yank-ignored-url-parameters>>|The URL parameters to strip with :yank url, separated by commas.
|<<general-default-open-dispatcher,default-open-dispatcher>>|The default program used to open downloads. Set to an empty string to use the default internal handler.
|<<general-default-page,default-page>>|The page to open if :open -t/-b/-w is used without URL. Use `about:blank` for a blank page.
|<<general-auto-search,auto-search>>|Whether to start a search when something else than a URL is entered.
|<<general-auto-save-config,auto-save-config>>|Whether to save the config automatically on quit.
@@ -16,9 +22,10 @@
|<<general-developer-extras,developer-extras>>|Enable extra tools for Web developers.
|<<general-print-element-backgrounds,print-element-backgrounds>>|Whether the background color and images are also drawn when the page is printed.
|<<general-xss-auditing,xss-auditing>>|Whether load requests should be monitored for cross-site scripting attempts.
|<<general-site-specific-quirks,site-specific-quirks>>|Enable workarounds for broken sites.
|<<general-site-specific-quirks,site-specific-quirks>>|Enable QtWebKit workarounds for broken sites.
|<<general-default-encoding,default-encoding>>|Default encoding to use for websites.
|<<general-new-instance-open-target,new-instance-open-target>>|How to open links in an existing instance if a new one is launched.
|<<general-new-instance-open-target.window,new-instance-open-target.window>>|Which window to choose when opening links as new tabs.
|<<general-log-javascript-console,log-javascript-console>>|How to log javascript console messages.
|<<general-save-session,save-session>>|Whether to always save the open pages.
|<<general-session-default-name,session-default-name>>|The name of the session to save by default, or empty for the last loaded session.
@@ -38,17 +45,19 @@
|<<ui-confirm-quit,confirm-quit>>|Whether to confirm quitting the application.
|<<ui-zoom-text-only,zoom-text-only>>|Whether the zoom factor on a frame applies only to the text or to all content.
|<<ui-frame-flattening,frame-flattening>>|Whether to expand each subframe to its contents.
|<<ui-user-stylesheet,user-stylesheet>>|User stylesheet to use (absolute filename, filename relative to the config directory or CSS string). Will expand environment variables.
|<<ui-user-stylesheet,user-stylesheet>>|User stylesheet to use (absolute filename or filename relative to the config directory). Will expand environment variables.
|<<ui-hide-scrollbar,hide-scrollbar>>|Hide the main scrollbar.
|<<ui-css-media-type,css-media-type>>|Set the CSS media type.
|<<ui-smooth-scrolling,smooth-scrolling>>|Whether to enable smooth scrolling for webpages.
|<<ui-remove-finished-downloads,remove-finished-downloads>>|Number of milliseconds to wait before removing finished downloads. Will not be removed if value is -1.
|<<ui-hide-statusbar,hide-statusbar>>|Whether to hide the statusbar unless a message is shown.
|<<ui-statusbar-padding,statusbar-padding>>|Padding for statusbar (top, bottom, left, right).
|<<ui-window-title-format,window-title-format>>|The format to use for the window title. The following placeholders are defined:
|<<ui-hide-mouse-cursor,hide-mouse-cursor>>|Whether to hide the mouse cursor.
|<<ui-modal-js-dialog,modal-js-dialog>>|Use standard JavaScript modal dialog for alert() and confirm()
|<<ui-hide-wayland-decoration,hide-wayland-decoration>>|Hide the window decoration when using wayland (requires restart)
|<<ui-keyhint-blacklist,keyhint-blacklist>>|Keychains that shouldn't be shown in the keyhint dialog
|<<ui-prompt-radius,prompt-radius>>|The rounding radius for the edges of prompts.
|<<ui-prompt-filebrowser,prompt-filebrowser>>|Show a filebrowser in upload/download prompts.
|==============
.Quick reference for section ``network''
@@ -64,16 +73,16 @@
|<<network-ssl-strict,ssl-strict>>|Whether to validate SSL handshakes.
|<<network-dns-prefetch,dns-prefetch>>|Whether to try to pre-fetch DNS entries to speed up browsing.
|<<network-custom-headers,custom-headers>>|Set custom headers for qutebrowser HTTP requests.
|<<network-netrc-file,netrc-file>>|Set location of a netrc-file for HTTP authentication. If empty, ~/.netrc is used.
|==============
.Quick reference for section ``completion''
[options="header",width="75%",cols="25%,75%"]
|==============
|Setting|Description
|<<completion-auto-open,auto-open>>|Automatically open completion when typing.
|<<completion-show,show>>|When to show the autocompletion window.
|<<completion-download-path-suggestion,download-path-suggestion>>|What to display in the download filename input.
|<<completion-timestamp-format,timestamp-format>>|How to format timestamps (e.g. for history)
|<<completion-show,show>>|Whether to show the autocompletion window.
|<<completion-height,height>>|The height of the completion, in px or as percentage of the window.
|<<completion-cmd-history-max-items,cmd-history-max-items>>|How many commands to save in the command history.
|<<completion-web-history-max-items,web-history-max-items>>|How many URLs to show in the web history.
@@ -87,8 +96,8 @@
[options="header",width="75%",cols="25%,75%"]
|==============
|Setting|Description
|<<input-timeout,timeout>>|Timeout for ambiguous key bindings.
|<<input-partial-timeout,partial-timeout>>|Timeout for partially typed key bindings.
|<<input-timeout,timeout>>|Timeout (in milliseconds) for ambiguous key bindings.
|<<input-partial-timeout,partial-timeout>>|Timeout (in milliseconds) for partially typed key bindings.
|<<input-insert-mode-on-plugins,insert-mode-on-plugins>>|Whether to switch to insert mode when clicking flash and other plugins.
|<<input-auto-leave-insert-mode,auto-leave-insert-mode>>|Whether to leave insert mode if a non-editable element is clicked.
|<<input-auto-insert-mode,auto-insert-mode>>|Whether to automatically enter insert mode if an editable element is focused after page load.
@@ -139,7 +148,7 @@
|<<storage-offline-storage-database,offline-storage-database>>|Whether support for the HTML 5 offline storage feature is enabled.
|<<storage-offline-web-application-storage,offline-web-application-storage>>|Whether support for the HTML 5 web application cache feature is enabled.
|<<storage-local-storage,local-storage>>|Whether support for the HTML 5 local storage feature is enabled.
|<<storage-cache-size,cache-size>>|Size of the HTTP network cache.
|<<storage-cache-size,cache-size>>|Size of the HTTP network cache. Empty to use the default value.
|==============
.Quick reference for section ``content''
@@ -154,7 +163,8 @@
|<<content-hyperlink-auditing,hyperlink-auditing>>|Enable or disable hyperlink auditing (<a ping>).
|<<content-geolocation,geolocation>>|Allow websites to request geolocations.
|<<content-notifications,notifications>>|Allow websites to show notifications.
|<<content-javascript-can-open-windows,javascript-can-open-windows>>|Whether JavaScript programs can open new windows.
|<<content-media-capture,media-capture>>|Allow websites to record audio/video.
|<<content-javascript-can-open-windows-automatically,javascript-can-open-windows-automatically>>|Whether JavaScript programs can open new windows without user interaction.
|<<content-javascript-can-close-windows,javascript-can-close-windows>>|Whether JavaScript programs can close windows.
|<<content-javascript-can-access-clipboard,javascript-can-access-clipboard>>|Whether JavaScript programs can read or write to the clipboard.
|<<content-ignore-javascript-prompt,ignore-javascript-prompt>>|Whether all javascript prompts should be ignored.
@@ -162,7 +172,7 @@
|<<content-local-content-can-access-remote-urls,local-content-can-access-remote-urls>>|Whether locally loaded documents are allowed to access remote urls.
|<<content-local-content-can-access-file-urls,local-content-can-access-file-urls>>|Whether locally loaded documents are allowed to access other local urls.
|<<content-cookies-accept,cookies-accept>>|Control which cookies to accept.
|<<content-cookies-store,cookies-store>>|Whether to store cookies.
|<<content-cookies-store,cookies-store>>|Whether to store cookies. Note this option needs a restart with QtWebEngine.
|<<content-host-block-lists,host-block-lists>>|List of URLs of lists which contain hosts to block.
|<<content-host-blocking-enabled,host-blocking-enabled>>|Whether host blocking is enabled.
|<<content-host-blocking-whitelist,host-blocking-whitelist>>|List of domains that should always be loaded, despite being ad-blocked.
@@ -174,18 +184,18 @@
|==============
|Setting|Description
|<<hints-border,border>>|CSS border value for hints.
|<<hints-opacity,opacity>>|Opacity for hints.
|<<hints-mode,mode>>|Mode to use for hints.
|<<hints-chars,chars>>|Chars used for hint strings.
|<<hints-min-chars,min-chars>>|Minimum number of chars used for hint strings.
|<<hints-scatter,scatter>>|Whether to scatter hint key chains (like Vimium) or not (like dwb). Ignored for number hints.
|<<hints-uppercase,uppercase>>|Make chars in hint strings uppercase.
|<<hints-dictionary,dictionary>>|The dictionary file to be used by the word hints.
|<<hints-auto-follow,auto-follow>>|Follow a hint immediately when the hint text is completely matched.
|<<hints-auto-follow-timeout,auto-follow-timeout>>|A timeout to inhibit normal-mode key bindings after a successfulauto-follow.
|<<hints-auto-follow,auto-follow>>|Controls when a hint can be automatically followed without the user pressing Enter.
|<<hints-auto-follow-timeout,auto-follow-timeout>>|A timeout (in milliseconds) to inhibit normal-mode key bindings after a successful auto-follow.
|<<hints-next-regexes,next-regexes>>|A comma-separated list of regexes to use for 'next' links.
|<<hints-prev-regexes,prev-regexes>>|A comma-separated list of regexes to use for 'prev' links.
|<<hints-find-implementation,find-implementation>>|Which implementation to use to find elements to hint.
|<<hints-hide-unmatched-rapid-hints,hide-unmatched-rapid-hints>>|Controls hiding unmatched hints in rapid mode.
|==============
.Quick reference for section ``colors''
@@ -208,12 +218,6 @@
|<<colors-completion.scrollbar.bg,completion.scrollbar.bg>>|Color of the scrollbar in completion view
|<<colors-statusbar.fg,statusbar.fg>>|Foreground color of the statusbar.
|<<colors-statusbar.bg,statusbar.bg>>|Background color of the statusbar.
|<<colors-statusbar.fg.error,statusbar.fg.error>>|Foreground color of the statusbar if there was an error.
|<<colors-statusbar.bg.error,statusbar.bg.error>>|Background color of the statusbar if there was an error.
|<<colors-statusbar.fg.warning,statusbar.fg.warning>>|Foreground color of the statusbar if there is a warning.
|<<colors-statusbar.bg.warning,statusbar.bg.warning>>|Background color of the statusbar if there is a warning.
|<<colors-statusbar.fg.prompt,statusbar.fg.prompt>>|Foreground color of the statusbar if there is a prompt.
|<<colors-statusbar.bg.prompt,statusbar.bg.prompt>>|Background color of the statusbar if there is a prompt.
|<<colors-statusbar.fg.insert,statusbar.fg.insert>>|Foreground color of the statusbar in insert mode.
|<<colors-statusbar.bg.insert,statusbar.bg.insert>>|Background color of the statusbar in insert mode.
|<<colors-statusbar.fg.command,statusbar.fg.command>>|Foreground color of the statusbar in command mode.
@@ -243,7 +247,7 @@
|<<colors-tabs.indicator.error,tabs.indicator.error>>|Color for the tab indicator on errors..
|<<colors-tabs.indicator.system,tabs.indicator.system>>|Color gradient interpolation system for the tab indicator.
|<<colors-hints.fg,hints.fg>>|Font color for hints.
|<<colors-hints.bg,hints.bg>>|Background color for hints.
|<<colors-hints.bg,hints.bg>>|Background color for hints. Note that you can use a `rgba(...)` value for transparency.
|<<colors-hints.fg.match,hints.fg.match>>|Font color for the matched part of hints.
|<<colors-downloads.bg.bar,downloads.bg.bar>>|Background color for the download bar.
|<<colors-downloads.fg.start,downloads.fg.start>>|Color gradient start for download text.
@@ -258,6 +262,18 @@
|<<colors-keyhint.fg,keyhint.fg>>|Text color for the keyhint widget.
|<<colors-keyhint.fg.suffix,keyhint.fg.suffix>>|Highlight color for keys to complete the current keychain
|<<colors-keyhint.bg,keyhint.bg>>|Background color of the keyhint widget.
|<<colors-messages.fg.error,messages.fg.error>>|Foreground color of an error message.
|<<colors-messages.bg.error,messages.bg.error>>|Background color of an error message.
|<<colors-messages.border.error,messages.border.error>>|Border color of an error message.
|<<colors-messages.fg.warning,messages.fg.warning>>|Foreground color a warning message.
|<<colors-messages.bg.warning,messages.bg.warning>>|Background color of a warning message.
|<<colors-messages.border.warning,messages.border.warning>>|Border color of an error message.
|<<colors-messages.fg.info,messages.fg.info>>|Foreground color an info message.
|<<colors-messages.bg.info,messages.bg.info>>|Background color of an info message.
|<<colors-messages.border.info,messages.border.info>>|Border color of an info message.
|<<colors-prompts.fg,prompts.fg>>|Foreground color for prompts.
|<<colors-prompts.bg,prompts.bg>>|Background color for prompts.
|<<colors-prompts.selected.bg,prompts.selected.bg>>|Background color for the selected item in filename prompts.
|==============
.Quick reference for section ``fonts''
@@ -266,6 +282,7 @@
|Setting|Description
|<<fonts-_monospace,_monospace>>|Default monospace fonts.
|<<fonts-completion,completion>>|Font used in the completion widget.
|<<fonts-completion.category,completion.category>>|Font used in the completion categories.
|<<fonts-tabbar,tabbar>>|Font used in the tab bar.
|<<fonts-statusbar,statusbar>>|Font used in the statusbar.
|<<fonts-downloads,downloads>>|Font used for the downloadbar.
@@ -282,6 +299,10 @@
|<<fonts-web-size-default,web-size-default>>|The default font size for regular text.
|<<fonts-web-size-default-fixed,web-size-default-fixed>>|The default font size for fixed-pitch text.
|<<fonts-keyhint,keyhint>>|Font used in the keyhint widget.
|<<fonts-messages.error,messages.error>>|Font used for error messages.
|<<fonts-messages.warning,messages.warning>>|Font used for warning messages.
|<<fonts-messages.info,messages.info>>|Font used for info messages.
|<<fonts-prompts,prompts>>|Font used for prompts.
|==============
== general
@@ -303,7 +324,21 @@ Default: +pass:[smart]+
=== startpage
The default page(s) to open at the start, separated by commas.
Default: +pass:[https://duckduckgo.com]+
Default: +pass:[https://start.duckduckgo.com]+
[[general-yank-ignored-url-parameters]]
=== yank-ignored-url-parameters
The URL parameters to strip with :yank url, separated by commas.
Default: +pass:[ref,utm_source,utm_medium,utm_campaign,utm_term,utm_content]+
[[general-default-open-dispatcher]]
=== default-open-dispatcher
The default program used to open downloads. Set to an empty string to use the default internal handler.
Any {} in the string will be expanded to the filename, else the filename will be appended.
Default: empty
[[general-default-page]]
=== default-page
@@ -366,11 +401,13 @@ Valid values:
Default: +pass:[false]+
This setting is only available with the QtWebKit backend.
[[general-developer-extras]]
=== developer-extras
Enable extra tools for Web developers.
This needs to be enabled for `:inspector` to work and also adds an _Inspect_ entry to the context menu.
This needs to be enabled for `:inspector` to work and also adds an _Inspect_ entry to the context menu. For QtWebEngine, see 'qutebrowser --help' instead.
Valid values:
@@ -379,9 +416,12 @@ Valid values:
Default: +pass:[false]+
This setting is only available with the QtWebKit backend.
[[general-print-element-backgrounds]]
=== print-element-backgrounds
Whether the background color and images are also drawn when the page is printed.
This setting only works with Qt 5.8 or newer when using the QtWebEngine backend.
Valid values:
@@ -405,7 +445,7 @@ Default: +pass:[false]+
[[general-site-specific-quirks]]
=== site-specific-quirks
Enable workarounds for broken sites.
Enable QtWebKit workarounds for broken sites.
Valid values:
@@ -414,6 +454,8 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[general-default-encoding]]
=== default-encoding
Default encoding to use for websites.
@@ -436,6 +478,19 @@ Valid values:
Default: +pass:[tab]+
[[general-new-instance-open-target.window]]
=== new-instance-open-target.window
Which window to choose when opening links as new tabs.
Valid values:
* +first-opened+: Open new tabs in the first (oldest) opened window.
* +last-opened+: Open new tabs in the last (newest) opened window.
* +last-focused+: Open new tabs in the most recently focused window.
* +last-visible+: Open new tabs in the most recently visible window.
Default: +pass:[last-focused]+
[[general-log-javascript-console]]
=== log-javascript-console
How to log javascript console messages.
@@ -556,6 +611,8 @@ Valid values:
Default: +pass:[false]+
This setting is only available with the QtWebKit backend.
[[ui-frame-flattening]]
=== frame-flattening
Whether to expand each subframe to its contents.
@@ -569,11 +626,24 @@ Valid values:
Default: +pass:[false]+
This setting is only available with the QtWebKit backend.
[[ui-user-stylesheet]]
=== user-stylesheet
User stylesheet to use (absolute filename, filename relative to the config directory or CSS string). Will expand environment variables.
User stylesheet to use (absolute filename or filename relative to the config directory). Will expand environment variables.
Default: +pass:[::-webkit-scrollbar { width: 0px; height: 0px; }]+
Default: empty
[[ui-hide-scrollbar]]
=== hide-scrollbar
Hide the main scrollbar.
Valid values:
* +true+
* +false+
Default: +pass:[true]+
[[ui-css-media-type]]
=== css-media-type
@@ -581,6 +651,8 @@ Set the CSS media type.
Default: empty
This setting is only available with the QtWebKit backend.
[[ui-smooth-scrolling]]
=== smooth-scrolling
Whether to enable smooth scrolling for webpages.
@@ -626,20 +698,10 @@ The format to use for the window title. The following placeholders are defined:
* `{id}`: The internal window ID of this window.
* `{scroll_pos}`: The page scroll position.
* `{host}`: The host of the current web page.
* `{backend}`: Either 'webkit' or 'webengine'
Default: +pass:[{perc}{title}{title_sep}qutebrowser]+
[[ui-hide-mouse-cursor]]
=== hide-mouse-cursor
Whether to hide the mouse cursor.
Valid values:
* +true+
* +false+
Default: +pass:[false]+
[[ui-modal-js-dialog]]
=== modal-js-dialog
Use standard JavaScript modal dialog for alert() and confirm()
@@ -670,6 +732,23 @@ Globs are supported, so ';*' will blacklist all keychainsstarting with ';'. Use
Default: empty
[[ui-prompt-radius]]
=== prompt-radius
The rounding radius for the edges of prompts.
Default: +pass:[8]+
[[ui-prompt-filebrowser]]
=== prompt-filebrowser
Show a filebrowser in upload/download prompts.
Valid values:
* +true+
* +false+
Default: +pass:[true]+
== network
Settings related to the network.
@@ -702,6 +781,8 @@ Valid values:
Default: +pass:[same-domain]+
This setting is only available with the QtWebKit backend.
[[network-user-agent]]
=== user-agent
User agent to send. Empty to send the default.
@@ -714,6 +795,8 @@ The proxy to use.
In addition to the listed values, you can use a `socks://...` or `http://...` URL.
This setting only works with Qt 5.8 or newer when using the QtWebEngine backend.
Valid values:
* +system+: Use the system wide proxy.
@@ -732,6 +815,8 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[network-ssl-strict]]
=== ssl-strict
Whether to validate SSL handshakes.
@@ -755,25 +840,34 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[network-custom-headers]]
=== custom-headers
Set custom headers for qutebrowser HTTP requests.
Default: empty
[[network-netrc-file]]
=== netrc-file
Set location of a netrc-file for HTTP authentication. If empty, ~/.netrc is used.
Default: empty
== completion
Options related to completion and command history.
[[completion-auto-open]]
=== auto-open
Automatically open completion when typing.
[[completion-show]]
=== show
When to show the autocompletion window.
Valid values:
* +true+
* +false+
* +always+: Whenever a completion is available.
* +auto+: Whenever a completion is requested.
* +never+: Never.
Default: +pass:[true]+
Default: +pass:[always]+
[[completion-download-path-suggestion]]
=== download-path-suggestion
@@ -793,17 +887,6 @@ How to format timestamps (e.g. for history)
Default: +pass:[%Y-%m-%d]+
[[completion-show]]
=== show
Whether to show the autocompletion window.
Valid values:
* +true+
* +false+
Default: +pass:[true]+
[[completion-height]]
=== height
The height of the completion, in px or as percentage of the window.
@@ -865,7 +948,7 @@ Options related to input modes.
[[input-timeout]]
=== timeout
Timeout for ambiguous key bindings.
Timeout (in milliseconds) for ambiguous key bindings.
If the current input forms both a complete match and a partial match, the complete match will be executed after this time.
@@ -873,7 +956,7 @@ Default: +pass:[500]+
[[input-partial-timeout]]
=== partial-timeout
Timeout for partially typed key bindings.
Timeout (in milliseconds) for partially typed key bindings.
If the current input forms only partial matches, the keystring will be cleared after this time.
@@ -985,11 +1068,11 @@ Which tab to select when the focused tab is removed.
Valid values:
* +left+: Select the tab on the left.
* +right+: Select the tab on the right.
* +previous+: Select the previously selected tab.
* +prev+: Select the tab which came before the closed one (left in horizontal, above in vertical).
* +next+: Select the tab which came after the closed one (right in horizontal, below in vertical).
* +last-used+: Select the previously selected tab.
Default: +pass:[right]+
Default: +pass:[next]+
[[tabs-new-tab-position]]
=== new-tab-position
@@ -997,12 +1080,12 @@ How new tabs are positioned.
Valid values:
* +left+: On the left of the current tab.
* +right+: On the right of the current tab.
* +first+: At the left end.
* +last+: At the right end.
* +prev+: Before the current tab.
* +next+: After the current tab.
* +first+: At the beginning.
* +last+: At the end.
Default: +pass:[right]+
Default: +pass:[next]+
[[tabs-new-tab-position-explicit]]
=== new-tab-position-explicit
@@ -1010,10 +1093,10 @@ How new tabs opened explicitly are positioned.
Valid values:
* +left+: On the left of the current tab.
* +right+: On the right of the current tab.
* +first+: At the left end.
* +last+: At the right end.
* +prev+: Before the current tab.
* +next+: After the current tab.
* +first+: At the beginning.
* +last+: At the end.
Default: +pass:[last]+
@@ -1143,6 +1226,7 @@ The format to use for the tab title. The following placeholders are defined:
* `{id}`: The internal tab ID of this tab.
* `{scroll_pos}`: The page scroll position.
* `{host}`: The host of the current web page.
* `{backend}`: Either 'webkit' or 'webengine'
Default: +pass:[{index}: {title}]+
@@ -1223,6 +1307,8 @@ For more information about the feature, please refer to: http://webkit.org/blog/
Default: empty
This setting is only available with the QtWebKit backend.
[[storage-object-cache-capacities]]
=== object-cache-capacities
The capacities for the global memory cache for dead objects such as stylesheets or scripts. Syntax: cacheMinDeadCapacity, cacheMaxDead, totalCapacity.
@@ -1235,18 +1321,24 @@ _totalCapacity_ specifies the maximum number of bytes that the cache should cons
Default: empty
This setting is only available with the QtWebKit backend.
[[storage-offline-storage-default-quota]]
=== offline-storage-default-quota
Default quota for new offline storage databases.
Default: empty
This setting is only available with the QtWebKit backend.
[[storage-offline-web-application-cache-quota]]
=== offline-web-application-cache-quota
Quota for the offline web application cache.
Default: empty
This setting is only available with the QtWebKit backend.
[[storage-offline-storage-database]]
=== offline-storage-database
Whether support for the HTML 5 offline storage feature is enabled.
@@ -1258,6 +1350,8 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[storage-offline-web-application-storage]]
=== offline-web-application-storage
Whether support for the HTML 5 web application cache feature is enabled.
@@ -1273,6 +1367,8 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[storage-local-storage]]
=== local-storage
Whether support for the HTML 5 local storage feature is enabled.
@@ -1286,9 +1382,9 @@ Default: +pass:[true]+
[[storage-cache-size]]
=== cache-size
Size of the HTTP network cache.
Size of the HTTP network cache. Empty to use the default value.
Default: +pass:[52428800]+
Default: empty
== content
Loaded plugins/scripts and allowed actions.
@@ -1337,7 +1433,7 @@ Valid values:
* +true+
* +false+
Default: +pass:[false]+
Default: +pass:[true]+
[[content-css-regions]]
=== css-regions
@@ -1350,6 +1446,8 @@ Valid values:
Default: +pass:[true]+
This setting is only available with the QtWebKit backend.
[[content-hyperlink-auditing]]
=== hyperlink-auditing
Enable or disable hyperlink auditing (<a ping>).
@@ -1385,9 +1483,23 @@ Valid values:
Default: +pass:[ask]+
[[content-javascript-can-open-windows]]
=== javascript-can-open-windows
Whether JavaScript programs can open new windows.
[[content-media-capture]]
=== media-capture
Allow websites to record audio/video.
Valid values:
* +true+
* +false+
* +ask+
Default: +pass:[ask]+
This setting is only available with the QtWebEngine backend.
[[content-javascript-can-open-windows-automatically]]
=== javascript-can-open-windows-automatically
Whether JavaScript programs can open new windows without user interaction.
Valid values:
@@ -1407,6 +1519,8 @@ Valid values:
Default: +pass:[false]+
This setting is only available with the QtWebKit backend.
[[content-javascript-can-access-clipboard]]
=== javascript-can-access-clipboard
Whether JavaScript programs can read or write to the clipboard.
@@ -1475,9 +1589,11 @@ Valid values:
Default: +pass:[no-3rdparty]+
This setting is only available with the QtWebKit backend.
[[content-cookies-store]]
=== cookies-store
Whether to store cookies.
Whether to store cookies. Note this option needs a restart with QtWebEngine.
Valid values:
@@ -1496,7 +1612,7 @@ The file can be in one of the following formats:
- One host per line
- A zip-file of any of the above, with either only one file, or a file named 'hosts' (with any extension).
Default: +pass:[http://www.malwaredomainlist.com/hostslist/hosts.txt,http://someonewhocares.org/hosts/hosts,http://winhelp2002.mvps.org/hosts.zip,http://malwaredomains.lehigh.edu/files/justdomains.zip,http://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&amp;mimetype=plaintext]+
Default: +pass:[https://www.malwaredomainlist.com/hostslist/hosts.txt,http://someonewhocares.org/hosts/hosts,http://winhelp2002.mvps.org/hosts.zip,http://malwaredomains.lehigh.edu/files/justdomains.zip,https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&amp;mimetype=plaintext]+
[[content-host-blocking-enabled]]
=== host-blocking-enabled
@@ -1541,19 +1657,13 @@ CSS border value for hints.
Default: +pass:[1px solid #E3BE23]+
[[hints-opacity]]
=== opacity
Opacity for hints.
Default: +pass:[0.7]+
[[hints-mode]]
=== mode
Mode to use for hints.
Valid values:
* +number+: Use numeric hints.
* +number+: Use numeric hints. (In this mode you can also type letters form the hinted element to filter and reduce the number of elements that are hinted.)
* +letter+: Use the chars in the hints -> chars setting.
* +word+: Use hints words based on the html elements and the extra words.
@@ -1601,18 +1711,20 @@ Default: +pass:[/usr/share/dict/words]+
[[hints-auto-follow]]
=== auto-follow
Follow a hint immediately when the hint text is completely matched.
Controls when a hint can be automatically followed without the user pressing Enter.
Valid values:
* +true+
* +false+
* +always+: Auto-follow whenever there is only a single hint on a page.
* +unique-match+: Auto-follow whenever there is a unique non-empty match in either the hint string (word mode) or filter (number mode).
* +full-match+: Follow the hint when the user typed the whole hint (letter, word or number mode) or the element's text (only in number mode).
* +never+: The user will always need to press Enter to follow a hint.
Default: +pass:[true]+
Default: +pass:[unique-match]+
[[hints-auto-follow-timeout]]
=== auto-follow-timeout
A timeout to inhibit normal-mode key bindings after a successfulauto-follow.
A timeout (in milliseconds) to inhibit normal-mode key bindings after a successful auto-follow.
Default: +pass:[0]+
@@ -1637,7 +1749,18 @@ Valid values:
* +javascript+: Better but slower
* +python+: Slightly worse but faster
Default: +pass:[javascript]+
Default: +pass:[python]+
[[hints-hide-unmatched-rapid-hints]]
=== hide-unmatched-rapid-hints
Controls hiding unmatched hints in rapid mode.
Valid values:
* +true+
* +false+
Default: +pass:[true]+
== searchengines
Definitions of search engines which can be used via the address bar.
@@ -1647,7 +1770,7 @@ The searchengine named `DEFAULT` is used when `general -> auto-search` is true a
Aliases for commands.
By default, no aliases are defined. Example which adds a new command `:qtb` to open qutebrowsers website:
`qtb = open http://www.qutebrowser.org/`
`qtb = open https://www.qutebrowser.org/`
== colors
Colors used in the UI.
@@ -1760,42 +1883,6 @@ Background color of the statusbar.
Default: +pass:[black]+
[[colors-statusbar.fg.error]]
=== statusbar.fg.error
Foreground color of the statusbar if there was an error.
Default: +pass:[${statusbar.fg}]+
[[colors-statusbar.bg.error]]
=== statusbar.bg.error
Background color of the statusbar if there was an error.
Default: +pass:[red]+
[[colors-statusbar.fg.warning]]
=== statusbar.fg.warning
Foreground color of the statusbar if there is a warning.
Default: +pass:[${statusbar.fg}]+
[[colors-statusbar.bg.warning]]
=== statusbar.bg.warning
Background color of the statusbar if there is a warning.
Default: +pass:[darkorange]+
[[colors-statusbar.fg.prompt]]
=== statusbar.fg.prompt
Foreground color of the statusbar if there is a prompt.
Default: +pass:[${statusbar.fg}]+
[[colors-statusbar.bg.prompt]]
=== statusbar.bg.prompt
Background color of the statusbar if there is a prompt.
Default: +pass:[darkblue]+
[[colors-statusbar.fg.insert]]
=== statusbar.fg.insert
Foreground color of the statusbar in insert mode.
@@ -1979,9 +2066,9 @@ Default: +pass:[black]+
[[colors-hints.bg]]
=== hints.bg
Background color for hints.
Background color for hints. Note that you can use a `rgba(...)` value for transparency.
Default: +pass:[-webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785), color-stop(100%,#FFC542))]+
Default: +pass:[qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 247, 133, 0.8), stop:1 rgba(255, 197, 66, 0.8))]+
[[colors-hints.fg.match]]
=== hints.fg.match
@@ -2081,6 +2168,78 @@ Background color of the keyhint widget.
Default: +pass:[rgba(0, 0, 0, 80%)]+
[[colors-messages.fg.error]]
=== messages.fg.error
Foreground color of an error message.
Default: +pass:[white]+
[[colors-messages.bg.error]]
=== messages.bg.error
Background color of an error message.
Default: +pass:[red]+
[[colors-messages.border.error]]
=== messages.border.error
Border color of an error message.
Default: +pass:[#bb0000]+
[[colors-messages.fg.warning]]
=== messages.fg.warning
Foreground color a warning message.
Default: +pass:[white]+
[[colors-messages.bg.warning]]
=== messages.bg.warning
Background color of a warning message.
Default: +pass:[darkorange]+
[[colors-messages.border.warning]]
=== messages.border.warning
Border color of an error message.
Default: +pass:[#d47300]+
[[colors-messages.fg.info]]
=== messages.fg.info
Foreground color an info message.
Default: +pass:[white]+
[[colors-messages.bg.info]]
=== messages.bg.info
Background color of an info message.
Default: +pass:[black]+
[[colors-messages.border.info]]
=== messages.border.info
Border color of an info message.
Default: +pass:[#333333]+
[[colors-prompts.fg]]
=== prompts.fg
Foreground color for prompts.
Default: +pass:[white]+
[[colors-prompts.bg]]
=== prompts.bg
Background color for prompts.
Default: +pass:[darkblue]+
[[colors-prompts.selected.bg]]
=== prompts.selected.bg
Background color for the selected item in filename prompts.
Default: +pass:[#308cc6]+
== fonts
Fonts used for the UI, with optional style/weight/size.
@@ -2100,6 +2259,12 @@ Font used in the completion widget.
Default: +pass:[8pt ${_monospace}]+
[[fonts-completion.category]]
=== completion.category
Font used in the completion categories.
Default: +pass:[bold ${completion}]+
[[fonts-tabbar]]
=== tabbar
Font used in the tab bar.
@@ -2122,7 +2287,7 @@ Default: +pass:[8pt ${_monospace}]+
=== hints
Font used for the hints.
Default: +pass:[bold 13px Monospace]+
Default: +pass:[bold 13px ${_monospace}]+
[[fonts-debug-console]]
=== debug-console
@@ -2195,3 +2360,27 @@ Default: empty
Font used in the keyhint widget.
Default: +pass:[8pt ${_monospace}]+
[[fonts-messages.error]]
=== messages.error
Font used for error messages.
Default: +pass:[8pt ${_monospace}]+
[[fonts-messages.warning]]
=== messages.warning
Font used for warning messages.
Default: +pass:[8pt ${_monospace}]+
[[fonts-messages.info]]
=== messages.info
Font used for info messages.
Default: +pass:[8pt ${_monospace}]+
[[fonts-prompts]]
=== prompts
Font used for prompts.
Default: +pass:[8pt sans-serif]+

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 KiB

After

Width:  |  Height:  |  Size: 989 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -9,7 +9,8 @@ Basic keybindings to get you started
------------------------------------
* Use the arrow keys or `hjkl` to move around a webpage (vim-like syntax is used in quite a few places)
* To go to a new webpage, press `o`, then type a url, then press Enter (Use `O` to open the url in a new tab). If what you've typed isn't a url, then a search engine will be used instead (DuckDuckGo, by default)
* To go to a new webpage, press `o`, then type a url, then press Enter (Use `O` to open the url in a new tab, `go` to edit the current URL)
* If what you've typed isn't a url, then a search engine will be used instead (DuckDuckGo, by default)
* To switch between tabs, use `J` (next tab) and `K` (previous tab), or press `<Alt-num>`, where `num` is the position of the tab to switch to
* To close the current tab, press `d` (and press `u` to undo closing a tab)
* Use `H` and `L` to go back and forth in the history
@@ -24,13 +25,16 @@ What to do now
* View the link:http://qutebrowser.org/img/cheatsheet-big.png[key binding cheatsheet]
to make yourself familiar with the key bindings: +
image:http://qutebrowser.org/img/cheatsheet-small.png["qutebrowser key binding cheatsheet",link="http://qutebrowser.org/img/cheatsheet-big.png"]
* There's also a https://www.shortcutfoo.com/app/dojos/qutebrowser[free training
course] on shortcutfoo for the keybindings - note that you need to be in
insert mode (i) for it to work.
* Run `:adblock-update` to download adblock lists and activate adblocking.
* If you just cloned the repository, you'll need to run
`scripts/asciidoc2html.py` to generate the documentation.
* Go to the link:qute://settings[settings page] to set up qutebrowser the way you want it.
* Subscribe to
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[the mailinglist]
where there are weekly "what's new in qutebrowser" posts.
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[the mailinglist] or
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[the announce-only mailinglist].
* Let me know what features you are missing or things that need (even small!)
improvements.

View File

@@ -7,10 +7,10 @@
:man source: qutebrowser
:man manual: qutebrowser manpage
:toc:
:homepage: http://www.qutebrowser.org/
:homepage: https://www.qutebrowser.org/
== NAME
qutebrowser - a keyboard-driven, vim-like browser based on PyQt5 and QtWebKit.
qutebrowser - a keyboard-driven, vim-like browser based on PyQt5.
== SYNOPSIS
*qutebrowser* ['-OPTION' ['...']] [':COMMAND' ['...']] ['URL' ['...']]
@@ -38,17 +38,8 @@ show it.
*-h*, *--help*::
show this help message and exit
*-c* 'CONFDIR', *--confdir* 'CONFDIR'::
Set config directory (empty for no config storage).
*--datadir* 'DATADIR'::
Set data directory (empty for no data storage).
*--cachedir* 'CACHEDIR'::
Set cache directory (empty for no cache storage).
*--basedir* 'BASEDIR'::
Base directory for all storage. Other --*dir arguments are ignored if this is given.
Base directory for all storage.
*-V*, *--version*::
Show version and quit.
@@ -68,6 +59,9 @@ show it.
*--backend* '{webkit,webengine}'::
Which backend to use (webengine backend is EXPERIMENTAL!).
*--enable-webengine-inspector*::
Enable the web inspector for QtWebEngine. Note that this is a SECURITY RISK and you should not visit untrusted websites with the inspector turned on. See https://bugreports.qt.io/browse/QTBUG-50725 for more details.
=== debug arguments
*-l* '{critical,error,warning,info,debug,vdebug}', *--loglevel* '{critical,error,warning,info,debug,vdebug}'::
Set loglevel
@@ -111,23 +105,11 @@ show it.
*--no-err-windows*::
Don't show any error windows (used for tests/smoke.py).
*--qt-name* 'NAME'::
Set the window name.
*--qt-arg* 'NAME' 'VALUE'::
Pass an argument with a value to Qt. For example, you can do `--qt-arg geometry 650x555+200+300` to set the window geometry.
*--qt-style* 'STYLE'::
Set the Qt GUI style to use.
*--qt-stylesheet* 'STYLESHEET'::
Override the Qt application stylesheet.
*--qt-widgetcount*::
Print debug message at the end about number of widgets left undestroyed and maximum number of widgets existed at the same time.
*--qt-reverse*::
Set the application's layout direction to right-to-left.
*--qt-qmljsdebugger* 'port:PORT[,block]'::
Activate the QML/JS debugger with a specified port. 'block' is optional and will make the application wait until a debugger connects to it.
*--qt-flag* 'QT_FLAG'::
Pass an argument to Qt as flag.
// QUTE_OPTIONS_END
== FILES
@@ -145,7 +127,7 @@ defaults.
== BUGS
Bugs are tracked in the Github issue tracker at
https://github.com/The-Compiler/qutebrowser/issues.
https://github.com/qutebrowser/qutebrowser/issues.
If you found a bug, use the built-in ':report' command to create a bug report
with all information needed.
@@ -155,7 +137,7 @@ https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[mailinglist] at
mailto:qutebrowser@lists.qutebrowser.org[] instead.
For security bugs, please contact me directly at me@the-compiler.org, GPG ID
http://www.the-compiler.org/pubkey.asc[0xFD55A072].
https://www.the-compiler.org/pubkey.asc[0xFD55A072].
== COPYRIGHT
This program is free software: you can redistribute it and/or modify it under
@@ -171,12 +153,14 @@ You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
== RESOURCES
* Website: http://www.qutebrowser.org/
* Website: https://www.qutebrowser.org/
* Mailinglist: mailto:qutebrowser@lists.qutebrowser.org[] /
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser
* Announce-only mailinglist: mailto:qutebrowser-announce@lists.qutebrowser.org[] /
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce
* IRC: irc://irc.freenode.org/#qutebrowser[`#qutebrowser`] on
http://freenode.net/[Freenode]
* Github: https://github.com/The-Compiler/qutebrowser
* Github: https://github.com/qutebrowser/qutebrowser
== AUTHOR
*qutebrowser* was written by Florian Bruhin. All contributors can be found in

View File

@@ -41,21 +41,8 @@ For Archlinux, no debug informations are provided. You can either compile Qt
yourself (which will take a few hours even on a modern machine) or use
debugging symbols compiled/packaged by me (x86_64 only).
.To compile by yourself
----
$ git clone https://github.com/The-Compiler/qt-debug-pkgbuild.git
$ cd qt-debug-pkgbuild
$ git checkout symbols
$ export DEBUG_CFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
$ export DEBUG_CXXFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
$ cd qt5
$ makepkg -si --pkg qt5-base-debug,qt5-webkit-debug,qt5-webengine-debug
$ cd ../pyqt5
$ makepkg -si --pkg pyqt5-common-debug,python-pyqt5-debug
----
.To install my pre-built packages
To install my pre-built packages
++++++++++++++++++++++++++++++++
First download and sign the key:
@@ -76,12 +63,30 @@ Server = http://qutebrowser.org/qt-debug/$arch
Then install the packages:
----
# pacman -Suy pyqt5-common-debug python-pyqt5-debug qt5-base-debug qt5-webkit-debug,qt5-webengine-debug
# pacman -Suy pyqt5-common-debug python-pyqt5-debug qt5-base-debug qt5-webkit-debug qt5-webengine-debug
----
The `-debug` packages conflict with the non-debug variants - it's safe to
remove them.
To compile by yourself
++++++++++++++++++++++
Note that building Qt will likely take multiple hours, even on a recent system.
I'd also expect it to take around 6 GB of RAM and 30 GB of disk space for a
successful compile run.
----
$ git clone https://github.com/qutebrowser/qt-debug-pkgbuild.git
$ cd qt-debug-pkgbuild
$ export DEBUG_CFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
$ export DEBUG_CXXFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
$ cd qt5
$ makepkg -si --pkg qt5-base-debug,qt5-webkit-debug,qt5-webengine-debug
$ cd ../pyqt5
$ makepkg -si --pkg pyqt5-common-debug,python-pyqt5-debug
----
Getting the stack trace
~~~~~~~~~~~~~~~~~~~~~~~
@@ -169,7 +174,7 @@ When you see the _qutebrowser.exe has stopped working_ window, do not click
file displayed there.
Now install
http://www.microsoft.com/en-us/download/details.aspx?id=42933[DebugDiag] from
https://www.microsoft.com/en-us/download/details.aspx?id=49924[DebugDiag] from
Microsoft, then run the *DebugDiag 2 Analysis* tool. There, check
*CrashHangAnalysis* and add your crash dump via *Add Data files*. Then click
*Start analysis*.

View File

@@ -22,6 +22,8 @@ To call a userscript, it needs to be stored in your data directory under
`userscripts` (for example: `~/.local/share/qutebrowser/userscripts/myscript`),
or just use an absolute path.
NOTE: On Windows, only userscripts with `com`, `bat`, or `exe` extensions will be launched.
Getting information
-------------------
@@ -36,13 +38,15 @@ The following environment variables will be set when a userscript is launched:
- `QUTE_CONFIG_DIR`: Path of the directory containing qutebrowser's configuration.
- `QUTE_DATA_DIR`: Path of the directory containing qutebrowser's data.
- `QUTE_DOWNLOAD_DIR`: Path of the downloads directory.
- `QUTE_COMMANDLINE_TEXT`: Text currently in qutebrowser's command line.
In `command` mode:
- `QUTE_URL`: The current URL.
- `QUTE_TITLE`: The title of the current page.
- `QUTE_SELECTED_TEXT`: The text currently selected on the page.
- `QUTE_SELECTED_HTML` The HTML currently selected on the page.
- `QUTE_SELECTED_HTML` The HTML currently selected on the page (not supported
with QtWebEngine).
In `hints` mode:

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 170 KiB

View File

@@ -1,35 +0,0 @@
FROM base/archlinux
MAINTAINER Florian Bruhin <me@the-compiler.org>
RUN echo 'Server = http://mirror.de.leaseweb.net/archlinux/$repo/os/$arch' > /etc/pacman.d/mirrorlist
RUN pacman-key --init && pacman-key --populate archlinux && pacman -Sy --noconfirm archlinux-keyring
RUN pacman -Suyy --noconfirm
RUN pacman-db-upgrade
RUN pacman -S --noconfirm \
git \
python-tox \
qt5-base \
qt5-webkit \
python-pyqt5 \
xorg-xinit \
herbstluftwm \
xorg-server-xvfb
RUN echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen && locale-gen
RUN useradd user && mkdir /home/user && chown -R user:users /home/user
USER user
WORKDIR /home/user
ENV DISPLAY=:0
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
CMD Xvfb -screen 0 800x600x24 :0 & \
sleep 2 && \
herbstluftwm & \
git clone /outside qutebrowser.git && \
cd qutebrowser.git && \
tox -e py35

View File

@@ -1,35 +0,0 @@
FROM debian:jessie
MAINTAINER Florian Bruhin <me@the-compiler.org>
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
apt-get -y dist-upgrade && \
apt-get -y install --no-install-recommends \
python3-pyqt5 \
python3-pyqt5.qtwebkit \
python-tox \
python3-sip \
xvfb \
git \
python3-setuptools \
wget \
herbstluftwm \
locales \
libjs-pdf
RUN echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen && locale-gen
RUN useradd user && mkdir /home/user && chown -R user:users /home/user
USER user
WORKDIR /home/user
ENV DISPLAY=:0
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
CMD Xvfb -screen 0 800x600x24 :0 & \
sleep 2 && \
herbstluftwm & \
git clone /outside qutebrowser.git && \
cd qutebrowser.git && \
tox -e py34

View File

@@ -1,37 +0,0 @@
FROM ubuntu:wily
MAINTAINER Florian Bruhin <me@the-compiler.org>
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
apt-get -y dist-upgrade && \
apt-get -y install --no-install-recommends \
python3-pyqt5 \
python3-pyqt5.qtwebkit \
python-tox \
python3-sip \
xvfb \
git \
python3-setuptools \
wget \
herbstluftwm \
language-pack-en \
libjs-pdf \
dbus
RUN dbus-uuidgen --ensure
RUN useradd user && mkdir /home/user && chown -R user:users /home/user
USER user
WORKDIR /home/user
ENV DISPLAY=:0
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
CMD Xvfb -screen 0 800x600x24 :0 & \
sleep 2 && \
herbstluftwm & \
git clone /outside qutebrowser.git && \
cd qutebrowser.git && \
tox -e py34

View File

@@ -1,37 +0,0 @@
FROM ubuntu:xenial
MAINTAINER Florian Bruhin <me@the-compiler.org>
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
apt-get -y dist-upgrade && \
apt-get -y install --no-install-recommends \
python3-pyqt5 \
python3-pyqt5.qtwebkit \
python-tox \
python3-sip \
xvfb \
git \
python3-setuptools \
wget \
herbstluftwm \
language-pack-en \
libjs-pdf \
dbus
RUN dbus-uuidgen --ensure
RUN useradd user && mkdir /home/user && chown -R user:users /home/user
USER user
WORKDIR /home/user
ENV DISPLAY=:0
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
CMD Xvfb -screen 0 800x600x24 :0 & \
sleep 2 && \
herbstluftwm & \
git clone /outside qutebrowser.git && \
cd qutebrowser.git && \
tox -e py35

View File

@@ -70,5 +70,9 @@ coll = COLLECT(exe,
app = BUNDLE(coll,
name='qutebrowser.app',
icon=icon,
info_plist={'NSHighResolutionCapable': 'True'},
bundle_identifier=None)
info_plist={
'NSHighResolutionCapable': 'True',
'NSSupportsAutomaticGraphicsSwitching': 'True',
},
# https://github.com/pyinstaller/pyinstaller/blob/b78bfe530cdc2904f65ce098bdf2de08c9037abb/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py#L24
bundle_identifier='org.qt-project.Qt.QtWebEngineCore')

View File

@@ -1,3 +1,3 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
check-manifest==0.31
check-manifest==0.35

View File

@@ -1,5 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
codecov==2.0.5
coverage==4.1
requests==2.10.0
coverage==4.3.4
requests==2.13.0

View File

@@ -1,3 +1,3 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
cx-Freeze==4.3.4
cx-Freeze==4.3.4 # rq.filter: < 5.0.0

View File

@@ -1 +1,5 @@
cx_Freeze
cx-Freeze < 5.0.0
# We'll probably switch to PyInstaller soon, and 5.x doesn't install without a
# compiler?
#@ filter: cx-Freeze < 5.0.0

View File

@@ -2,25 +2,19 @@
flake8==2.6.2 # rq.filter: < 3.0.0
flake8-copyright==0.2.0
flake8-debugger==1.4.0
flake8-deprecated==1.0
flake8-docstrings==0.2.8
flake8-debugger==1.4.0 # rq.filter: != 2.0.0
flake8-deprecated==1.1
flake8-docstrings==1.0.3
flake8-future-import==0.4.3
flake8-mock==0.2
flake8-pep3101==0.4
flake8-mock==0.3
flake8-pep3101==1.0
flake8-polyfill==1.0.1
flake8-putty==0.4.0
flake8-string-format==0.2.2
flake8-tidy-imports==1.0.2
flake8-string-format==0.2.3
flake8-tidy-imports==1.0.5
flake8-tuple==0.2.12
hacking==0.11.0
mccabe==0.5.0
packaging==16.7
pbr==1.10.0
pep257==0.7.0 # still needed by flake8-docstrings but ignored
pep8==1.7.0
mccabe==0.6.1
pep8-naming==0.4.1
pycodestyle==2.0.0
pydocstyle==1.0.0
pyflakes==1.2.3
pyparsing==2.1.5
six==1.10.0
pycodestyle==2.3.1
pydocstyle==1.1.1
pyflakes==1.5.0

View File

@@ -1,6 +1,6 @@
flake8<3.0.0
flake8-copyright
flake8-debugger
flake8-debugger!=2.0.0
flake8-deprecated
flake8-docstrings
flake8-future-import
@@ -10,14 +10,17 @@ flake8-putty
flake8-string-format
flake8-tidy-imports
flake8-tuple
hacking
pep8-naming
pydocstyle
pyflakes
pep8==1.7.0
# Pinned to 2.0.0 otherwise
pycodestyle==2.3.1
# Pinned to 0.5.3 otherwise
mccabe==0.6.1
#@ comment: pep257 still needed by flake8-docstrings but ignored
# Waiting until hacking/flake8-tuple are updated
# Waiting until flake8-putty updated
#@ filter: flake8 < 3.0.0
# https://github.com/JBKahn/flake8-debugger/issues/5
#@ filter: flake8-debugger != 2.0.0

View File

@@ -1 +1,8 @@
pip==8.1.2
# This file is automatically generated by scripts/dev/recompile_requirements.py
appdirs==1.4.2
packaging==16.8
pyparsing==2.1.10
setuptools==34.3.0
six==1.10.0
wheel==0.29.0

View File

@@ -1,3 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyInstaller==3.2
-e git+https://github.com/pyinstaller/pyinstaller.git@develop#egg=PyInstaller
PyQt5==5.8
sip==4.19.1

View File

@@ -1 +1,5 @@
PyInstaller
-e git+https://github.com/pyinstaller/pyinstaller.git@develop#egg=PyInstaller
PyQt5
# remove @commit-id for scm installs
#@ replace: @.*# @develop#

View File

@@ -1,11 +1,11 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-e git+https://github.com/PyCQA/astroid.git#egg=astroid
editdistance==0.3.1
isort==4.2.5
lazy-object-proxy==1.2.2
mccabe==0.5.0
mccabe==0.6.1
-e git+https://github.com/PyCQA/pylint.git#egg=pylint
./scripts/dev/pylint_checkers
requests==2.10.0
six==1.10.0
requests==2.13.0
wrapt==1.10.8

View File

@@ -3,9 +3,6 @@
./scripts/dev/pylint_checkers
requests
# https://github.com/PyCQA/pylint/issues/932
mccabe==0.5.0
# remove @commit-id for scm installs
#@ replace: @.*# #

View File

@@ -1,11 +1,13 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
astroid==1.4.7
astroid==1.4.9
github3.py==0.9.6
isort==4.2.5
lazy-object-proxy==1.2.2
mccabe==0.5.0
pylint==1.6.4
mccabe==0.6.1
pylint==1.6.5
./scripts/dev/pylint_checkers
requests==2.10.0
six==1.10.0
requests==2.13.0
uritemplate==3.0.0
uritemplate.py==3.0.2
wrapt==1.10.8

View File

@@ -1,6 +1,7 @@
pylint
./scripts/dev/pylint_checkers
requests
github3.py
# fix qute-pylint location
#@ replace: qute-pylint==.* ./scripts/dev/pylint_checkers

View File

@@ -1,4 +1,4 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
docutils==0.12
pyroma==2.0.2
docutils==0.13.1
pyroma==2.2

View File

@@ -0,0 +1,49 @@
bzr+lp:beautifulsoup
git+https://github.com/cherrypy/cheroot.git
hg+https://bitbucket.org/ned/coveragepy
git+https://github.com/micheles/decorator.git
git+https://github.com/pallets/flask.git
git+https://github.com/miracle2k/python-glob2.git
git+https://github.com/Runscope/httpbin.git
git+https://github.com/HypothesisWorks/hypothesis-python.git
git+https://github.com/pallets/itsdangerous.git
git+https://bitbucket.org/zzzeek/mako.git
git+https://github.com/r1chardj0n3s/parse.git
git+https://github.com/jenisys/parse_type.git
hg+https://bitbucket.org/pytest-dev/py
git+https://github.com/pytest-dev/pytest.git@features
git+https://github.com/pytest-dev/pytest-bdd.git
# This is broken at the moment because logfail tries to access
# LogCaptureHandler
# git+https://github.com/eisensheng/pytest-catchlog.git
pytest-catchlog==1.2.2
git+https://github.com/pytest-dev/pytest-cov.git
git+https://github.com/pytest-dev/pytest-faulthandler.git
git+https://github.com/pytest-dev/pytest-instafail.git
git+https://github.com/pytest-dev/pytest-mock.git
git+https://github.com/pytest-dev/pytest-qt.git
git+https://github.com/pytest-dev/pytest-repeat.git
git+https://github.com/pytest-dev/pytest-rerunfailures.git
git+https://github.com/abusalimov/pytest-travis-fold.git
git+https://github.com/fschulze/pytest-warnings.git
git+https://github.com/The-Compiler/pytest-xvfb.git
hg+https://bitbucket.org/gutworth/six
hg+https://bitbucket.org/jendrikseipp/vulture
git+https://github.com/pallets/werkzeug.git
## qutebrowser dependencies
git+https://github.com/tartley/colorama.git
hg+https://bitbucket.org/cthedot/cssutils
git+https://github.com/pallets/jinja.git
git+https://github.com/pallets/markupsafe.git
hg+http://bitbucket.org/birkenfeld/pygments-main
hg+https://bitbucket.org/fdik/pypeg
# Fails to build:
# gcc: error: ext/_yaml.c: No such file or directory
# hg+https://bitbucket.org/xi/pyyaml
PyYAML==3.12

View File

@@ -1,32 +1,36 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
beautifulsoup4==4.5.0
CherryPy==7.1.0
coverage==4.1
decorator==4.0.10
Flask==0.10.1 # rq.filter: < 0.11.0
glob2==0.4.1
httpbin==0.4.1
hypothesis==3.4.2
beautifulsoup4==4.5.3
cheroot==5.1.0
click==6.7
coverage==4.3.4
decorator==4.0.11
EasyProcess==0.2.3
Flask==0.12
glob2==0.5
httpbin==0.5.0
hypothesis==3.6.1
itsdangerous==0.24
# Jinja2==2.8
Mako==1.0.4
# Jinja2==2.9.5
Mako==1.0.6
# MarkupSafe==0.23
parse==1.6.6
parse-type==0.3.4
py==1.4.31
pytest==2.9.2
pytest-bdd==2.17.0
py==1.4.32
pytest==3.0.6
pytest-bdd==2.18.1
pytest-benchmark==3.0.0
pytest-catchlog==1.2.2
pytest-cov==2.3.0
pytest-faulthandler==1.3.0
pytest-cov==2.4.0
pytest-faulthandler==1.3.1
pytest-instafail==0.3.0
pytest-mock==1.1
pytest-qt==1.11.0
pytest-repeat==0.3.0
pytest-rerunfailures==2.0.0
pytest-mock==1.5.0
pytest-qt==2.1.0
pytest-repeat==0.4.1
pytest-rerunfailures==2.1.0
pytest-travis-fold==1.2.0
pytest-xvfb==0.2.0
six==1.10.0
vulture==0.10
Werkzeug==0.11.10
pytest-warnings==0.2.0
pytest-xvfb==1.0.0
PyVirtualDisplay==0.2.1
vulture==0.12
Werkzeug==0.11.15

View File

@@ -1,11 +1,12 @@
beautifulsoup4
CherryPy
cheroot
coverage
Flask==0.10.1
Flask
httpbin
hypothesis
pytest
pytest-bdd
pytest-benchmark
pytest-catchlog
pytest-cov
pytest-faulthandler
@@ -15,8 +16,8 @@ pytest-qt
pytest-repeat
pytest-rerunfailures
pytest-travis-fold
pytest-warnings
pytest-xvfb
vulture
#@ filter: Flask < 0.11.0
#@ ignore: Jinja2, MarkupSafe

View File

@@ -1,6 +1,6 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
pluggy==0.3.1
py==1.4.31
tox==2.3.1
virtualenv==15.0.2
pluggy==0.4.0
py==1.4.32
tox==2.6.0
virtualenv==15.1.0

View File

@@ -1 +1,4 @@
tox
# The latest tox release still depends on pluggy < 0.4...
pluggy==0.4.0

View File

@@ -1,3 +1,3 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
vulture==0.10
vulture==0.12

150
misc/userscripts/cast Executable file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env bash
#
# Behaviour
# Userscript for qutebrowser which casts the url passed in $1 to the default
# ChromeCast device in the network using the program `castnow`
#
# Usage
# You can launch the script from qutebrowser as follows:
# spawn --userscript ${PATH_TO_FILE} {url}
#
# Then, you can control the chromecast by launching the simple command
# `castnow` in a shell which will connect to the running castnow instance.
#
# For stopping the script, issue the command `pkill -f castnow` which would
# then let the rest of the userscript execute for cleaning temporary file.
#
# Thanks
# This userscript borrows Thorsten Wißmann's javascript code from his `mpv`
# userscript.
#
# Dependencies
# - castnow, https://github.com/xat/castnow
#
# Author
# Simon Désaulniers <sim.desaulniers@gmail.com>
if [ -z "$QUTE_FIFO" ] ; then
cat 1>&2 <<EOF
Error: $0 can not be run as a standalone script.
It is a qutebrowser userscript. In order to use it, call it using
'spawn --userscript' as described in qute://help/userscripts.html
EOF
exit 1
fi
msg() {
local cmd="$1"
shift
local msg="$*"
if [ -z "$QUTE_FIFO" ] ; then
echo "$cmd: $msg" >&2
else
echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
fi
}
js() {
cat <<EOF
function descendantOfTagName(child, ancestorTagName) {
// tells whether child has some (proper) ancestor
// with the tag name ancestorTagName
while (child.parentNode != null) {
child = child.parentNode;
if (typeof child.tagName === 'undefined') break;
if (child.tagName.toUpperCase() == ancestorTagName.toUpperCase()) {
return true;
}
}
return false;
}
var App = {};
var all_videos = [];
all_videos.push.apply(all_videos, document.getElementsByTagName("video"));
all_videos.push.apply(all_videos, document.getElementsByTagName("object"));
all_videos.push.apply(all_videos, document.getElementsByTagName("embed"));
App.backup_videos = Array();
App.all_replacements = Array();
for (i = 0; i < all_videos.length; i++) {
var video = all_videos[i];
if (descendantOfTagName(video, "object")) {
// skip tags that are contained in an object, because we hide
// the object anyway.
continue;
}
var replacement = document.createElement("div");
replacement.innerHTML = "
<p style=\\"margin-bottom: 0.5em\\">
The video is being cast on your ChromeCast device.
</p>
<p>
In order to restore this particular video
<a style=\\"font-weight: bold;
color: white;
background: transparent;
\\"
onClick=\\"restore_video(this, " + i + ");\\"
href=\\"javascript: restore_video(this, " + i + ")\\"
>click here</a>.
</p>
";
replacement.style.position = "relative";
replacement.style.zIndex = "100003000000";
replacement.style.fontSize = "1rem";
replacement.style.textAlign = "center";
replacement.style.verticalAlign = "middle";
replacement.style.height = "100%";
replacement.style.background = "#101010";
replacement.style.color = "white";
replacement.style.border = "4px dashed #545454";
replacement.style.padding = "2em";
replacement.style.margin = "auto";
App.all_replacements[i] = replacement;
App.backup_videos[i] = video;
video.parentNode.replaceChild(replacement, video);
}
function restore_video(obj, index) {
obj = App.all_replacements[index];
video = App.backup_videos[index];
console.log(video);
obj.parentNode.replaceChild(video, obj);
}
/** force repainting the video, thanks to:
* http://martinwolf.org/2014/06/10/force-repaint-of-an-element-with-javascript/
*/
var siteHeader = document.getElementById('header');
siteHeader.style.display='none';
siteHeader.offsetHeight; // no need to store this anywhere, the reference is enough
siteHeader.style.display='block';
EOF
}
printjs() {
js | sed 's,//.*$,,' | tr '\n' ' '
}
echo "jseval -q $(printjs)" >> "$QUTE_FIFO"
tmpdir=$(mktemp -d)
file_to_cast=${tmpdir}/qutecast
# kill any running instance of castnow
pkill -f /usr/bin/castnow
# start youtube download in stream mode (-o -) into temporary file
youtube-dl -qo - "$1" > ${file_to_cast} &
ytdl_pid=$!
msg info "Casting $1" >> "$QUTE_FIFO"
# start castnow in stream mode to cast on ChromeCast
tail -F "${file_to_cast}" | castnow -
# cleanup remaining background process and file on disk
kill ${ytdl_pid}
rm -rf ${tmpdir}

View File

@@ -342,10 +342,14 @@ cat <<EOF
for (var j = 0; j < inputs.length; j++) {
var input = inputs[j];
if (input.type == "text" || input.type == "email") {
input.focus();
input.value = "$(javascript_escape "${username}")";
input.blur();
}
if (input.type == "password") {
input.focus();
input.value = "$(javascript_escape "${password}")";
input.blur();
}
}
};

View File

@@ -24,9 +24,9 @@
# Caveat: Does not use authentication of any kind. Add it in if you want it to.
#
path=/tmp/qutebrowser_$(mktemp XXXXXXXX).html
path=$(mktemp --tmpdir qutebrowser_XXXXXXXX.html)
curl "$QUTE_URL" > $path
curl "$QUTE_URL" > "$path"
urxvt -e vim "$path"
rm "$path"

25
misc/userscripts/readability Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env python2
#
# Executes python-readability on current page and opens the summary as new tab.
#
# Usage:
# :spawn --userscript readability
#
from __future__ import absolute_import
import codecs, os
from readability.readability import Document
tmpfile=os.path.expanduser('~/.local/share/qutebrowser/userscripts/readability.html')
if not os.path.exists(os.path.dirname(tmpfile)):
os.makedirs(os.path.dirname(tmpfile))
with codecs.open(os.environ['QUTE_HTML'], 'r', 'utf-8') as source:
doc = Document(source.read())
content = doc.summary().replace('<html>', '<html><head><title>%s</title></head>' % doc.title())
with codecs.open(tmpfile, 'w', 'utf-8') as target:
target.write('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />')
target.write(content)
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
fifo.write('open -t %s' % tmpfile)

27
misc/userscripts/ripbang Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env python2
#
# Adds DuckDuckGo bang as searchengine.
#
# Usage:
# :spawn --userscript ripbang [bang]...
#
# Example:
# :spawn --userscript ripbang amazon maps
#
import os, re, requests, sys, urllib
for argument in sys.argv[1:]:
bang = '!' + argument
r = requests.get('https://duckduckgo.com/',
params={'q': bang + ' SEARCHTEXT'})
searchengine = urllib.unquote(re.search("url=[^']+", r.text).group(0))
searchengine = searchengine.replace('url=', '')
searchengine = searchengine.replace('/l/?kh=-1&uddg=', '')
searchengine = searchengine.replace('SEARCHTEXT', '{}')
if os.getenv('QUTE_FIFO'):
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
fifo.write('set searchengines %s %s' % (bang, searchengine))
else:
print '%s %s' % (bang, searchengine)

122
misc/userscripts/rss Executable file
View File

@@ -0,0 +1,122 @@
#!/bin/sh
# Copyright 2016 Jan Verbeek (blyxxyz) <ring@openmailbox.org>
#
# 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 <http://www.gnu.org/licenses/>.
# This script keeps track of URLs in RSS feeds and opens new ones.
# New feeds can be added with ':spawn -u /path/to/userscripts/rss add' or
# ':spawn -u /path/to/userscripts/rss <url>'.
# New items can be opened with ':spawn -u /path/to/userscripts/rss'.
# The script doesn't really parse XML, and searches for things that look like
# item links. It might open things that aren't real links, and it might miss
# real links.
config_dir="$HOME/.qute-rss"
add_feed () {
touch "feeds"
if grep -Fq "$1" "feeds"; then
notice "$1 is saved already."
else
printf "%s\n" "$1" >> "feeds"
fi
}
# Show an error message and exit
fail () {
echo "message-error '$*'" > "$QUTE_FIFO"
exit 1
}
# Get a sorted list of item URLs from a RSS feed
get_items () {
$curl "$@" | grep "$text_only" -zo -e '<guid[^<>]*>[^<>]*</guid>' \
-e '<link[^<>]*>[^<>]*</link>' \
-e '<link[^<>]*href="[^"]*"' |
grep "$text_only" -o 'http[^<>"]*' | sort | uniq
}
# Show an info message
notice () {
echo "message-info '$*'" > "$QUTE_FIFO"
}
# Update a database of a feed and open new URLs
read_items () {
cd read_urls
feed_file="$(echo "$1" | tr -d /)"
feed_temp_file="$(mktemp "$feed_file.tmp.XXXXXXXXXX")"
feed_new_items="$(mktemp "$feed_file.new.XXXXXXXXXX")"
get_items "$1" > "$feed_temp_file"
if [ ! -s "$feed_temp_file" ]; then
notice "No items found for $1."
rm "$feed_temp_file" "$feed_new_items"
elif [ ! -f "$feed_file" ]; then
notice "$1 is a new feed. All items will be marked as read."
mv "$feed_temp_file" "$feed_file"
rm "$feed_new_items"
else
sort -o "$feed_file" "$feed_file"
comm -2 -3 "$feed_temp_file" "$feed_file" | tee "$feed_new_items"
cat "$feed_new_items" >> "$feed_file"
sort -o "$feed_file" "$feed_file"
rm "$feed_temp_file" "$feed_new_items"
fi | while read item; do
echo "open -t $item" > "$QUTE_FIFO"
done
}
if [ ! -d "$config_dir/read_urls" ]; then
notice "Creating configuration directory."
mkdir -p "$config_dir/read_urls"
fi
cd "$config_dir"
if [ $# != 0 ]; then
for arg in "$@"; do
if [ "$arg" = "add" ]; then
add_feed "$QUTE_URL"
else
add_feed "$arg"
fi
done
exit
fi
if [ ! -f "feeds" ]; then
fail "Add feeds by running ':spawn -u rss add' or ':spawn -u rss <url>'."
fi
if curl --version >&-; then
curl="curl -sL"
elif wget --version >&-; then
curl="wget -qO -"
else
fail "Either curl or wget is needed to run this script."
fi
# Detect GNU grep so we can force it to treat everything as text
if < /dev/null grep --help 2>&1 | grep -q -- -a; then
text_only="-a"
fi
while read feed_url; do
read_items "$feed_url" &
done < "$config_dir/feeds"
wait

View File

@@ -1,5 +1,5 @@
[pytest]
addopts = --strict -rfEw --faulthandler-timeout=70 --instafail
addopts = --strict -rfEw --faulthandler-timeout=70 --instafail --pythonwarnings error
markers =
gui: Tests using the GUI (e.g. spawning widgets)
posix: Tests which only can run on a POSIX OS.
@@ -14,7 +14,16 @@ markers =
end2end: End to end tests which run qutebrowser as subprocess
xfail_norun: xfail the test with out running it
ci: Tests which should only run on CI.
flaky_once: Try to rerun this test once if it fails
qtwebengine_todo: Features still missing with QtWebEngine
qtwebengine_skip: Tests not applicable with QtWebEngine
qtwebkit_skip: Tests not applicable with QtWebKit
qtwebkit_ng_xfail: Tests failing with QtWebKit-NG
qtwebkit_ng_skip: Tests skipped with QtWebKit-NG
qtwebengine_flaky: Tests which are flaky (and currently skipped) with QtWebEngine
qtwebengine_osx_xfail: Tests which fail on OS X with QtWebEngine
js_prompt: Tests needing to display a javascript prompt
this: Used to mark tests during development
no_invalid_lines: Don't fail on unparseable lines in end2end tests
qt_log_level_fail = WARNING
qt_log_ignore =
^SpellCheck: .*
@@ -23,6 +32,9 @@ qt_log_ignore =
^QProcess: Destroyed while process .* is still running\.
^"Method "GetAll" with signature "s" on interface "org\.freedesktop\.DBus\.Properties" doesn't exist
^"Method \\"GetAll\\" with signature \\"s\\" on interface \\"org\.freedesktop\.DBus\.Properties\\" doesn't exist\\n"
^propsReply "Method \\"GetAll\\" with signature \\"s\\" on interface \\"org\.freedesktop\.DBus\.Properties\\" doesn't exist\\n"
^nmReply "Method \\"GetDevices\\" with signature \\"\\" on interface \\"org\.freedesktop\.NetworkManager\\" doesn't exist\\n"
^"Object path cannot be empty"
^virtual void QSslSocketBackendPrivate::transmit\(\) SSL write failed with error: -9805
^virtual void QSslSocketBackendPrivate::transmit\(\) SSLRead failed with: -9805
^Type conversion already registered from type .*
@@ -30,11 +42,13 @@ qt_log_ignore =
^QWaitCondition: Destroyed while threads are still waiting
^QXcbXSettings::QXcbXSettings\(QXcbScreen\*\) Failed to get selection owner for XSETTINGS_S atom
^QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to .*
^QXcbClipboard: SelectionRequest too old
^QGeoclueMaster error creating GeoclueMasterClient\.
^Geoclue error: Process org\.freedesktop\.Geoclue\.Master exited with status 127
^QObject::connect: Cannot connect \(null\)::stateChanged\(QNetworkSession::State\) to QNetworkReplyHttpImpl::_q_networkSessionStateChanged\(QNetworkSession::State\)
^QXcbClipboard: Cannot transfer data, no data available
^load glyph failed
qt_wait_signal_raising = true
^Error when parsing the netrc file
^Image of format '' blocked because it is not considered safe. If you are sure it is safe to do so, you can white-list the format by setting the environment variable QTWEBKIT_IMAGEFORMAT_WHITELIST=
^QPainter::end: Painter ended with \d+ saved states
^QSslSocket: cannot resolve SSLv[23]_(client|server)_method
xfail_strict = true

View File

@@ -8,3 +8,4 @@ Exec=qutebrowser %u
Terminal=false
StartupNotify=false
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
Keywords=Browser

View File

@@ -17,9 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=line-too-long
"""A keyboard-driven, vim-like browser based on PyQt5 and QtWebKit."""
"""A keyboard-driven, vim-like browser based on PyQt5."""
import os.path
@@ -28,8 +26,8 @@ __copyright__ = "Copyright 2014-2016 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version_info__ = (0, 8, 0)
__version_info__ = (0, 10, 0)
__version__ = '.'.join(str(e) for e in __version_info__)
__description__ = "A keyboard-driven, vim-like browser based on PyQt5 and QtWebKit."
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."
basedir = os.path.dirname(os.path.realpath(__file__))

View File

@@ -32,10 +32,9 @@ import datetime
import tokenize
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtGui import QDesktopServices, QPixmap, QIcon, QCursor, QWindow
from PyQt5.QtGui import QDesktopServices, QPixmap, QIcon, QWindow
from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
QObject, Qt, QEvent, pyqtSignal)
QObject, QEvent, pyqtSignal)
try:
import hunter
except ImportError:
@@ -46,12 +45,15 @@ import qutebrowser.resources
from qutebrowser.completion.models import instances as completionmodels
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, config, websettings, configexc
from qutebrowser.browser import urlmarks, adblock
from qutebrowser.browser.webkit import cookies, cache, history, downloads
from qutebrowser.browser.webkit.network import (qutescheme, proxy,
networkmanager)
from qutebrowser.mainwindow import mainwindow
from qutebrowser.misc import readline, ipc, savemanager, sessions, crashsignal
from qutebrowser.browser import (urlmarks, adblock, history, browsertab,
downloads)
from qutebrowser.browser.network import proxy
from qutebrowser.browser.webkit import cookies, cache
from qutebrowser.browser.webkit.network import networkmanager
from qutebrowser.keyinput import macros
from qutebrowser.mainwindow import mainwindow, prompt
from qutebrowser.misc import (readline, ipc, savemanager, sessions,
crashsignal, earlyinit)
from qutebrowser.misc import utilcmds # pylint: disable=unused-import
from qutebrowser.utils import (log, version, message, utils, qtutils, urlutils,
objreg, usertypes, standarddir, error, debug)
@@ -63,10 +65,6 @@ qApp = None
def run(args):
"""Initialize everything and run the application."""
if args.version:
print(version.version())
sys.exit(usertypes.Exit.ok)
if args.temp_basedir:
args.basedir = tempfile.mkdtemp(prefix='qutebrowser-basedir-')
@@ -80,6 +78,13 @@ def run(args):
qApp.setApplicationVersion(qutebrowser.__version__)
qApp.lastWindowClosed.connect(quitter.on_last_window_closed)
log.init.debug("Initializing directories...")
standarddir.init(args)
if args.version:
print(version.version())
sys.exit(usertypes.Exit.ok)
crash_handler = crashsignal.CrashHandler(
app=qApp, quitter=quitter, args=args, parent=qApp)
crash_handler.activate()
@@ -149,12 +154,13 @@ def init(args, crash_handler):
config_obj = objreg.get('config')
config_obj.style_changed.connect(style.get_stylesheet.cache_clear)
qApp.focusChanged.connect(on_focus_changed)
qApp.focusChanged.connect(message.on_focus_changed)
QDesktopServices.setUrlHandler('http', open_desktopservices_url)
QDesktopServices.setUrlHandler('https', open_desktopservices_url)
QDesktopServices.setUrlHandler('qute', open_desktopservices_url)
macros.init()
log.init.debug("Init done!")
crash_handler.raise_crashdlg()
@@ -181,8 +187,7 @@ def _process_args(args):
try:
config_obj.set('temp', sect, opt, val)
except (configexc.Error, configparser.Error) as e:
message.error('current', "set: {} - {}".format(
e.__class__.__name__, e))
message.error("set: {} - {}".format(e.__class__.__name__, e))
if not args.override_restore:
_load_session(args.session)
@@ -198,6 +203,9 @@ def _process_args(args):
_open_startpage()
_open_quickstart(args)
delta = datetime.datetime.now() - earlyinit.START_TIME
log.init.debug("Init finished after {}s".format(delta.total_seconds()))
def _load_session(name):
"""Load the default session.
@@ -206,21 +214,23 @@ def _load_session(name):
name: The name of the session to load, or None to read state file.
"""
state_config = objreg.get('state-config')
if name is None:
session_manager = objreg.get('session-manager')
if name is None and session_manager.exists('_autosave'):
name = '_autosave'
elif name is None:
try:
name = state_config['general']['session']
except KeyError:
# No session given as argument and none in the session file ->
# start without loading a session
return
session_manager = objreg.get('session-manager')
try:
session_manager.load(name)
except sessions.SessionNotFoundError:
message.error('current', "Session {} not found!".format(name))
message.error("Session {} not found!".format(name))
except sessions.SessionError as e:
message.error('current', "Failed to load session {}: {}".format(
name, e))
message.error("Failed to load session {}: {}".format(name, e))
try:
del state_config['general']['session']
except KeyError:
@@ -272,8 +282,8 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
try:
url = urlutils.fuzzy_url(cmd, cwd, relative=True)
except urlutils.InvalidUrlError as e:
message.error('current', "Error in startup argument '{}': "
"{}".format(cmd, e))
message.error("Error in startup argument '{}': {}".format(
cmd, e))
else:
background = open_target in ['tab-bg', 'tab-bg-silent']
tabbed_browser.tabopen(url, background=background,
@@ -302,8 +312,7 @@ def _open_startpage(win_id=None):
try:
url = urlutils.fuzzy_url(urlstr, do_search=False)
except urlutils.InvalidUrlError as e:
message.error('current', "Error when opening startpage: "
"{}".format(e))
message.error("Error when opening startpage: {}".format(e))
tabbed_browser.tabopen(QUrl('about:blank'))
else:
tabbed_browser.tabopen(url)
@@ -315,8 +324,8 @@ def _open_quickstart(args):
Args:
args: The argparse namespace.
"""
if args.datadir is not None or args.basedir is not None:
# With --datadir or --basedir given, don't open quickstart.
if args.basedir is not None:
# With --basedir given, don't open quickstart.
return
state_config = objreg.get('state-config')
try:
@@ -327,7 +336,7 @@ def _open_quickstart(args):
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
tabbed_browser.tabopen(
QUrl('http://www.qutebrowser.org/quickstart.html'))
QUrl('https://www.qutebrowser.org/quickstart.html'))
state_config['general']['quickstart-done'] = '1'
@@ -339,19 +348,20 @@ def _save_version():
def on_focus_changed(_old, new):
"""Register currently focused main window in the object registry."""
if new is None:
return
if not isinstance(new, QWidget):
log.misc.debug("on_focus_changed called with non-QWidget {!r}".format(
new))
return
if new is None or not isinstance(new, mainwindow.MainWindow):
try:
objreg.delete('last-focused-main-window')
except KeyError:
pass
qApp.restoreOverrideCursor()
else:
objreg.register('last-focused-main-window', new.window(), update=True)
_maybe_hide_mouse_cursor()
window = new.window()
if isinstance(window, mainwindow.MainWindow):
objreg.register('last-focused-main-window', window, update=True)
# A focused window must also be visible, and in this case we should
# consider it as the most recently looked-at window
objreg.register('last-visible-main-window', window, update=True)
def open_desktopservices_url(url):
@@ -362,17 +372,6 @@ def open_desktopservices_url(url):
tabbed_browser.tabopen(url)
@config.change_filter('ui', 'hide-mouse-cursor', function=True)
def _maybe_hide_mouse_cursor():
"""Hide the mouse cursor if it isn't yet and it's configured."""
if config.get('ui', 'hide-mouse-cursor'):
if qApp.overrideCursor() is not None:
return
qApp.setOverrideCursor(QCursor(Qt.BlankCursor))
else:
qApp.restoreOverrideCursor()
def _init_modules(args, crash_handler):
"""Initialize all 'modules' which need to be initialized.
@@ -381,63 +380,76 @@ def _init_modules(args, crash_handler):
crash_handler: The CrashHandler instance.
"""
# pylint: disable=too-many-statements
log.init.debug("Initializing prompts...")
prompt.init()
log.init.debug("Initializing save manager...")
save_manager = savemanager.SaveManager(qApp)
objreg.register('save-manager', save_manager)
save_manager.add_saveable('version', _save_version)
log.init.debug("Initializing network...")
networkmanager.init()
if qtutils.version_check('5.8'):
# Otherwise we can only initialize it for QtWebKit because of crashes
log.init.debug("Initializing proxy...")
proxy.init()
log.init.debug("Initializing readline-bridge...")
readline_bridge = readline.ReadlineBridge()
objreg.register('readline-bridge', readline_bridge)
log.init.debug("Initializing directories...")
standarddir.init(args)
log.init.debug("Initializing config...")
config.init(qApp)
save_manager.init_autosave()
log.init.debug("Initializing web history...")
history.init(qApp)
log.init.debug("Initializing crashlog...")
if not args.no_err_windows:
crash_handler.handle_segfault()
log.init.debug("Initializing sessions...")
sessions.init(qApp)
log.init.debug("Initializing js-bridge...")
js_bridge = qutescheme.JSBridge(qApp)
objreg.register('js-bridge', js_bridge)
log.init.debug("Initializing websettings...")
websettings.init()
websettings.init(args)
log.init.debug("Initializing adblock...")
host_blocker = adblock.HostBlocker()
host_blocker.read_hosts()
objreg.register('host-blocker', host_blocker)
log.init.debug("Initializing quickmarks...")
quickmark_manager = urlmarks.QuickmarkManager(qApp)
objreg.register('quickmark-manager', quickmark_manager)
log.init.debug("Initializing bookmarks...")
bookmark_manager = urlmarks.BookmarkManager(qApp)
objreg.register('bookmark-manager', bookmark_manager)
log.init.debug("Initializing proxy...")
proxy.init()
log.init.debug("Initializing cookies...")
cookie_jar = cookies.CookieJar(qApp)
ram_cookie_jar = cookies.RAMCookieJar(qApp)
objreg.register('cookie-jar', cookie_jar)
objreg.register('ram-cookie-jar', ram_cookie_jar)
log.init.debug("Initializing cache...")
diskcache = cache.DiskCache(standarddir.cache(), parent=qApp)
objreg.register('cache', diskcache)
log.init.debug("Initializing completions...")
completionmodels.init()
log.init.debug("Misc initialization...")
if config.get('ui', 'hide-wayland-decoration'):
os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1'
else:
os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None)
_maybe_hide_mouse_cursor()
objreg.get('config').changed.connect(_maybe_hide_mouse_cursor)
temp_downloads = downloads.TempDownloadManager(qApp)
objreg.register('temporary-downloads', temp_downloads)
# Init backend-specific stuff
browsertab.init()
def _init_late_modules(args):
@@ -525,7 +537,7 @@ class Quitter:
if not os.path.isdir(cwd):
# Probably running from a python egg. Let's fallback to
# cwd=None and see if that works out.
# See https://github.com/The-Compiler/qutebrowser/issues/323
# See https://github.com/qutebrowser/qutebrowser/issues/323
cwd = None
# Add all open pages so they get reopened.
@@ -551,8 +563,9 @@ class Quitter:
argdict['session'] = session
argdict['override_restore'] = False
# Ensure :restart works with --temp-basedir
argdict['temp_basedir'] = False
argdict['temp_basedir_restarted'] = True
if self._args.temp_basedir:
argdict['temp_basedir'] = False
argdict['temp_basedir_restarted'] = True
# Dump the data
data = json.dumps(argdict)
@@ -644,13 +657,7 @@ class Quitter:
session_manager.save(sessions.default, last_window=last_window,
load_next_time=True)
deferrer = False
for win_id in objreg.window_registry:
prompter = objreg.get('prompter', None, scope='window',
window=win_id)
if prompter is not None and prompter.shutdown():
deferrer = True
if deferrer:
if prompt.prompt_queue.shutdown():
# If shutdown was called while we were asking a question, we're in
# a still sub-eventloop (which gets quit now) and not in the main
# one.
@@ -699,9 +706,7 @@ class Quitter:
e, self._args, "Error while saving!",
pre_text="Error while saving {}".format(key))
# Disable storage so removing tempdir will work
QWebSettings.setIconDatabasePath('')
QWebSettings.setOfflineWebApplicationCachePath('')
QWebSettings.globalSettings().setLocalStoragePath('')
websettings.shutdown()
# Re-enable faulthandler to stdout, then remove crash log
log.destroy.debug("Deactivating crash log...")
objreg.get('crash-handler').destroy_crashlogfile()
@@ -711,13 +716,14 @@ class Quitter:
atexit.register(shutil.rmtree, self._args.basedir,
ignore_errors=True)
# Delete temp download dir
objreg.get('temporary-downloads').cleanup()
downloads.temp_download_manager.cleanup()
# If we don't kill our custom handler here we might get segfaults
log.destroy.debug("Deactivating message handler...")
qInstallMessageHandler(None)
# Now we can hopefully quit without segfaults
log.destroy.debug("Deferring QApplication::exit...")
objreg.get('signal-handler').deactivate()
objreg.get('session-manager').delete_autosave()
# We use a singleshot timer to exit here to minimize the likelihood of
# segfaults.
QTimer.singleShot(0, functools.partial(qApp.exit, status))
@@ -739,6 +745,7 @@ class Application(QApplication):
Attributes:
_args: ArgumentParser instance.
_last_focus_object: The last focused object's repr.
"""
new_window = pyqtSignal(mainwindow.MainWindow)
@@ -749,6 +756,8 @@ class Application(QApplication):
Args:
Argument namespace from argparse.
"""
self._last_focus_object = None
qt_args = qtutils.get_args(args)
log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args))
super().__init__(qt_args)
@@ -765,7 +774,10 @@ class Application(QApplication):
@pyqtSlot(QObject)
def on_focus_object_changed(self, obj):
"""Log when the focus object changed."""
log.misc.debug("Focus object changed: {!r}".format(obj))
output = repr(obj)
if self._last_focus_object != output:
log.misc.debug("Focus object changed: {}".format(output))
self._last_focus_object = output
def __repr__(self):
return utils.get_repr(self)

View File

@@ -26,9 +26,10 @@ import posixpath
import zipfile
import fnmatch
from qutebrowser.browser import downloads
from qutebrowser.config import config
from qutebrowser.utils import objreg, standarddir, log, message, usertypes
from qutebrowser.commands import cmdutils, cmdexc
from qutebrowser.utils import objreg, standarddir, log, message
from qutebrowser.commands import cmdutils
def guess_zip_filename(zf):
@@ -112,17 +113,11 @@ class HostBlocker:
self._done_count = 0
data_dir = standarddir.data()
if data_dir is None:
self._local_hosts_file = None
else:
self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
self.on_config_changed()
config_dir = standarddir.config()
if config_dir is None:
self._config_hosts_file = None
else:
self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')
self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')
objreg.get('config').changed.connect(self.on_config_changed)
@@ -145,7 +140,7 @@ class HostBlocker:
Return:
True if a read was attempted, False otherwise
"""
if filename is None or not os.path.exists(filename):
if not os.path.exists(filename):
return False
try:
@@ -161,9 +156,6 @@ class HostBlocker:
"""Read hosts from the existing blocked-hosts file."""
self._blocked_hosts = set()
if self._local_hosts_file is None:
return
self._read_hosts_file(self._config_hosts_file,
self._config_blocked_hosts)
@@ -174,26 +166,22 @@ class HostBlocker:
args = objreg.get('args')
if (config.get('content', 'host-block-lists') is not None and
args.basedir is None):
message.info('current',
"Run :adblock-update to get adblock lists.")
message.info("Run :adblock-update to get adblock lists.")
@cmdutils.register(instance='host-blocker')
@cmdutils.argument('win_id', win_id=True)
def adblock_update(self, win_id):
def adblock_update(self):
"""Update the adblock block lists.
This updates ~/.local/share/qutebrowser/blocked-hosts with downloaded
host lists and re-reads ~/.config/qutebrowser/blocked-hosts.
This updates `~/.local/share/qutebrowser/blocked-hosts` with downloaded
host lists and re-reads `~/.config/qutebrowser/blocked-hosts`.
"""
self._read_hosts_file(self._config_hosts_file,
self._config_blocked_hosts)
if self._local_hosts_file is None:
raise cmdexc.CommandError("No data storage is configured!")
self._blocked_hosts = set()
self._done_count = 0
urls = config.get('content', 'host-block-lists')
download_manager = objreg.get('download-manager', scope='window',
window='last-focused')
download_manager = objreg.get('qtnetwork-download-manager',
scope='window', window='last-focused')
if urls is None:
return
for url in urls:
@@ -201,8 +189,8 @@ class HostBlocker:
try:
fileobj = open(url.path(), 'rb')
except OSError as e:
message.error(win_id, "adblock: Error while reading {}: "
"{}".format(url.path(), e.strerror))
message.error("adblock: Error while reading {}: {}".format(
url.path(), e.strerror))
continue
download = FakeDownload(fileobj)
self._in_progress.append(download)
@@ -210,7 +198,7 @@ class HostBlocker:
else:
fobj = io.BytesIO()
fobj.name = 'adblock: ' + url.host()
target = usertypes.FileObjDownloadTarget(fobj)
target = downloads.FileObjDownloadTarget(fobj)
download = download_manager.get(url, target=target,
auto_remove=True)
self._in_progress.append(download)
@@ -231,9 +219,9 @@ class HostBlocker:
try:
f = get_fileobj(byte_io)
except (OSError, UnicodeDecodeError, zipfile.BadZipFile,
zipfile.LargeZipFile) as e:
message.error('current', "adblock: Error while reading {}: {} - "
"{}".format(byte_io.name, e.__class__.__name__, e))
zipfile.LargeZipFile, LookupError) as e:
message.error("adblock: Error while reading {}: {} - {}".format(
byte_io.name, e.__class__.__name__, e))
return
for line in f:
line_count += 1
@@ -261,7 +249,7 @@ class HostBlocker:
self._blocked_hosts.add(host)
log.misc.debug("{}: read {} lines".format(byte_io.name, line_count))
if error_count > 0:
message.error('current', "adblock: {} read errors for {}".format(
message.error("adblock: {} read errors for {}".format(
error_count, byte_io.name))
def on_lists_downloaded(self):
@@ -269,14 +257,14 @@ class HostBlocker:
with open(self._local_hosts_file, 'w', encoding='utf-8') as f:
for host in sorted(self._blocked_hosts):
f.write(host + '\n')
message.info('current', "adblock: Read {} hosts from {} sources."
.format(len(self._blocked_hosts), self._done_count))
message.info("adblock: Read {} hosts from {} sources.".format(
len(self._blocked_hosts), self._done_count))
@config.change_filter('content', 'host-block-lists')
def on_config_changed(self):
"""Update files when the config changed."""
urls = config.get('content', 'host-block-lists')
if urls is None and self._local_hosts_file is not None:
if urls is None:
try:
os.remove(self._local_hosts_file)
except FileNotFoundError:

View File

@@ -21,13 +21,15 @@
import itertools
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QPoint
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QLayout
from PyQt5.QtWidgets import QWidget, QApplication
from qutebrowser.keyinput import modeman
from qutebrowser.config import config
from qutebrowser.utils import utils, objreg, usertypes, message, log, qtutils
from qutebrowser.utils import utils, objreg, usertypes, log, qtutils
from qutebrowser.misc import miscwidgets, objects
from qutebrowser.browser import mouse, hints
tab_id_gen = itertools.count(0)
@@ -43,7 +45,7 @@ def create(win_id, parent=None):
# Importing modules here so we don't depend on QtWebEngine without the
# argument and to avoid circular imports.
mode_manager = modeman.instance(win_id)
if objreg.get('args').backend == 'webengine':
if objects.backend == usertypes.Backend.QtWebEngine:
from qutebrowser.browser.webengine import webenginetab
tab_class = webenginetab.WebEngineTab
else:
@@ -52,38 +54,33 @@ def create(win_id, parent=None):
return tab_class(win_id=win_id, mode_manager=mode_manager, parent=parent)
def init():
"""Initialize backend-specific modules."""
if objects.backend == usertypes.Backend.QtWebEngine:
from qutebrowser.browser.webengine import webenginetab
webenginetab.init()
else:
from qutebrowser.browser.webkit import webkittab
webkittab.init()
class WebTabError(Exception):
"""Base class for various errors."""
class WrapperLayout(QLayout):
class UnsupportedOperationError(WebTabError):
"""A Qt layout which simply wraps a single widget.
"""Raised when an operation is not supported with the given backend."""
This is used so the widget is hidden behind a AbstractTab API and can't
easily be accidentally accessed.
"""
def __init__(self, widget, parent=None):
super().__init__(parent)
self._widget = widget
def addItem(self, _widget):
raise AssertionError("Should never be called!")
def sizeHint(self):
return self._widget.sizeHint()
def itemAt(self, _index): # pragma: no cover
# For some reason this sometimes gets called by Qt.
return None
def takeAt(self, _index):
raise AssertionError("Should never be called!")
def setGeometry(self, rect):
self._widget.setGeometry(rect)
TerminationStatus = usertypes.enum('TerminationStatus', [
'normal',
'abnormal', # non-zero exit status
'crashed', # e.g. segfault
'killed',
'unknown',
])
class TabData:
@@ -95,14 +92,31 @@ class TabData:
load.
inspector: The QWebInspector used for this webview.
viewing_source: Set if we're currently showing a source view.
override_target: Override for open_target for fake clicks (like hints).
Only used for QtWebKit.
"""
__slots__ = ['keep_icon', 'viewing_source', 'inspector']
def __init__(self):
self.keep_icon = False
self.viewing_source = False
self.inspector = None
self.override_target = None
class AbstractAction:
"""Attribute of AbstractTab for Qt WebActions."""
def __init__(self):
self._widget = None
def exit_fullscreen(self):
"""Exit the fullscreen mode."""
raise NotImplementedError
def save_page(self):
"""Save the current page."""
raise NotImplementedError
class AbstractPrinting:
@@ -118,10 +132,20 @@ class AbstractPrinting:
def check_printer_support(self):
raise NotImplementedError
def check_preview_support(self):
raise NotImplementedError
def to_pdf(self, filename):
raise NotImplementedError
def to_printer(self, printer):
def to_printer(self, printer, callback=None):
"""Print the tab.
Args:
printer: The QPrinter to print to.
callback: Called with a boolean
(True if printing succeeded, False otherwise)
"""
raise NotImplementedError
@@ -193,7 +217,7 @@ class AbstractZoom(QObject):
# # FIXME:qtwebengine is this needed?
# # For some reason, this signal doesn't get disconnected automatically
# # when the WebView is destroyed on older PyQt versions.
# # See https://github.com/The-Compiler/qutebrowser/issues/390
# # See https://github.com/qutebrowser/qutebrowser/issues/390
# self.destroyed.connect(functools.partial(
# cfg.changed.disconnect, self.init_neighborlist))
@@ -226,6 +250,9 @@ class AbstractZoom(QObject):
self.set_factor(float(level) / 100, fuzzyval=False)
return level
def _set_factor_internal(self, factor):
raise NotImplementedError
def set_factor(self, factor, *, fuzzyval=True):
"""Zoom to a given zoom factor.
@@ -247,19 +274,6 @@ class AbstractZoom(QObject):
default_zoom = config.get('ui', 'default-zoom')
self._set_factor_internal(float(default_zoom) / 100)
@pyqtSlot(QPoint)
def _on_mouse_wheel_zoom(self, delta):
"""Handle zooming via mousewheel requested by the web view."""
divider = config.get('input', 'mouse-zoom-divider')
factor = self.factor() + delta.y() / divider
if factor < 0:
return
perc = int(100 * factor)
message.info(self._win_id, "Zoom level: {}%".format(perc))
self._neighborlist.fuzzyval = perc
self._set_factor_internal(factor)
self._default_zoom_changed = True
class AbstractCaret(QObject):
@@ -351,6 +365,12 @@ class AbstractScroller(QObject):
super().__init__(parent)
self._tab = tab
self._widget = None
self.perc_changed.connect(self._log_scroll_pos_change)
@pyqtSlot()
def _log_scroll_pos_change(self):
log.webview.vdebug("Scroll position changed to {}".format(
self.pos_px()))
def _init_widget(self, widget):
self._widget = widget
@@ -446,6 +466,55 @@ class AbstractHistory:
raise NotImplementedError
class AbstractElements:
"""Finding and handling of elements on the page."""
def __init__(self, tab):
self._widget = None
self._tab = tab
def find_css(self, selector, callback, *, only_visible=False):
"""Find all HTML elements matching a given selector async.
Args:
callback: The callback to be called when the search finished.
selector: The CSS selector to search for.
only_visible: Only show elements which are visible on screen.
"""
raise NotImplementedError
def find_id(self, elem_id, callback):
"""Find the HTML element with the given ID async.
Args:
callback: The callback to be called when the search finished.
elem_id: The ID to search for.
"""
raise NotImplementedError
def find_focused(self, callback):
"""Find the focused element on the page async.
Args:
callback: The callback to be called when the search finished.
Called with a WebEngineElement or None.
"""
raise NotImplementedError
def find_at_pos(self, pos, callback):
"""Find the element at the given position async.
This is also called "hit test" elsewhere.
Args:
pos: The QPoint to get the element for.
callback: The callback to be called when the search finished.
Called with a WebEngineElement or None.
"""
raise NotImplementedError
class AbstractTab(QWidget):
"""A wrapper over the given widget to hide its API and expose another one.
@@ -469,6 +538,13 @@ class AbstractTab(QWidget):
new_tab_requested: Emitted when a new tab should be opened with the
given URL.
load_status_changed: The loading status changed
fullscreen_requested: Fullscreen display was requested by the page.
arg: True if fullscreen should be turned on,
False if it should be turned off.
renderer_process_terminated: Emitted when the underlying renderer
process terminated.
arg 0: A TerminationStatus member.
arg 1: The exit code.
"""
window_close_requested = pyqtSignal()
@@ -482,8 +558,12 @@ class AbstractTab(QWidget):
new_tab_requested = pyqtSignal(QUrl)
url_changed = pyqtSignal(QUrl)
shutting_down = pyqtSignal()
contents_size_changed = pyqtSignal(QSizeF)
add_history_item = pyqtSignal(QUrl, QUrl, str) # url, requested url, title
fullscreen_requested = pyqtSignal(bool)
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
def __init__(self, win_id, parent=None):
def __init__(self, win_id, mode_manager, parent=None):
self.win_id = win_id
self.tab_id = next(tab_id_gen)
super().__init__(parent)
@@ -496,32 +576,49 @@ class AbstractTab(QWidget):
# self.history = AbstractHistory(self)
# self.scroller = AbstractScroller(self, parent=self)
# self.caret = AbstractCaret(win_id=win_id, tab=self, mode_manager=...,
# parent=self)
# self.caret = AbstractCaret(win_id=win_id, tab=self,
# mode_manager=mode_manager, parent=self)
# self.zoom = AbstractZoom(win_id=win_id)
# self.search = AbstractSearch(parent=self)
# self.printing = AbstractPrinting()
# self.elements = AbstractElements(self)
# self.action = AbstractAction()
self.data = TabData()
self._layout = None
self._layout = miscwidgets.WrapperLayout(self)
self._widget = None
self._progress = 0
self._has_ssl_errors = False
self._mode_manager = mode_manager
self._load_status = usertypes.LoadStatus.none
self._mouse_event_filter = mouse.MouseEventFilter(
self, parent=self)
self.backend = None
# FIXME:qtwebengine Should this be public api via self.hints?
# Also, should we get it out of objreg?
hintmanager = hints.HintManager(win_id, self.tab_id, parent=self)
objreg.register('hintmanager', hintmanager, scope='tab',
window=self.win_id, tab=self.tab_id)
def _set_widget(self, widget):
# pylint: disable=protected-access
self._layout = WrapperLayout(widget, self)
self._widget = widget
self._layout.wrap(self, widget)
self.history._history = widget.history()
self.scroller._init_widget(widget)
self.caret._widget = widget
self.zoom._widget = widget
self.search._widget = widget
self.printing._widget = widget
widget.mouse_wheel_zoom.connect(self.zoom._on_mouse_wheel_zoom)
widget.setParent(self)
self.setFocusProxy(widget)
self.action._widget = widget
self.elements._widget = widget
self._install_event_filter()
self.zoom.set_default()
def _install_event_filter(self):
raise NotImplementedError
def _set_load_status(self, val):
"""Setter for load_status."""
@@ -531,6 +628,25 @@ class AbstractTab(QWidget):
self._load_status = val
self.load_status_changed.emit(val.name)
def event_target(self):
"""Return the widget events should be sent to."""
raise NotImplementedError
def send_event(self, evt):
"""Send the given event to the underlying widget.
The event will be sent via QApplication.postEvent.
Note that a posted event may not be re-used in any way!
"""
# This only gives us some mild protection against re-using events, but
# it's certainly better than a segfault.
if getattr(evt, 'posted', False):
raise AssertionError("Can't re-use an event which was already "
"posted!")
recipient = self.event_target()
evt.posted = True
QApplication.postEvent(recipient, evt)
@pyqtSlot(QUrl)
def _on_url_changed(self, url):
"""Update title when URL has changed and no title is available."""
@@ -546,14 +662,36 @@ class AbstractTab(QWidget):
self._set_load_status(usertypes.LoadStatus.loading)
self.load_started.emit()
def _handle_auto_insert_mode(self, ok):
"""Handle auto-insert-mode after loading finished."""
if not config.get('input', 'auto-insert-mode') or not ok:
return
cur_mode = self._mode_manager.mode
if cur_mode == usertypes.KeyMode.insert:
return
def _auto_insert_mode_cb(elem):
"""Called from JS after finding the focused element."""
if elem is None:
log.webview.debug("No focused element!")
return
if elem.is_editable():
modeman.enter(self.win_id, usertypes.KeyMode.insert,
'load finished', only_if_normal=True)
self.elements.find_focused(_auto_insert_mode_cb)
@pyqtSlot(bool)
def _on_load_finished(self, ok):
sess_manager = objreg.get('session-manager')
sess_manager.save_autosave()
if ok and not self._has_ssl_errors:
if self.url().scheme() == 'https':
self._set_load_status(usertypes.LoadStatus.success_https)
else:
self._set_load_status(usertypes.LoadStatus.success)
elif ok:
self._set_load_status(usertypes.LoadStatus.warn)
else:
@@ -561,6 +699,12 @@ class AbstractTab(QWidget):
self.load_finished.emit(ok)
if not self.title():
self.title_changed.emit(self.url().toDisplayString())
self._handle_auto_insert_mode(ok)
@pyqtSlot()
def _on_history_trigger(self):
"""Emit add_history_item when triggered by backend-specific signal."""
raise NotImplementedError
@pyqtSlot(int)
def _on_load_progress(self, perc):
@@ -571,7 +715,7 @@ class AbstractTab(QWidget):
def _on_ssl_errors(self):
self._has_ssl_errors = True
def url(self):
def url(self, requested=False):
raise NotImplementedError
def progress(self):
@@ -604,19 +748,17 @@ class AbstractTab(QWidget):
"""
raise NotImplementedError
def run_js_async(self, code, callback=None):
def run_js_async(self, code, callback=None, *, world=None):
"""Run javascript async.
The given callback will be called with the result when running JS is
complete.
"""
raise NotImplementedError
def run_js_blocking(self, code):
"""Run javascript and block.
This returns the result to the caller. Its use should be avoided when
possible as it runs a local event loop for QtWebEngine.
Args:
code: The javascript code to run.
callback: The callback to call with the result, or None.
world: A world ID (int or usertypes.JsWorld member) to run the JS
in the main world or in another isolated world.
"""
raise NotImplementedError
@@ -632,6 +774,22 @@ class AbstractTab(QWidget):
def set_html(self, html, base_url):
raise NotImplementedError
def networkaccessmanager(self):
"""Get the QNetworkAccessManager for this tab.
This is only implemented for QtWebKit.
For QtWebEngine, always returns None.
"""
raise NotImplementedError
def user_agent(self):
"""Get the user agent for this tab.
This is only implemented for QtWebKit.
For QtWebEngine, always returns None.
"""
raise NotImplementedError
def __repr__(self):
try:
url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@ import sip
from PyQt5.QtCore import pyqtSlot, QSize, Qt, QTimer
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
from qutebrowser.browser.webkit import downloads
from qutebrowser.browser import downloads
from qutebrowser.config import style
from qutebrowser.utils import qtutils, utils, objreg
@@ -39,8 +39,8 @@ def update_geometry(obj):
Here we check if obj ("self") was deleted and just ignore the event if so.
Original bug: https://github.com/The-Compiler/qutebrowser/issues/167
Workaround bug: https://github.com/The-Compiler/qutebrowser/issues/171
Original bug: https://github.com/qutebrowser/qutebrowser/issues/167
Workaround bug: https://github.com/qutebrowser/qutebrowser/issues/171
"""
def _update_geometry():
"""Actually update the geometry if the object still exists."""
@@ -83,7 +83,7 @@ class DownloadView(QListView):
self.setFlow(QListView.LeftToRight)
self.setSpacing(1)
self._menu = None
model = objreg.get('download-manager', scope='window', window=win_id)
model = objreg.get('download-model', scope='window', window=win_id)
model.rowsInserted.connect(functools.partial(update_geometry, self))
model.rowsRemoved.connect(functools.partial(update_geometry, self))
model.dataChanged.connect(functools.partial(update_geometry, self))
@@ -113,7 +113,7 @@ class DownloadView(QListView):
item = self.model().data(index, downloads.ModelRole.item)
if item.done and item.successful:
item.open_file()
self.model().remove_item(item)
item.remove()
def _get_menu_actions(self, item):
"""Get the available context menu actions for a given DownloadItem.
@@ -135,8 +135,7 @@ class DownloadView(QListView):
actions.append(("Open", item.open_file))
else:
actions.append(("Retry", item.retry))
actions.append(("Remove",
functools.partial(model.remove_item, item)))
actions.append(("Remove", item.remove))
else:
actions.append(("Cancel", item.cancel))
if model.can_clear():

File diff suppressed because it is too large Load Diff

View File

@@ -22,13 +22,13 @@
import time
import collections
from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from PyQt5.QtWebKit import QWebHistoryInterface
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject
from qutebrowser.commands import cmdutils
from qutebrowser.utils import utils, objreg, standarddir, log, qtutils
from qutebrowser.utils import (utils, objreg, standarddir, log, qtutils,
usertypes, message)
from qutebrowser.config import config
from qutebrowser.misc import lineparser
from qutebrowser.misc import lineparser, objects
class Entry:
@@ -88,12 +88,8 @@ class Entry:
if not url.isValid():
raise ValueError("Invalid URL: {}".format(url.errorString()))
if atime.startswith('\0'):
log.init.debug(
"Removing NUL bytes from entry {!r} - see "
"https://github.com/The-Compiler/qutebrowser/issues/"
"670".format(data))
atime = atime.lstrip('\0')
# https://github.com/qutebrowser/qutebrowser/issues/670
atime = atime.lstrip('\0')
if '-' in atime:
atime, flags = atime.split('-')
@@ -108,34 +104,6 @@ class Entry:
return cls(atime, url, title, redirect=redirect)
class WebHistoryInterface(QWebHistoryInterface):
"""Glue code between WebHistory and Qt's QWebHistoryInterface.
Attributes:
_history: The WebHistory object.
"""
def __init__(self, webhistory, parent=None):
super().__init__(parent)
self._history = webhistory
def addHistoryEntry(self, url_string):
"""Required for a QWebHistoryInterface impl, obsoleted by add_url."""
pass
def historyContains(self, url_string):
"""Called by WebKit to determine if a URL is contained in the history.
Args:
url_string: The URL (as string) to check for.
Return:
True if the url is in the history, False otherwise.
"""
return url_string in self._history.history_dict
class WebHistory(QObject):
"""The global history of visited pages.
@@ -157,7 +125,6 @@ class WebHistory(QObject):
Attributes:
history_dict: An OrderedDict of URLs read from the on-disk history.
_hist_dir: The directory to store the history in
_lineparser: The AppendLineParser used to save the history.
_new_history: A list of Entry items of the current session.
_saved_count: How many HistoryEntries have been written to disk.
@@ -185,7 +152,6 @@ class WebHistory(QObject):
super().__init__(parent)
self._initial_read_started = False
self._initial_read_done = False
self._hist_dir = hist_dir
self._lineparser = lineparser.AppendLineParser(hist_dir, hist_name,
parent=self)
self.history_dict = collections.OrderedDict()
@@ -211,12 +177,6 @@ class WebHistory(QObject):
return
self._initial_read_started = True
if self._hist_dir is None:
self._initial_read_done = True
self.async_read_done.emit()
assert not self._temp_history
return
with self._lineparser.open():
for line in self._lineparser:
yield
@@ -270,13 +230,23 @@ class WebHistory(QObject):
self._saved_count = len(self._new_history)
@cmdutils.register(name='history-clear', instance='web-history')
def clear(self):
def clear(self, force=False):
"""Clear all browsing history.
Note this only clears the global history
(e.g. `~/.local/share/qutebrowser/history` on Linux) but not cookies,
the back/forward history of a tab, cache or other persistent data.
Args:
force: Don't ask for confirmation.
"""
if force:
self._do_clear()
else:
message.confirm_async(self._do_clear, title="Clear all browsing "
"history?")
def _do_clear(self):
self._lineparser.clear()
self.history_dict.clear()
self._temp_history.clear()
@@ -284,8 +254,19 @@ class WebHistory(QObject):
self._saved_count = 0
self.cleared.emit()
@pyqtSlot(QUrl, QUrl, str)
def add_from_tab(self, url, requested_url, title):
"""Add a new history entry as slot, called from a BrowserTab."""
no_formatting = QUrl.UrlFormattingOption(0)
if (requested_url.isValid() and
not requested_url.matches(url, no_formatting)):
# If the url of the page is different than the url of the link
# originally clicked, save them both.
self.add_url(requested_url, title, redirect=True)
self.add_url(url, title)
def add_url(self, url, title="", *, redirect=False, atime=None):
"""Called by WebKit when a URL should be added to the history.
"""Called via add_from_tab when a URL should be added to the history.
Args:
url: A url (as QUrl) to add to the history.
@@ -295,6 +276,10 @@ class WebHistory(QObject):
"""
if config.get('general', 'private-browsing'):
return
if not url.isValid():
log.misc.warning("Ignoring invalid URL being added to history")
return
if atime is None:
atime = time.time()
entry = Entry(atime, url, title, redirect=redirect)
@@ -318,5 +303,6 @@ def init(parent=None):
parent=parent)
objreg.register('web-history', history)
interface = WebHistoryInterface(history, parent=history)
QWebHistoryInterface.setDefaultInterface(interface)
if objects.backend == usertypes.Backend.QtWebKit:
from qutebrowser.browser.webkit import webkithistory
webkithistory.init(history)

View File

@@ -17,31 +17,53 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Customized QWebInspector."""
"""Base class for a QtWebKit/QtWebEngine web inspector."""
import base64
import binascii
from PyQt5.QtWebKitWidgets import QWebInspector
from PyQt5.QtWidgets import QWidget
from qutebrowser.utils import log, objreg
from qutebrowser.utils import log, objreg, usertypes
from qutebrowser.misc import miscwidgets, objects
class WebInspector(QWebInspector):
def create(parent=None):
"""Get a WebKitInspector/WebEngineInspector.
Args:
parent: The Qt parent to set.
"""
# Importing modules here so we don't depend on QtWebEngine without the
# argument and to avoid circular imports.
if objects.backend == usertypes.Backend.QtWebEngine:
from qutebrowser.browser.webengine import webengineinspector
return webengineinspector.WebEngineInspector(parent)
else:
from qutebrowser.browser.webkit import webkitinspector
return webkitinspector.WebKitInspector(parent)
class WebInspectorError(Exception):
"""Raised when the inspector could not be initialized."""
pass
class AbstractWebInspector(QWidget):
"""A customized WebInspector which stores its geometry."""
def __init__(self, parent=None):
super().__init__(parent)
self._widget = None
self._layout = miscwidgets.WrapperLayout(self)
self._load_state_geometry()
def closeEvent(self, e):
"""Save the geometry when closed."""
state_config = objreg.get('state-config')
data = bytes(self.saveGeometry())
geom = base64.b64encode(data).decode('ASCII')
state_config['geometry']['inspector'] = geom
super().closeEvent(e)
def _set_widget(self, widget):
self._widget = widget
self._layout.wrap(self, widget)
def _load_state_geometry(self):
"""Load the geometry from the state file."""
@@ -59,3 +81,21 @@ class WebInspector(QWebInspector):
ok = self.restoreGeometry(geom)
if not ok:
log.init.warning("Error while loading geometry.")
def closeEvent(self, e):
"""Save the geometry when closed."""
state_config = objreg.get('state-config')
data = bytes(self.saveGeometry())
geom = base64.b64encode(data).decode('ASCII')
state_config['geometry']['inspector'] = geom
super().closeEvent(e)
def inspect(self, page):
"""Inspect the given QWeb(Engine)Page."""
raise NotImplementedError
def toggle(self, page):
if self._widget.isVisible():
self.hide()
else:
self.inspect(page)

View File

@@ -0,0 +1,216 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Mouse handling for a browser tab."""
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes
from qutebrowser.keyinput import modeman
from PyQt5.QtCore import QObject, QEvent, Qt, QTimer
class ChildEventFilter(QObject):
"""An event filter re-adding MouseEventFilter on ChildEvent.
This is needed because QtWebEngine likes to randomly change its
focusProxy...
FIXME:qtwebengine Add a test for this happening
Attributes:
_filter: The event filter to install.
_widget: The widget expected to send out childEvents.
"""
def __init__(self, eventfilter, widget, parent=None):
super().__init__(parent)
self._filter = eventfilter
assert widget is not None
self._widget = widget
def eventFilter(self, obj, event):
"""Act on ChildAdded events."""
if event.type() == QEvent.ChildAdded:
child = event.child()
log.mouse.debug("{} got new child {}, installing filter".format(
obj, child))
assert obj is self._widget
child.installEventFilter(self._filter)
return False
class MouseEventFilter(QObject):
"""Handle mouse events on a tab.
Attributes:
_tab: The browsertab object this filter is installed on.
_handlers: A dict of handler functions for the handled events.
_ignore_wheel_event: Whether to ignore the next wheelEvent.
_check_insertmode_on_release: Whether an insertmode check should be
done when the mouse is released.
"""
def __init__(self, tab, *, parent=None):
super().__init__(parent)
self._tab = tab
self._handlers = {
QEvent.MouseButtonPress: self._handle_mouse_press,
QEvent.MouseButtonRelease: self._handle_mouse_release,
QEvent.Wheel: self._handle_wheel,
QEvent.ContextMenu: self._handle_context_menu,
}
self._ignore_wheel_event = False
self._check_insertmode_on_release = False
def _handle_mouse_press(self, e):
"""Handle pressing of a mouse button."""
is_rocker_gesture = (config.get('input', 'rocker-gestures') and
e.buttons() == Qt.LeftButton | Qt.RightButton)
if e.button() in [Qt.XButton1, Qt.XButton2] or is_rocker_gesture:
self._mousepress_backforward(e)
return True
self._ignore_wheel_event = True
if e.button() != Qt.NoButton:
self._tab.elements.find_at_pos(e.pos(),
self._mousepress_insertmode_cb)
return False
def _handle_mouse_release(self, _e):
"""Handle releasing of a mouse button."""
# We want to make sure we check the focus element after the WebView is
# updated completely.
QTimer.singleShot(0, self._mouserelease_insertmode)
return False
def _handle_wheel(self, e):
"""Zoom on Ctrl-Mousewheel.
Args:
e: The QWheelEvent.
"""
if self._ignore_wheel_event:
# See https://github.com/qutebrowser/qutebrowser/issues/395
self._ignore_wheel_event = False
return True
if e.modifiers() & Qt.ControlModifier:
divider = config.get('input', 'mouse-zoom-divider')
if divider == 0:
return False
factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider)
if factor < 0:
return False
perc = int(100 * factor)
message.info("Zoom level: {}%".format(perc), replace=True)
self._tab.zoom.set_factor(factor)
elif e.modifiers() & Qt.ShiftModifier:
if e.angleDelta().y() > 0:
self._tab.scroller.left()
else:
self._tab.scroller.right()
return True
return False
def _handle_context_menu(self, _e):
"""Suppress context menus if rocker gestures are turned on."""
return config.get('input', 'rocker-gestures')
def _mousepress_insertmode_cb(self, elem):
"""Check if the clicked element is editable."""
if elem is None:
# Something didn't work out, let's find the focus element after
# a mouse release.
log.mouse.debug("Got None element, scheduling check on "
"mouse release")
self._check_insertmode_on_release = True
return
if elem.is_editable():
log.mouse.debug("Clicked editable element!")
modeman.enter(self._tab.win_id, usertypes.KeyMode.insert,
'click', only_if_normal=True)
else:
log.mouse.debug("Clicked non-editable element!")
if config.get('input', 'auto-leave-insert-mode'):
modeman.leave(self._tab.win_id, usertypes.KeyMode.insert,
'click', maybe=True)
def _mouserelease_insertmode(self):
"""If we have an insertmode check scheduled, handle it."""
if not self._check_insertmode_on_release:
return
self._check_insertmode_on_release = False
def mouserelease_insertmode_cb(elem):
"""Callback which gets called from JS."""
if elem is None:
log.mouse.debug("Element vanished!")
return
if elem.is_editable():
log.mouse.debug("Clicked editable element (delayed)!")
modeman.enter(self._tab.win_id, usertypes.KeyMode.insert,
'click-delayed', only_if_normal=True)
else:
log.mouse.debug("Clicked non-editable element (delayed)!")
if config.get('input', 'auto-leave-insert-mode'):
modeman.leave(self._tab.win_id, usertypes.KeyMode.insert,
'click-delayed', maybe=True)
self._tab.elements.find_focused(mouserelease_insertmode_cb)
def _mousepress_backforward(self, e):
"""Handle back/forward mouse button presses.
Args:
e: The QMouseEvent.
"""
if e.button() in [Qt.XButton1, Qt.LeftButton]:
# Back button on mice which have it, or rocker gesture
if self._tab.history.can_go_back():
self._tab.history.back()
else:
message.error("At beginning of history.")
elif e.button() in [Qt.XButton2, Qt.RightButton]:
# Forward button on mice which have it, or rocker gesture
if self._tab.history.can_go_forward():
self._tab.history.forward()
else:
message.error("At end of history.")
def eventFilter(self, obj, event):
"""Filter events going to a QWeb(Engine)View."""
evtype = event.type()
if evtype not in self._handlers:
return False
if obj is not self._tab.event_target():
log.mouse.debug("Ignoring {} to {}".format(
event.__class__.__name__, obj))
return False
return self._handlers[evtype](event)

View File

@@ -0,0 +1,147 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Implementation of :navigate."""
import posixpath
from qutebrowser.browser import webelem
from qutebrowser.config import config
from qutebrowser.utils import objreg, urlutils, log, message, qtutils
class Error(Exception):
"""Raised when the navigation can't be done."""
def incdec(url, count, inc_or_dec):
"""Helper method for :navigate when `where' is increment/decrement.
Args:
url: The current url.
count: How much to increment or decrement by.
inc_or_dec: Either 'increment' or 'decrement'.
tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
segments = set(config.get('general', 'url-incdec-segments'))
try:
new_url = urlutils.incdec_number(url, inc_or_dec, count,
segments=segments)
except urlutils.IncDecError as error:
raise Error(error.msg)
return new_url
def path_up(url, count):
"""Helper method for :navigate when `where' is up.
Args:
url: The current url.
count: The number of levels to go up in the url.
"""
path = url.path()
if not path or path == '/':
raise Error("Can't go up!")
for _i in range(0, min(count, path.count('/'))):
path = posixpath.join(path, posixpath.pardir)
url.setPath(path)
return url
def _find_prevnext(prev, elems):
"""Find a prev/next element in the given list of elements."""
# First check for <link rel="prev(ious)|next">
rel_values = {'prev', 'previous'} if prev else {'next'}
for e in elems:
if e.tag_name() not in ['link', 'a'] or 'rel' not in e:
continue
if set(e['rel'].split(' ')) & rel_values:
log.hints.debug("Found {!r} with rel={}".format(e, e['rel']))
return e
# Then check for regular links/buttons.
filterfunc = webelem.FILTERS[webelem.Group.prevnext]
elems = [e for e in elems if e.tag_name() != 'link' and filterfunc(e)]
option = 'prev-regexes' if prev else 'next-regexes'
if not elems:
return None
for regex in config.get('hints', option):
log.hints.vdebug("== Checking regex '{}'.".format(regex.pattern))
for e in elems:
text = str(e)
if not text:
continue
if regex.search(text):
log.hints.debug("Regex '{}' matched on '{}'.".format(
regex.pattern, text))
return e
else:
log.hints.vdebug("No match on '{}'!".format(text))
return None
def prevnext(*, browsertab, win_id, baseurl, prev=False,
tab=False, background=False, window=False):
"""Click a "previous"/"next" element on the page.
Args:
browsertab: The WebKitTab/WebEngineTab of the page.
baseurl: The base URL of the current tab.
prev: True to open a "previous" link, False to open a "next" link.
tab: True to open in a new tab, False for the current tab.
background: True to open in a background tab.
window: True to open in a new window, False for the current one.
"""
def _prevnext_cb(elems):
if elems is None:
message.error("There was an error while getting hint elements")
return
elem = _find_prevnext(prev, elems)
word = 'prev' if prev else 'forward'
if elem is None:
message.error("No {} links found!".format(word))
return
url = elem.resolve_url(baseurl)
if url is None:
message.error("No {} links found!".format(word))
return
qtutils.ensure_valid(url)
if window:
from qutebrowser.mainwindow import mainwindow
new_window = mainwindow.MainWindow()
new_window.show()
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=new_window.win_id)
tabbed_browser.tabopen(url, background=False)
elif tab:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.tabopen(url, background=background)
else:
browsertab.openurl(url)
selector = ', '.join([webelem.SELECTORS[webelem.Group.links],
webelem.SELECTORS[webelem.Group.prevnext]])
browsertab.elements.find_css(selector, _prevnext_cb)

View File

@@ -0,0 +1,3 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
"""Modules related to network operations."""

View File

@@ -0,0 +1,305 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Evaluation of PAC scripts."""
import sys
import functools
from PyQt5.QtCore import (QObject, pyqtSignal, pyqtSlot)
from PyQt5.QtNetwork import (QNetworkProxy, QNetworkRequest, QHostInfo,
QNetworkReply, QNetworkAccessManager,
QHostAddress)
from PyQt5.QtQml import QJSEngine, QJSValue
from qutebrowser.utils import log, utils, qtutils
class ParseProxyError(Exception):
"""Error while parsing PAC result string."""
pass
class EvalProxyError(Exception):
"""Error while evaluating PAC script."""
pass
def _js_slot(*args):
"""Wrap a methods as a JavaScript function.
Register a PACContext method as a JavaScript function, and catch
exceptions returning them as JavaScript Error objects.
Args:
args: Types of method arguments.
Return: Wrapped method.
"""
def _decorator(method):
@functools.wraps(method)
def new_method(self, *args, **kwargs):
try:
return method(self, *args, **kwargs)
except:
e = str(sys.exc_info()[0])
log.network.exception("PAC evaluation error")
# pylint: disable=protected-access
return self._error_con.callAsConstructor([e])
# pylint: enable=protected-access
return pyqtSlot(*args, result=QJSValue)(new_method)
return _decorator
class _PACContext(QObject):
"""Implementation of PAC API functions that require native calls.
See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Necko/Proxy_Auto-Configuration_(PAC)_file
"""
JS_DEFINITIONS = """
function dnsResolve(host) {
return PAC.dnsResolve(host);
}
function myIpAddress() {
return PAC.myIpAddress();
}
"""
def __init__(self, engine):
"""Create a new PAC API implementation instance.
Args:
engine: QJSEngine which is used for running PAC.
"""
super().__init__(parent=engine)
self._engine = engine
self._error_con = engine.globalObject().property("Error")
@_js_slot(str)
def dnsResolve(self, host):
"""Resolve a DNS hostname.
Resolves the given DNS hostname into an IP address, and returns it
in the dot-separated format as a string.
Args:
host: hostname to resolve.
"""
ips = QHostInfo.fromName(host)
if ips.error() != QHostInfo.NoError or not ips.addresses():
err_f = "Failed to resolve host during PAC evaluation: {}"
log.network.info(err_f.format(host))
return QJSValue(QJSValue.NullValue)
else:
return ips.addresses()[0].toString()
@_js_slot()
def myIpAddress(self):
"""Get host IP address.
Return the server IP address of the current machine, as a string in
the dot-separated integer format.
"""
return QHostAddress(QHostAddress.LocalHost).toString()
class PACResolver:
"""Evaluate PAC script files and resolve proxies."""
@staticmethod
def _parse_proxy_host(host_str):
host, _colon, port_str = host_str.partition(':')
try:
port = int(port_str)
except ValueError:
raise ParseProxyError("Invalid port number")
return (host, port)
@staticmethod
def _parse_proxy_entry(proxy_str):
"""Parse one proxy string entry, as described in PAC specification."""
config = [c.strip() for c in proxy_str.split(' ') if c]
if not config:
raise ParseProxyError("Empty proxy entry")
elif config[0] == "DIRECT":
if len(config) != 1:
raise ParseProxyError("Invalid number of parameters for " +
"DIRECT")
return QNetworkProxy(QNetworkProxy.NoProxy)
elif config[0] == "PROXY":
if len(config) != 2:
raise ParseProxyError("Invalid number of parameters for PROXY")
host, port = PACResolver._parse_proxy_host(config[1])
return QNetworkProxy(QNetworkProxy.HttpProxy, host, port)
elif config[0] == "SOCKS":
if len(config) != 2:
raise ParseProxyError("Invalid number of parameters for SOCKS")
host, port = PACResolver._parse_proxy_host(config[1])
return QNetworkProxy(QNetworkProxy.Socks5Proxy, host, port)
else:
err = "Unknown proxy type: {}"
raise ParseProxyError(err.format(config[0]))
@staticmethod
def _parse_proxy_string(proxy_str):
proxies = proxy_str.split(';')
return [PACResolver._parse_proxy_entry(x) for x in proxies]
def _evaluate(self, js_code, js_file):
ret = self._engine.evaluate(js_code, js_file)
if ret.isError():
err = "JavaScript error while evaluating PAC file: {}"
raise EvalProxyError(err.format(ret.toString()))
def __init__(self, pac_str):
"""Create a PAC resolver.
Args:
pac_str: JavaScript code containing PAC resolver.
"""
self._engine = QJSEngine()
self._ctx = _PACContext(self._engine)
self._engine.globalObject().setProperty(
"PAC", self._engine.newQObject(self._ctx))
self._evaluate(_PACContext.JS_DEFINITIONS, "pac_js_definitions")
self._evaluate(utils.read_file("javascript/pac_utils.js"), "pac_utils")
proxy_config = self._engine.newObject()
proxy_config.setProperty("bindings", self._engine.newObject())
self._engine.globalObject().setProperty("ProxyConfig", proxy_config)
self._evaluate(pac_str, "pac")
global_js_object = self._engine.globalObject()
self._resolver = global_js_object.property("FindProxyForURL")
if not self._resolver.isCallable():
err = "Cannot resolve FindProxyForURL function, got '{}' instead"
raise EvalProxyError(err.format(self._resolver.toString()))
def resolve(self, query):
"""Resolve a proxy via PAC.
Args:
query: QNetworkProxyQuery.
Return:
A list of QNetworkProxy objects in order of preference.
"""
result = self._resolver.call([query.url().toString(),
query.peerHostName()])
result_str = result.toString()
if not result.isString():
err = "Got strange value from FindProxyForURL: '{}'"
raise EvalProxyError(err.format(result_str))
return self._parse_proxy_string(result_str)
class PACFetcher(QObject):
"""Asynchronous fetcher of PAC files."""
finished = pyqtSignal()
def __init__(self, url, parent=None):
"""Resolve a PAC proxy from URL.
Args:
url: QUrl of a PAC proxy.
"""
super().__init__(parent)
pac_prefix = "pac+"
assert url.scheme().startswith(pac_prefix)
url.setScheme(url.scheme()[len(pac_prefix):])
self._manager = QNetworkAccessManager()
self._manager.setProxy(QNetworkProxy(QNetworkProxy.NoProxy))
self._reply = self._manager.get(QNetworkRequest(url))
self._reply.finished.connect(self._finish)
self._pac = None
self._error_message = None
@pyqtSlot()
def _finish(self):
if self._reply.error() != QNetworkReply.NoError:
error = "Can't fetch PAC file from URL, error code {}: {}"
self._error_message = error.format(
self._reply.error(), self._reply.errorString())
log.network.error(self._error_message)
else:
try:
pacscript = bytes(self._reply.readAll()).decode("utf-8")
except UnicodeError as e:
error = "Invalid encoding of a PAC file: {}"
self._error_message = error.format(e)
log.network.exception(self._error_message)
try:
self._pac = PACResolver(pacscript)
log.network.debug("Successfully evaluated PAC file.")
except EvalProxyError as e:
error = "Error in PAC evaluation: {}"
self._error_message = error.format(e)
log.network.exception(self._error_message)
self._manager = None
self._reply = None
self.finished.emit()
def _wait(self):
"""Wait until a reply from the remote server is received."""
if self._manager is not None:
loop = qtutils.EventLoop()
self.finished.connect(loop.quit)
loop.exec_()
def fetch_error(self):
"""Check if PAC script is successfully fetched.
Return None iff PAC script is downloaded and evaluated successfully,
error string otherwise.
"""
self._wait()
return self._error_message
def resolve(self, query):
"""Resolve a query via PAC.
Args: QNetworkProxyQuery.
Return a list of QNetworkProxy objects in order of preference.
"""
self._wait()
try:
return self._pac.resolve(query)
except (EvalProxyError, ParseProxyError) as e:
log.network.exception("Error in PAC resolution: {}.".format(e))
# .invalid is guaranteed to be inaccessible in RFC 6761.
# Port 9 is for DISCARD protocol -- DISCARD servers act like
# /dev/null.
# Later NetworkManager.createRequest will detect this and display
# an error message.
error_host = "pac-resolve-error.qutebrowser.invalid"
return QNetworkProxy(QNetworkProxy.HttpProxy, error_host, 9)

View File

@@ -23,17 +23,33 @@
from PyQt5.QtNetwork import QNetworkProxy, QNetworkProxyFactory
from qutebrowser.config import config, configtypes
from qutebrowser.utils import objreg
from qutebrowser.browser.network import pac
def init():
"""Set the application wide proxy factory."""
QNetworkProxyFactory.setApplicationProxyFactory(ProxyFactory())
proxy_factory = ProxyFactory()
objreg.register('proxy-factory', proxy_factory)
QNetworkProxyFactory.setApplicationProxyFactory(proxy_factory)
class ProxyFactory(QNetworkProxyFactory):
"""Factory for proxies to be used by qutebrowser."""
def get_error(self):
"""Check if proxy can't be resolved.
Return:
None if proxy is correct, otherwise an error message.
"""
proxy = config.get('network', 'proxy')
if isinstance(proxy, pac.PACFetcher):
return proxy.fetch_error()
else:
return None
def queryProxy(self, query):
"""Get the QNetworkProxies for a query.
@@ -46,6 +62,8 @@ class ProxyFactory(QNetworkProxyFactory):
proxy = config.get('network', 'proxy')
if proxy is configtypes.SYSTEM_PROXY:
proxies = QNetworkProxyFactory.systemProxyForQuery(query)
elif isinstance(proxy, pac.PACFetcher):
proxies = proxy.resolve(query)
else:
proxies = [proxy]
for p in proxies:

View File

@@ -23,8 +23,7 @@ import os
from PyQt5.QtCore import QUrl
from qutebrowser.browser.webkit import webelem
from qutebrowser.utils import utils
from qutebrowser.utils import utils, javascript
class PDFJSNotFound(Exception):
@@ -63,9 +62,11 @@ def _generate_pdfjs_script(url):
url: The url of the pdf page as QUrl.
"""
return (
'PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
'PDFView.open("{url}");\n'
).format(url=webelem.javascript_escape(url.toString(QUrl.FullyEncoded)))
'document.addEventListener("DOMContentLoaded", function() {{\n'
' PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
' (window.PDFView || window.PDFViewerApplication).open("{url}");\n'
'}});\n'
).format(url=javascript.string_escape(url.toString(QUrl.FullyEncoded)))
def fix_urls(asset):
@@ -99,6 +100,8 @@ SYSTEM_PDFJS_PATHS = [
# Debian pdf.js-common
# Arch Linux pdfjs (AUR)
'/usr/share/pdf.js/',
# Arch Linux pdf.js (AUR)
'/usr/share/javascript/pdf.js/',
# Debian libjs-pdf
'/usr/share/javascript/pdf/',
# fallback

View File

@@ -0,0 +1,528 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Download manager."""
import io
import shutil
import functools
import collections
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QTimer
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
from qutebrowser.utils import message, usertypes, log, urlutils, utils
from qutebrowser.browser import downloads
from qutebrowser.browser.webkit import http
from qutebrowser.browser.webkit.network import networkmanager
_RetryInfo = collections.namedtuple('_RetryInfo', ['request', 'manager'])
class DownloadItem(downloads.AbstractDownloadItem):
"""A single download currently running.
There are multiple ways the data can flow from the QNetworkReply to the
disk.
If the filename/file object is known immediately when starting the
download, QNetworkReply's readyRead writes to the target file directly.
If not, readyRead is ignored and with self._read_timer we periodically read
into the self._buffer BytesIO slowly, so some broken servers don't close
our connection.
As soon as we know the file object, we copy self._buffer over and the next
readyRead will write to the real file object.
Class attributes:
_MAX_REDIRECTS: The maximum redirection count.
Attributes:
_retry_info: A _RetryInfo instance.
_redirects: How many time we were redirected already.
_buffer: A BytesIO object to buffer incoming data until we know the
target file.
_read_timer: A Timer which reads the QNetworkReply into self._buffer
periodically.
_manager: The DownloadManager which started this download
_reply: The QNetworkReply associated with this download.
_autoclose: Whether to close the associated file when the download is
done.
Signals:
adopt_download: Emitted when a download is retried and should be
adopted by the QNAM if needed.
arg 0: The new DownloadItem
"""
_MAX_REDIRECTS = 10
adopt_download = pyqtSignal(object) # DownloadItem
def __init__(self, reply, manager):
"""Constructor.
Args:
reply: The QNetworkReply to download.
"""
super().__init__(parent=manager)
self.fileobj = None
self.raw_headers = {}
self._autoclose = True
self._manager = manager
self._retry_info = None
self._reply = None
self._buffer = io.BytesIO()
self._read_timer = usertypes.Timer(self, name='download-read-timer')
self._read_timer.setInterval(500)
self._read_timer.timeout.connect(self._on_read_timer_timeout)
self._redirects = 0
self._init_reply(reply)
def _create_fileobj(self):
"""Create a file object using the internal filename."""
try:
fileobj = open(self._filename, 'wb')
except OSError as e:
self._die(e.strerror)
else:
self._set_fileobj(fileobj)
def _do_die(self):
"""Abort the download and emit an error."""
self._read_timer.stop()
self._reply.downloadProgress.disconnect()
self._reply.finished.disconnect()
self._reply.error.disconnect()
self._reply.readyRead.disconnect()
with log.hide_qt_warning('QNetworkReplyImplPrivate::error: Internal '
'problem, this method must only be called '
'once.'):
# See https://codereview.qt-project.org/#/c/107863/
self._reply.abort()
self._reply.deleteLater()
self._reply = None
if self.fileobj is not None:
try:
self.fileobj.close()
except OSError:
log.downloads.exception("Error while closing file object")
def _init_reply(self, reply):
"""Set a new reply and connect its signals.
Args:
reply: The QNetworkReply to handle.
"""
self.done = False
self.successful = False
self._reply = reply
reply.setReadBufferSize(16 * 1024 * 1024) # 16 MB
reply.downloadProgress.connect(self.stats.on_download_progress)
reply.finished.connect(self._on_reply_finished)
reply.error.connect(self._on_reply_error)
reply.readyRead.connect(self._on_ready_read)
reply.metaDataChanged.connect(self._on_meta_data_changed)
self._retry_info = _RetryInfo(request=reply.request(),
manager=reply.manager())
if not self.fileobj:
self._read_timer.start()
# We could have got signals before we connected slots to them.
# Here no signals are connected to the DownloadItem yet, so we use a
# singleShot QTimer to emit them after they are connected.
if reply.error() != QNetworkReply.NoError:
QTimer.singleShot(0, lambda: self._die(reply.errorString()))
def _do_cancel(self):
if self._reply is not None:
self._reply.finished.disconnect(self._on_reply_finished)
self._reply.abort()
self._reply.deleteLater()
self._reply = None
if self.fileobj is not None:
self.fileobj.close()
self.cancelled.emit()
@pyqtSlot()
def retry(self):
"""Retry a failed download."""
assert self.done
assert not self.successful
new_reply = self._retry_info.manager.get(self._retry_info.request)
new_download = self._manager.fetch(new_reply,
suggested_filename=self.basename)
self.adopt_download.emit(new_download)
self.cancel()
def _get_open_filename(self):
filename = self._filename
if filename is None:
filename = getattr(self.fileobj, 'name', None)
return filename
def _ensure_can_set_filename(self, filename):
if self.fileobj is not None: # pragma: no cover
raise ValueError("fileobj was already set! filename: {}, "
"existing: {}, fileobj {}".format(
filename, self._filename, self.fileobj))
def _after_set_filename(self):
self._create_fileobj()
def _ask_confirm_question(self, title, msg):
no_action = functools.partial(self.cancel, remove_data=False)
message.confirm_async(title=title, text=msg,
yes_action=self._after_set_filename,
no_action=no_action, cancel_action=no_action,
abort_on=[self.cancelled, self.error])
def _set_fileobj(self, fileobj, *, autoclose=True):
""""Set the file object to write the download to.
Args:
fileobj: A file-like object.
"""
if self.fileobj is not None: # pragma: no cover
raise ValueError("fileobj was already set! Old: {}, new: "
"{}".format(self.fileobj, fileobj))
self.fileobj = fileobj
self._autoclose = autoclose
try:
self._read_timer.stop()
log.downloads.debug("buffer: {} bytes".format(self._buffer.tell()))
self._buffer.seek(0)
shutil.copyfileobj(self._buffer, fileobj)
self._buffer.close()
if self._reply.isFinished():
# Downloading to the buffer in RAM has already finished so we
# write out the data and clean up now.
self._on_reply_finished()
else:
# Since the buffer already might be full, on_ready_read might
# not be called at all anymore, so we force it here to flush
# the buffer and continue receiving new data.
self._on_ready_read()
except OSError as e:
self._die(e.strerror)
def _set_tempfile(self, fileobj):
self._set_fileobj(fileobj)
def _finish_download(self):
"""Write buffered data to disk and finish the QNetworkReply."""
log.downloads.debug("Finishing download...")
if self._reply.isOpen():
self.fileobj.write(self._reply.readAll())
if self._autoclose:
self.fileobj.close()
self.successful = self._reply.error() == QNetworkReply.NoError
self._reply.close()
self._reply.deleteLater()
self._reply = None
self.finished.emit()
self.done = True
log.downloads.debug("Download {} finished".format(self.basename))
self.data_changed.emit()
@pyqtSlot()
def _on_reply_finished(self):
"""Clean up when the download was finished.
Note when this gets called, only the QNetworkReply has finished. This
doesn't mean the download (i.e. writing data to the disk) is finished
as well. Therefore, we can't close() the QNetworkReply in here yet.
"""
if self._reply is None:
return
self._read_timer.stop()
self.stats.finish()
is_redirected = self._handle_redirect()
if is_redirected:
return
log.downloads.debug("Reply finished, fileobj {}".format(self.fileobj))
if self.fileobj is not None:
# We can do a "delayed" write immediately to empty the buffer and
# clean up.
self._finish_download()
@pyqtSlot()
def _on_ready_read(self):
"""Read available data and save file when ready to read."""
if self.fileobj is None or self._reply is None:
# No filename has been set yet (so we don't empty the buffer) or we
# got a readyRead after the reply was finished (which happens on
# qute:log for example).
return
if not self._reply.isOpen():
raise OSError("Reply is closed!")
try:
self.fileobj.write(self._reply.readAll())
except OSError as e:
self._die(e.strerror)
@pyqtSlot('QNetworkReply::NetworkError')
def _on_reply_error(self, code):
"""Handle QNetworkReply errors."""
if code == QNetworkReply.OperationCanceledError:
return
else:
self._die(self._reply.errorString())
@pyqtSlot()
def _on_read_timer_timeout(self):
"""Read some bytes from the QNetworkReply periodically."""
if not self._reply.isOpen():
raise OSError("Reply is closed!")
data = self._reply.read(1024)
if data is not None:
self._buffer.write(data)
@pyqtSlot()
def _on_meta_data_changed(self):
"""Update the download's metadata."""
if self._reply is None:
return
self.raw_headers = {}
for key, value in self._reply.rawHeaderPairs():
self.raw_headers[bytes(key)] = bytes(value)
def _handle_redirect(self):
"""Handle an HTTP redirect.
Return:
True if the download was redirected, False otherwise.
"""
redirect = self._reply.attribute(
QNetworkRequest.RedirectionTargetAttribute)
if redirect is None or redirect.isEmpty():
return False
new_url = self._reply.url().resolved(redirect)
new_request = self._reply.request()
if new_url == new_request.url():
return False
if self._redirects > self._MAX_REDIRECTS:
self._die("Maximum redirection count reached!")
self.delete()
return True # so on_reply_finished aborts
log.downloads.debug("{}: Handling redirect".format(self))
self._redirects += 1
new_request.setUrl(new_url)
old_reply = self._reply
old_reply.finished.disconnect(self._on_reply_finished)
self._read_timer.stop()
self._reply = None
if self.fileobj is not None:
self.fileobj.seek(0)
log.downloads.debug("redirected: {} -> {}".format(
old_reply.url(), new_request.url()))
new_reply = old_reply.manager().get(new_request)
self._init_reply(new_reply)
old_reply.deleteLater()
return True
def _uses_nam(self, nam):
"""Check if this download uses the given QNetworkAccessManager."""
running_nam = self._reply is not None and self._reply.manager() is nam
# user could request retry after tab is closed.
retry_nam = (self.done and (not self.successful) and
self._retry_info.manager is nam)
return running_nam or retry_nam
class DownloadManager(downloads.AbstractDownloadManager):
"""Manager for currently running downloads.
Attributes:
_networkmanager: A NetworkManager for generic downloads.
"""
def __init__(self, win_id, parent=None):
super().__init__(parent)
self._networkmanager = networkmanager.NetworkManager(
win_id, None, self)
@pyqtSlot('QUrl')
def get(self, url, *, user_agent=None, **kwargs):
"""Start a download with a link URL.
Args:
url: The URL to get, as QUrl
user_agent: The UA to set for the request, or None.
**kwargs: passed to get_request().
Return:
The created DownloadItem.
"""
if not url.isValid():
urlutils.invalid_url_error(url, "start download")
return
req = QNetworkRequest(url)
if user_agent is not None:
req.setHeader(QNetworkRequest.UserAgentHeader, user_agent)
return self.get_request(req, **kwargs)
def get_mhtml(self, tab, target):
"""Download the given tab as mhtml to the given DownloadTarget."""
assert tab.backend == usertypes.Backend.QtWebKit
from qutebrowser.browser.webkit import mhtml
if target is not None:
mhtml.start_download_checked(target, tab=tab)
return
suggested_fn = utils.sanitize_filename(tab.title() + ".mhtml")
filename = downloads.immediate_download_path()
if filename is not None:
target = downloads.FileDownloadTarget(filename)
mhtml.start_download_checked(target, tab=tab)
else:
question = downloads.get_filename_question(
suggested_filename=suggested_fn, url=tab.url(), parent=tab)
question.answered.connect(functools.partial(
mhtml.start_download_checked, tab=tab))
message.global_bridge.ask(question, blocking=False)
def get_request(self, request, *, target=None, **kwargs):
"""Start a download with a QNetworkRequest.
Args:
request: The QNetworkRequest to download.
target: Where to save the download as downloads.DownloadTarget.
**kwargs: Passed to _fetch_request.
Return:
The created DownloadItem.
"""
# WORKAROUND for Qt corrupting data loaded from cache:
# https://bugreports.qt.io/browse/QTBUG-42757
request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
QNetworkRequest.AlwaysNetwork)
if request.url().scheme().lower() != 'data':
suggested_fn = urlutils.filename_from_url(request.url())
else:
# We might be downloading a binary blob embedded on a page or even
# generated dynamically via javascript. We try to figure out a more
# sensible name than the base64 content of the data.
origin = request.originatingObject()
try:
origin_url = origin.url()
except AttributeError:
# Raised either if origin is None or some object that doesn't
# have its own url. We're probably fine with a default fallback
# then.
suggested_fn = 'binary blob'
else:
# Use the originating URL as a base for the filename (works
# e.g. for pdf.js).
suggested_fn = urlutils.filename_from_url(origin_url)
if suggested_fn is None:
suggested_fn = 'qutebrowser-download'
return self._fetch_request(request,
target=target,
suggested_filename=suggested_fn,
**kwargs)
def _fetch_request(self, request, *, qnam=None, **kwargs):
"""Download a QNetworkRequest to disk.
Args:
request: The QNetworkRequest to download.
qnam: The QNetworkAccessManager to use.
**kwargs: passed to fetch().
Return:
The created DownloadItem.
"""
if qnam is None:
qnam = self._networkmanager
reply = qnam.get(request)
return self.fetch(reply, **kwargs)
@pyqtSlot('QNetworkReply')
def fetch(self, reply, *, target=None, auto_remove=False,
suggested_filename=None, prompt_download_directory=None):
"""Download a QNetworkReply to disk.
Args:
reply: The QNetworkReply to download.
target: Where to save the download as downloads.DownloadTarget.
auto_remove: Whether to remove the download even if
ui -> remove-finished-downloads is set to -1.
Return:
The created DownloadItem.
"""
if not suggested_filename:
try:
suggested_filename = target.suggested_filename()
except downloads.NoFilenameError:
_, suggested_filename = http.parse_content_disposition(reply)
log.downloads.debug("fetch: {} -> {}".format(reply.url(),
suggested_filename))
download = DownloadItem(reply, manager=self)
self._init_item(download, auto_remove, suggested_filename)
if target is not None:
download.set_target(target)
return download
# Neither filename nor fileobj were given
filename = downloads.immediate_download_path(prompt_download_directory)
if filename is not None:
# User doesn't want to be asked, so just use the download_dir
target = downloads.FileDownloadTarget(filename)
download.set_target(target)
return download
# Ask the user for a filename
question = downloads.get_filename_question(
suggested_filename=suggested_filename, url=reply.url(),
parent=self)
self._init_filename_question(question, download)
message.global_bridge.ask(question, blocking=False)
return download
def has_downloads_with_nam(self, nam):
"""Check if the DownloadManager has any downloads with the given QNAM.
Args:
nam: The QNetworkAccessManager to check.
Return:
A boolean.
"""
assert nam.adopted_downloads == 0
for download in self.downloads:
if download._uses_nam(nam): # pylint: disable=protected-access
nam.adopt_download(download)
return nam.adopted_downloads

View File

@@ -0,0 +1,341 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Backend-independent qute:* code.
Module attributes:
pyeval_output: The output of the last :pyeval command.
_HANDLERS: The handlers registered via decorators.
"""
import sys
import time
import datetime
import urllib.parse
from PyQt5.QtCore import QUrlQuery
import qutebrowser
from qutebrowser.utils import (version, utils, jinja, log, message, docutils,
objreg)
from qutebrowser.misc import objects
pyeval_output = ":pyeval was never called"
_HANDLERS = {}
class NoHandlerFound(Exception):
"""Raised when no handler was found for the given URL."""
pass
class QuteSchemeOSError(Exception):
"""Called when there was an OSError inside a handler."""
pass
class QuteSchemeError(Exception):
"""Exception to signal that a handler should return an ErrorReply.
Attributes correspond to the arguments in
networkreply.ErrorNetworkReply.
Attributes:
errorstring: Error string to print.
error: Numerical error value.
"""
def __init__(self, errorstring, error):
self.errorstring = errorstring
self.error = error
super().__init__(errorstring)
class add_handler: # pylint: disable=invalid-name
"""Decorator to register a qute:* URL handler.
Attributes:
_name: The 'foo' part of qute:foo
backend: Limit which backends the handler can run with.
"""
def __init__(self, name, backend=None):
self._name = name
self._backend = backend
self._function = None
def __call__(self, function):
self._function = function
_HANDLERS[self._name] = self.wrapper
return function
def wrapper(self, *args, **kwargs):
if self._backend is not None and objects.backend != self._backend:
return self.wrong_backend_handler(*args, **kwargs)
else:
return self._function(*args, **kwargs)
def wrong_backend_handler(self, url):
"""Show an error page about using the invalid backend."""
html = jinja.render('error.html',
title="Error while opening qute:url",
url=url.toDisplayString(),
error='{} is not available with this '
'backend'.format(url.toDisplayString()),
icon='')
return 'text/html', html
def data_for_url(url):
"""Get the data to show for the given URL.
Args:
url: The QUrl to show.
Return:
A (mimetype, data) tuple.
"""
path = url.path()
host = url.host()
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
log.misc.debug("url: {}, path: {}, host {}".format(
url.toDisplayString(), path, host))
try:
handler = _HANDLERS[path]
except KeyError:
try:
handler = _HANDLERS[host]
except KeyError:
raise NoHandlerFound(url)
try:
mimetype, data = handler(url)
except OSError as e:
# FIXME:qtwebengine how to handle this?
raise QuteSchemeOSError(e)
except QuteSchemeError as e:
raise
assert mimetype is not None, url
if mimetype == 'text/html' and isinstance(data, str):
# We let handlers return HTML as text
data = data.encode('utf-8', errors='xmlcharrefreplace')
return mimetype, data
@add_handler('bookmarks')
def qute_bookmarks(_url):
"""Handler for qute:bookmarks. Display all quickmarks / bookmarks."""
bookmarks = sorted(objreg.get('bookmark-manager').marks.items(),
key=lambda x: x[1]) # Sort by title
quickmarks = sorted(objreg.get('quickmark-manager').marks.items(),
key=lambda x: x[0]) # Sort by name
html = jinja.render('bookmarks.html',
title='Bookmarks',
bookmarks=bookmarks,
quickmarks=quickmarks)
return 'text/html', html
@add_handler('history') # noqa
def qute_history(url):
"""Handler for qute:history. Display history."""
# Get current date from query parameter, if not given choose today.
curr_date = datetime.date.today()
try:
query_date = QUrlQuery(url).queryItemValue("date")
if query_date:
curr_date = datetime.datetime.strptime(query_date, "%Y-%m-%d")
curr_date = curr_date.date()
except ValueError:
log.misc.debug("Invalid date passed to qute:history: " + query_date)
one_day = datetime.timedelta(days=1)
next_date = curr_date + one_day
prev_date = curr_date - one_day
def history_iter(reverse):
"""Iterate through the history and get items we're interested in."""
curr_timestamp = time.mktime(curr_date.timetuple())
history = objreg.get('web-history').history_dict.values()
if reverse:
history = reversed(history)
for item in history:
# If we can't apply the reverse performance trick below,
# at least continue as early as possible with old items.
# This gets us down from 550ms to 123ms with 500k old items on my
# machine.
if item.atime < curr_timestamp and not reverse:
continue
# Convert timestamp
try:
item_atime = datetime.datetime.fromtimestamp(item.atime)
except (ValueError, OSError, OverflowError):
log.misc.debug("Invalid timestamp {}.".format(item.atime))
continue
if reverse and item_atime.date() < curr_date:
# If we could reverse the history in-place, and this entry is
# older than today, only older entries will follow, so we can
# abort here.
return
# Skip items not on curr_date
# Skip redirects
# Skip qute:// links
is_internal = item.url.scheme() == 'qute'
is_not_today = item_atime.date() != curr_date
if item.redirect or is_internal or is_not_today:
continue
# Use item's url as title if there's no title.
item_url = item.url.toDisplayString()
item_title = item.title if item.title else item_url
display_atime = item_atime.strftime("%X")
yield (item_url, item_title, display_atime)
if sys.hexversion >= 0x03050000:
# On Python >= 3.5 we can reverse the ordereddict in-place and thus
# apply an additional performance improvement in history_iter.
# On my machine, this gets us down from 550ms to 72us with 500k old
# items.
history = list(history_iter(reverse=True))
else:
# On Python 3.4, we can't do that, so we'd need to copy the entire
# history to a list. There, filter first and then reverse it here.
history = reversed(list(history_iter(reverse=False)))
html = jinja.render('history.html',
title='History',
history=history,
curr_date=curr_date,
next_date=next_date,
prev_date=prev_date,
today=datetime.date.today())
return 'text/html', html
@add_handler('pyeval')
def qute_pyeval(_url):
"""Handler for qute:pyeval."""
html = jinja.render('pre.html', title='pyeval', content=pyeval_output)
return 'text/html', html
@add_handler('version')
@add_handler('verizon')
def qute_version(_url):
"""Handler for qute:version."""
html = jinja.render('version.html', title='Version info',
version=version.version(),
copyright=qutebrowser.__copyright__)
return 'text/html', html
@add_handler('plainlog')
def qute_plainlog(url):
"""Handler for qute:plainlog.
An optional query parameter specifies the minimum log level to print.
For example, qute://log?level=warning prints warnings and errors.
Level can be one of: vdebug, debug, info, warning, error, critical.
"""
if log.ram_handler is None:
text = "Log output was disabled."
else:
try:
level = urllib.parse.parse_qs(url.query())['level'][0]
except KeyError:
level = 'vdebug'
text = log.ram_handler.dump_log(html=False, level=level)
html = jinja.render('pre.html', title='log', content=text)
return 'text/html', html
@add_handler('log')
def qute_log(url):
"""Handler for qute:log.
An optional query parameter specifies the minimum log level to print.
For example, qute://log?level=warning prints warnings and errors.
Level can be one of: vdebug, debug, info, warning, error, critical.
"""
if log.ram_handler is None:
html_log = None
else:
try:
level = urllib.parse.parse_qs(url.query())['level'][0]
except KeyError:
level = 'vdebug'
html_log = log.ram_handler.dump_log(html=True, level=level)
html = jinja.render('log.html', title='log', content=html_log)
return 'text/html', html
@add_handler('gpl')
def qute_gpl(_url):
"""Handler for qute:gpl. Return HTML content as string."""
return 'text/html', utils.read_file('html/COPYING.html')
@add_handler('help')
def qute_help(url):
"""Handler for qute:help."""
try:
utils.read_file('html/doc/index.html')
except OSError:
html = jinja.render(
'error.html',
title="Error while loading documentation",
url=url.toDisplayString(),
error="This most likely means the documentation was not generated "
"properly. If you are running qutebrowser from the git "
"repository, please run scripts/asciidoc2html.py. "
"If you're running a released version this is a bug, please "
"use :report to report it.",
icon='')
return 'text/html', html
urlpath = url.path()
if not urlpath or urlpath == '/':
urlpath = 'index.html'
else:
urlpath = urlpath.lstrip('/')
if not docutils.docs_up_to_date(urlpath):
message.error("Your documentation is outdated! Please re-run "
"scripts/asciidoc2html.py.")
path = 'html/doc/{}'.format(urlpath)
if urlpath.endswith('.png'):
return 'image/png', utils.read_file(path, binary=True)
else:
data = utils.read_file(path)
return 'text/html', data

View File

@@ -0,0 +1,245 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Various utilities shared between webpage/webview subclasses."""
import html
import jinja2
from qutebrowser.config import config
from qutebrowser.utils import usertypes, message, log, objreg
class CallSuper(Exception):
"""Raised when the caller should call the superclass instead."""
def custom_headers():
"""Get the combined custom headers."""
headers = {}
dnt = b'1' if config.get('network', 'do-not-track') else b'0'
headers[b'DNT'] = dnt
headers[b'X-Do-Not-Track'] = dnt
config_headers = config.get('network', 'custom-headers')
if config_headers is not None:
for header, value in config_headers.items():
headers[header.encode('ascii')] = value.encode('ascii')
accept_language = config.get('network', 'accept-language')
if accept_language is not None:
headers[b'Accept-Language'] = accept_language.encode('ascii')
return sorted(headers.items())
def authentication_required(url, authenticator, abort_on):
"""Ask a prompt for an authentication question."""
realm = authenticator.realm()
if realm:
msg = '<b>{}</b> says:<br/>{}'.format(
html.escape(url.toDisplayString()), html.escape(realm))
else:
msg = '<b>{}</b> needs authentication'.format(
html.escape(url.toDisplayString()))
answer = message.ask(title="Authentication required", text=msg,
mode=usertypes.PromptMode.user_pwd,
abort_on=abort_on)
if answer is not None:
authenticator.setUser(answer.user)
authenticator.setPassword(answer.password)
return answer
def javascript_confirm(url, js_msg, abort_on):
"""Display a javascript confirm prompt."""
log.js.debug("confirm: {}".format(js_msg))
if config.get('ui', 'modal-js-dialog'):
raise CallSuper
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
html.escape(js_msg))
ans = message.ask('Javascript confirm', msg,
mode=usertypes.PromptMode.yesno,
abort_on=abort_on)
return bool(ans)
def javascript_prompt(url, js_msg, default, abort_on):
"""Display a javascript prompt."""
log.js.debug("prompt: {}".format(js_msg))
if config.get('ui', 'modal-js-dialog'):
raise CallSuper
if config.get('content', 'ignore-javascript-prompt'):
return (False, "")
msg = '<b>{}</b> asks:<br/>{}'.format(html.escape(url.toDisplayString()),
html.escape(js_msg))
answer = message.ask('Javascript prompt', msg,
mode=usertypes.PromptMode.text,
default=default,
abort_on=abort_on)
if answer is None:
return (False, "")
else:
return (True, answer)
def javascript_alert(url, js_msg, abort_on):
"""Display a javascript alert."""
log.js.debug("alert: {}".format(js_msg))
if config.get('ui', 'modal-js-dialog'):
raise CallSuper
if config.get('content', 'ignore-javascript-alert'):
return
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
html.escape(js_msg))
message.ask('Javascript alert', msg, mode=usertypes.PromptMode.alert,
abort_on=abort_on)
def ignore_certificate_errors(url, errors, abort_on):
"""Display a certificate error question.
Args:
url: The URL the errors happened in
errors: A list of QSslErrors or QWebEngineCertificateErrors
Return:
True if the error should be ignored, False otherwise.
"""
ssl_strict = config.get('network', 'ssl-strict')
log.webview.debug("Certificate errors {!r}, strict {}".format(
errors, ssl_strict))
for error in errors:
assert error.is_overridable(), repr(error)
if ssl_strict == 'ask':
err_template = jinja2.Template("""
Errors while loading <b>{{url.toDisplayString()}}</b>:<br/>
<ul>
{% for err in errors %}
<li>{{err}}</li>
{% endfor %}
</ul>
""".strip())
msg = err_template.render(url=url, errors=errors)
ignore = message.ask(title="Certificate errors - continue?", text=msg,
mode=usertypes.PromptMode.yesno, default=False,
abort_on=abort_on)
if ignore is None:
# prompt aborted
ignore = False
return ignore
elif ssl_strict is False:
log.webview.debug("ssl-strict is False, only warning about errors")
for err in errors:
# FIXME we might want to use warn here (non-fatal error)
# https://github.com/qutebrowser/qutebrowser/issues/114
message.error('Certificate error: {}'.format(err))
return True
elif ssl_strict is True:
return False
else:
raise ValueError("Invalid ssl_strict value {!r}".format(ssl_strict))
raise AssertionError("Not reached")
def feature_permission(url, option, msg, yes_action, no_action, abort_on):
"""Handle a feature permission request.
Args:
url: The URL the request was done for.
option: A (section, option) tuple for the option to check.
msg: A string like "show notifications"
yes_action: A callable to call if the request was approved
no_action: A callable to call if the request was denied
abort_on: A list of signals which interrupt the question.
Return:
The Question object if a question was asked, None otherwise.
"""
config_val = config.get(*option)
if config_val == 'ask':
if url.isValid():
text = "Allow the website at <b>{}</b> to {}?".format(
html.escape(url.toDisplayString()), msg)
else:
text = "Allow the website to {}?".format(msg)
return message.confirm_async(
yes_action=yes_action, no_action=no_action,
cancel_action=no_action, abort_on=abort_on,
title='Permission request', text=text)
elif config_val:
yes_action()
return None
else:
no_action()
return None
def get_tab(win_id, target):
"""Get a tab widget for the given usertypes.ClickTarget.
Args:
win_id: The window ID to open new tabs in
target: A usertypes.ClickTarget
"""
if target == usertypes.ClickTarget.tab:
win_id = win_id
bg_tab = False
elif target == usertypes.ClickTarget.tab_bg:
win_id = win_id
bg_tab = True
elif target == usertypes.ClickTarget.window:
from qutebrowser.mainwindow import mainwindow
window = mainwindow.MainWindow()
window.show()
win_id = window.win_id
bg_tab = False
else:
raise ValueError("Invalid ClickTarget {}".format(target))
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
return tabbed_browser.tabopen(url=None, background=bg_tab)
def get_user_stylesheet():
"""Get the combined user-stylesheet."""
filename = config.get('ui', 'user-stylesheet')
if filename is None:
css = ''
else:
with open(filename, 'r', encoding='utf-8') as f:
css = f.read()
if config.get('ui', 'hide-scrollbar'):
css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }'
return css

View File

@@ -26,6 +26,7 @@ to a file on shutdown, so it makes sense to keep them as strings here.
"""
import os
import html
import os.path
import functools
import collections
@@ -33,7 +34,7 @@ import collections
from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from qutebrowser.utils import (message, usertypes, qtutils, urlutils,
standarddir, objreg)
standarddir, objreg, log)
from qutebrowser.commands import cmdutils
from qutebrowser.misc import lineparser
@@ -72,8 +73,7 @@ class UrlMarkManager(QObject):
Attributes:
marks: An OrderedDict of all quickmarks/bookmarks.
_lineparser: The LineParser used for the marks, or None
(when qutebrowser is started with -c '').
_lineparser: The LineParser used for the marks
Signals:
changed: Emitted when anything changed.
@@ -90,10 +90,6 @@ class UrlMarkManager(QObject):
super().__init__(parent)
self.marks = collections.OrderedDict()
self._lineparser = None
if standarddir.config() is None:
return
self._init_lineparser()
for line in self._lineparser:
@@ -114,10 +110,8 @@ class UrlMarkManager(QObject):
def save(self):
"""Save the marks to disk."""
if self._lineparser is not None:
self._lineparser.data = [' '.join(tpl)
for tpl in self.marks.items()]
self._lineparser.save()
self._lineparser.data = [' '.join(tpl) for tpl in self.marks.items()]
self._lineparser.save()
def delete(self, key):
"""Delete a quickmark/bookmark.
@@ -155,45 +149,44 @@ class QuickmarkManager(UrlMarkManager):
try:
key, url = line.rsplit(maxsplit=1)
except ValueError:
message.error('current', "Invalid quickmark '{}'".format(line))
message.error("Invalid quickmark '{}'".format(line))
else:
self.marks[key] = url
def prompt_save(self, win_id, url):
def prompt_save(self, url):
"""Prompt for a new quickmark name to be added and add it.
Args:
win_id: The current window ID.
url: The quickmark url as a QUrl.
"""
if not url.isValid():
urlutils.invalid_url_error(win_id, url, "save quickmark")
urlutils.invalid_url_error(url, "save quickmark")
return
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
message.ask_async(
win_id, "Add quickmark:", usertypes.PromptMode.text,
functools.partial(self.quickmark_add, win_id, urlstr))
"Add quickmark:", usertypes.PromptMode.text,
functools.partial(self.quickmark_add, urlstr),
text="Please enter a quickmark name for<br/><b>{}</b>".format(
html.escape(url.toDisplayString())))
@cmdutils.register(instance='quickmark-manager')
@cmdutils.argument('win_id', win_id=True)
def quickmark_add(self, win_id, url, name):
def quickmark_add(self, url, name):
"""Add a new quickmark.
You can view all saved quickmarks on the
link:qute://bookmarks[bookmarks page].
Args:
win_id: The window ID to display the errors in.
url: The url to add as quickmark.
name: The name for the new quickmark.
"""
# We don't raise cmdexc.CommandError here as this can be called async
# via prompt_save.
if not name:
message.error(win_id, "Can't set mark with empty name!")
message.error("Can't set mark with empty name!")
return
if not url:
message.error(win_id, "Can't set mark with empty URL!")
message.error("Can't set mark with empty URL!")
return
def set_mark():
@@ -201,10 +194,12 @@ class QuickmarkManager(UrlMarkManager):
self.marks[name] = url
self.changed.emit()
self.added.emit(name, url)
log.misc.debug("Added quickmark {} for {}".format(name, url))
if name in self.marks:
message.confirm_async(
win_id, "Override existing quickmark?", set_mark, default=True)
title="Override existing quickmark?",
yes_action=set_mark, default=True)
else:
set_mark()
@@ -272,12 +267,18 @@ class BookmarkManager(UrlMarkManager):
elif len(parts) == 1:
self.marks[parts[0]] = ''
def add(self, url, title):
def add(self, url, title, *, toggle=False):
"""Add a new bookmark.
Args:
url: The url to add as bookmark.
title: The title for the new bookmark.
toggle: remove the bookmark instead of raising an error if it
already exists.
Return:
True if the bookmark was added, and False if it was
removed (only possible if toggle is True).
"""
if not url.isValid():
errstr = urlutils.get_errstring(url)
@@ -286,8 +287,13 @@ class BookmarkManager(UrlMarkManager):
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
if urlstr in self.marks:
raise AlreadyExistsError("Bookmark already exists!")
if toggle:
del self.marks[urlstr]
return False
else:
raise AlreadyExistsError("Bookmark already exists!")
else:
self.marks[urlstr] = title
self.changed.emit()
self.added.emit(title, urlstr)
return True

View File

@@ -0,0 +1,437 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Generic web element related code.
Module attributes:
Group: Enum for different kinds of groups.
SELECTORS: CSS selectors for different groups of elements.
FILTERS: A dictionary of filter functions for the modes.
The filter for "links" filters javascript:-links and a-tags
without "href".
"""
import collections.abc
from PyQt5.QtCore import QUrl, Qt, QEvent, QTimer
from PyQt5.QtGui import QMouseEvent
from qutebrowser.config import config
from qutebrowser.keyinput import modeman
from qutebrowser.utils import log, usertypes, utils, qtutils, objreg
Group = usertypes.enum('Group', ['all', 'links', 'images', 'url', 'prevnext',
'inputs'])
SELECTORS = {
Group.all: ('a, area, textarea, select, input:not([type=hidden]), button, '
'frame, iframe, link, [onclick], [onmousedown], [role=link], '
'[role=option], [role=button], img'),
Group.links: 'a, area, link, [role=link]',
Group.images: 'img',
Group.url: '[src], [href]',
Group.prevnext: 'a, area, button, link, [role=button]',
Group.inputs: ('input[type=text], input[type=email], input[type=url], '
'input[type=tel], input[type=number], '
'input[type=password], input[type=search], '
'input:not([type]), textarea'),
}
def filter_links(elem):
return 'href' in elem and QUrl(elem['href']).scheme() != 'javascript'
FILTERS = {
Group.links: filter_links,
Group.prevnext: filter_links,
}
class Error(Exception):
"""Base class for WebElement errors."""
pass
class AbstractWebElement(collections.abc.MutableMapping):
"""A wrapper around QtWebKit/QtWebEngine web element.
Attributes:
tab: The tab associated with this element.
"""
def __init__(self, tab):
self._tab = tab
def __eq__(self, other):
raise NotImplementedError
def __str__(self):
raise NotImplementedError
def __getitem__(self, key):
raise NotImplementedError
def __setitem__(self, key, val):
raise NotImplementedError
def __delitem__(self, key):
raise NotImplementedError
def __iter__(self):
raise NotImplementedError
def __len__(self):
raise NotImplementedError
def __repr__(self):
try:
html = utils.compact_text(self.outer_xml(), 500)
except Error:
html = None
return utils.get_repr(self, html=html)
def has_frame(self):
"""Check if this element has a valid frame attached."""
raise NotImplementedError
def geometry(self):
"""Get the geometry for this element."""
raise NotImplementedError
def style_property(self, name, *, strategy):
"""Get the element style resolved with the given strategy."""
raise NotImplementedError
def classes(self):
"""Get a list of classes assigned to this element."""
raise NotImplementedError
def tag_name(self):
"""Get the tag name of this element.
The returned name will always be lower-case.
"""
raise NotImplementedError
def outer_xml(self):
"""Get the full HTML representation of this element."""
raise NotImplementedError
def value(self):
"""Get the value attribute for this element, or None."""
raise NotImplementedError
def set_value(self, value):
"""Set the element value."""
raise NotImplementedError
def insert_text(self, text):
"""Insert the given text into the element."""
raise NotImplementedError
def rect_on_view(self, *, elem_geometry=None, no_js=False):
"""Get the geometry of the element relative to the webview.
Uses the getClientRects() JavaScript method to obtain the collection of
rectangles containing the element and returns the first rectangle which
is large enough (larger than 1px times 1px). If all rectangles returned
by getClientRects() are too small, falls back to elem.rect_on_view().
Skipping of small rectangles is due to <a> elements containing other
elements with "display:block" style, see
https://github.com/qutebrowser/qutebrowser/issues/1298
Args:
elem_geometry: The geometry of the element, or None.
Calling QWebElement::geometry is rather expensive so
we want to avoid doing it twice.
no_js: Fall back to the Python implementation
"""
raise NotImplementedError
def is_writable(self):
"""Check whether an element is writable."""
return not ('disabled' in self or 'readonly' in self)
def is_content_editable(self):
"""Check if an element has a contenteditable attribute.
Args:
elem: The QWebElement to check.
Return:
True if the element has a contenteditable attribute,
False otherwise.
"""
try:
return self['contenteditable'].lower() not in ['false', 'inherit']
except KeyError:
return False
def _is_editable_object(self):
"""Check if an object-element is editable."""
if 'type' not in self:
log.webelem.debug("<object> without type clicked...")
return False
objtype = self['type'].lower()
if objtype.startswith('application/') or 'classid' in self:
# Let's hope flash/java stuff has an application/* mimetype OR
# at least a classid attribute. Oh, and let's hope images/...
# DON'T have a classid attribute. HTML sucks.
log.webelem.debug("<object type='{}'> clicked.".format(objtype))
return config.get('input', 'insert-mode-on-plugins')
else:
# Image/Audio/...
return False
def _is_editable_input(self):
"""Check if an input-element is editable.
Return:
True if the element is editable, False otherwise.
"""
try:
objtype = self['type'].lower()
except KeyError:
return self.is_writable()
else:
if objtype in ['text', 'email', 'url', 'tel', 'number', 'password',
'search']:
return self.is_writable()
else:
return False
def _is_editable_classes(self):
"""Check if an element is editable based on its classes.
Return:
True if the element is editable, False otherwise.
"""
# Beginnings of div-classes which are actually some kind of editor.
classes = {
'div': ['CodeMirror', # Javascript editor over a textarea
'kix-', # Google Docs editor
'ace_'], # http://ace.c9.io/
'pre': ['CodeMirror'],
}
relevant_classes = classes[self.tag_name()]
for klass in self.classes():
if any([klass.strip().startswith(e) for e in relevant_classes]):
return True
return False
def is_editable(self, strict=False):
"""Check whether we should switch to insert mode for this element.
Args:
strict: Whether to do stricter checking so only fields where we can
get the value match, for use with the :editor command.
Return:
True if we should switch to insert mode, False otherwise.
"""
roles = ('combobox', 'textbox')
log.webelem.debug("Checking if element is editable: {}".format(
repr(self)))
tag = self.tag_name()
if self.is_content_editable() and self.is_writable():
return True
elif self.get('role', None) in roles and self.is_writable():
return True
elif tag == 'input':
return self._is_editable_input()
elif tag == 'textarea':
return self.is_writable()
elif tag in ['embed', 'applet']:
# Flash/Java/...
return config.get('input', 'insert-mode-on-plugins') and not strict
elif tag == 'object':
return self._is_editable_object() and not strict
elif tag in ['div', 'pre']:
return self._is_editable_classes() and not strict
return False
def is_text_input(self):
"""Check if this element is some kind of text box."""
roles = ('combobox', 'textbox')
tag = self.tag_name()
return self.get('role', None) in roles or tag in ['input', 'textarea']
def remove_blank_target(self):
"""Remove target from link."""
raise NotImplementedError
def resolve_url(self, baseurl):
"""Resolve the URL in the element's src/href attribute.
Args:
baseurl: The URL to base relative URLs on as QUrl.
Return:
A QUrl with the absolute URL, or None.
"""
if baseurl.isRelative():
raise ValueError("Need an absolute base URL!")
for attr in ['href', 'src']:
if attr in self:
text = self[attr].strip()
break
else:
return None
url = QUrl(text)
if not url.isValid():
return None
if url.isRelative():
url = baseurl.resolved(url)
qtutils.ensure_valid(url)
return url
def _mouse_pos(self):
"""Get the position to click/hover."""
# Click the center of the largest square fitting into the top/left
# corner of the rectangle, this will help if part of the <a> element
# is hidden behind other elements
# https://github.com/qutebrowser/qutebrowser/issues/1005
rect = self.rect_on_view()
if rect.width() > rect.height():
rect.setWidth(rect.height())
else:
rect.setHeight(rect.width())
pos = rect.center()
if pos.x() < 0 or pos.y() < 0:
raise Error("Element position is out of view!")
return pos
def _click_fake_event(self, click_target):
"""Send a fake click event to the element."""
pos = self._mouse_pos()
log.webelem.debug("Sending fake click to {!r} at position {} with "
"target {}".format(self, pos, click_target))
modifiers = {
usertypes.ClickTarget.normal: Qt.NoModifier,
usertypes.ClickTarget.window: Qt.AltModifier | Qt.ShiftModifier,
usertypes.ClickTarget.tab: Qt.ControlModifier,
usertypes.ClickTarget.tab_bg: Qt.ControlModifier,
}
if config.get('tabs', 'background-tabs'):
modifiers[usertypes.ClickTarget.tab] |= Qt.ShiftModifier
else:
modifiers[usertypes.ClickTarget.tab_bg] |= Qt.ShiftModifier
events = [
QMouseEvent(QEvent.MouseMove, pos, Qt.NoButton, Qt.NoButton,
Qt.NoModifier),
QMouseEvent(QEvent.MouseButtonPress, pos, Qt.LeftButton,
Qt.LeftButton, modifiers[click_target]),
QMouseEvent(QEvent.MouseButtonRelease, pos, Qt.LeftButton,
Qt.NoButton, modifiers[click_target]),
]
for evt in events:
self._tab.send_event(evt)
def after_click():
"""Move cursor to end after clicking."""
if self.is_text_input() and self.is_editable():
self._tab.caret.move_to_end_of_document()
QTimer.singleShot(0, after_click)
def _click_editable(self, click_target):
"""Fake a click on an editable input field."""
raise NotImplementedError
def _click_js(self, click_target):
"""Fake a click by using the JS .click() method."""
raise NotImplementedError
def _click_href(self, click_target):
"""Fake a click on an element with a href by opening the link."""
baseurl = self._tab.url()
url = self.resolve_url(baseurl)
if url is None:
self._click_fake_event(click_target)
return
if click_target in [usertypes.ClickTarget.tab,
usertypes.ClickTarget.tab_bg]:
background = click_target == usertypes.ClickTarget.tab_bg
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._tab.win_id)
tabbed_browser.tabopen(url, background=background)
elif click_target == usertypes.ClickTarget.window:
from qutebrowser.mainwindow import mainwindow
window = mainwindow.MainWindow()
window.show()
window.tabbed_browser.tabopen(url)
else:
raise ValueError("Unknown ClickTarget {}".format(click_target))
def click(self, click_target, *, force_event=False):
"""Simulate a click on the element.
Args:
click_target: A usertypes.ClickTarget member, what kind of click
to simulate.
force_event: Force generating a fake mouse event.
"""
log.webelem.debug("Clicking {!r} with click_target {}, force_event {}"
.format(self, click_target, force_event))
if force_event:
self._click_fake_event(click_target)
return
href_tags = ['a', 'area', 'link']
if click_target == usertypes.ClickTarget.normal:
if self.tag_name() in href_tags:
log.webelem.debug("Clicking via JS click()")
self._click_js(click_target)
elif self.is_editable(strict=True):
log.webelem.debug("Clicking via JS focus()")
self._click_editable(click_target)
modeman.enter(self._tab.win_id, usertypes.KeyMode.insert,
'clicking input')
else:
self._click_fake_event(click_target)
elif click_target in [usertypes.ClickTarget.tab,
usertypes.ClickTarget.tab_bg,
usertypes.ClickTarget.window]:
if self.tag_name() in href_tags:
self._click_href(click_target)
else:
self._click_fake_event(click_target)
else:
raise ValueError("Unknown ClickTarget {}".format(click_target))
def hover(self):
"""Simulate a mouse hover over the element."""
pos = self._mouse_pos()
event = QMouseEvent(QEvent.MouseMove, pos, Qt.NoButton, Qt.NoButton,
Qt.NoModifier)
self._tab.send_event(event)

View File

@@ -0,0 +1,43 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Wrapper over a QWebEngineCertificateError."""
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEngineCertificateError
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.utils import usertypes, utils, debug
class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper):
"""A wrapper over a QWebEngineCertificateError."""
def __str__(self):
return self._error.errorDescription()
def __repr__(self):
return utils.get_repr(
self, error=debug.qenum_key(QWebEngineCertificateError,
self._error.error()),
string=str(self))
def is_overridable(self):
return self._error.isOverridable()

View File

@@ -0,0 +1,71 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""A request interceptor taking care of adblocking and custom headers."""
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.config import config
from qutebrowser.browser import shared
from qutebrowser.utils import utils, log
class RequestInterceptor(QWebEngineUrlRequestInterceptor):
"""Handle ad blocking and custom headers."""
def __init__(self, host_blocker, parent=None):
super().__init__(parent)
self._host_blocker = host_blocker
def install(self, profile):
"""Install the interceptor on the given QWebEngineProfile."""
profile.setRequestInterceptor(self)
# Gets called in the IO thread -> showing crash window will fail
@utils.prevent_exceptions(None)
def interceptRequest(self, info):
"""Handle the given request.
Reimplementing this virtual function and setting the interceptor on a
profile makes it possible to intercept URL requests. This function is
executed on the IO thread, and therefore running long tasks here will
block networking.
info contains the information about the URL request and will track
internally whether its members have been altered.
Args:
info: QWebEngineUrlRequestInfo &info
"""
# FIXME:qtwebengine only block ads for NavigationTypeOther?
if (bytes(info.requestMethod()) == b'GET' and
self._host_blocker.is_blocked(info.requestUrl())):
log.webview.info("Request to {} blocked by host blocker.".format(
info.requestUrl().host()))
info.block(True)
for header, value in shared.custom_headers():
info.setHttpHeader(header, value)
user_agent = config.get('network', 'user-agent')
if user_agent is not None:
info.setHttpHeader(b'User-Agent', user_agent.encode('ascii'))

View File

@@ -0,0 +1,117 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QWebHistory serializer for QtWebEngine."""
import time
from PyQt5.QtCore import QByteArray, QDataStream, QIODevice, QUrl
from qutebrowser.utils import qtutils
HISTORY_STREAM_VERSION = 3
def _serialize_item(item, stream):
"""Serialize a single WebHistoryItem into a QDataStream.
Args:
item: The WebHistoryItem to write.
stream: The QDataStream to write to.
"""
### Thanks to Otter Browser:
### https://github.com/OtterBrowser/otter-browser/blob/v0.9.10/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp#L1210
### src/core/web_contents_adapter.cpp serializeNavigationHistory
## toQt(entry->GetVirtualURL());
qtutils.serialize_stream(stream, item.url)
## toQt(entry->GetTitle());
stream.writeQString(item.title)
## QByteArray(encodedPageState.data(), encodedPageState.size());
qtutils.serialize_stream(stream, QByteArray())
## static_cast<qint32>(entry->GetTransitionType());
# chromium/ui/base/page_transition_types.h
stream.writeInt32(0) # PAGE_TRANSITION_LINK
## entry->GetHasPostData();
stream.writeBool(False)
## toQt(entry->GetReferrer().url);
qtutils.serialize_stream(stream, QUrl())
## static_cast<qint32>(entry->GetReferrer().policy);
# chromium/third_party/WebKit/public/platform/WebReferrerPolicy.h
stream.writeInt32(0) # WebReferrerPolicyAlways
## toQt(entry->GetOriginalRequestURL());
qtutils.serialize_stream(stream, item.original_url)
## entry->GetIsOverridingUserAgent();
stream.writeBool(False)
## static_cast<qint64>(entry->GetTimestamp().ToInternalValue());
stream.writeInt64(int(time.time()))
## entry->GetHttpStatusCode();
stream.writeInt(200)
def serialize(items):
"""Serialize a list of QWebHistoryItems to a data stream.
Args:
items: An iterable of WebHistoryItems.
Return:
A (stream, data, user_data) tuple.
stream: The reset QDataStream.
data: The QByteArray with the raw data.
cur_user_data: The user data for the current item or None.
Warning:
If 'data' goes out of scope, reading from 'stream' will result in a
segfault!
"""
data = QByteArray()
stream = QDataStream(data, QIODevice.ReadWrite)
cur_user_data = None
current_idx = None
for i, item in enumerate(items):
if item.active:
if current_idx is not None:
raise ValueError("Multiple active items ({} and {}) "
"found!".format(current_idx, i))
current_idx = i
cur_user_data = item.user_data
if items:
if current_idx is None:
raise ValueError("No active item found!")
else:
current_idx = -1
### src/core/web_contents_adapter.cpp serializeNavigationHistory
# kHistoryStreamVersion
stream.writeInt(HISTORY_STREAM_VERSION)
# count
stream.writeInt(len(items))
# currentIndex
stream.writeInt(current_idx)
for item in items:
_serialize_item(item, stream)
stream.device().reset()
qtutils.check_qdatastream(stream)
return stream, data, cur_user_data

View File

@@ -0,0 +1,210 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QtWebEngine specific code for downloads."""
import re
import os.path
import urllib
import functools
from PyQt5.QtCore import pyqtSlot, Qt
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEngineDownloadItem
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import downloads
from qutebrowser.utils import debug, usertypes, message, log, qtutils
class DownloadItem(downloads.AbstractDownloadItem):
"""A wrapper over a QWebEngineDownloadItem.
Attributes:
_qt_item: The wrapped item.
"""
def __init__(self, qt_item, parent=None):
super().__init__(parent)
self._qt_item = qt_item
qt_item.downloadProgress.connect(self.stats.on_download_progress)
qt_item.stateChanged.connect(self._on_state_changed)
def _is_page_download(self):
"""Check if this item is a page (i.e. mhtml) download."""
return (self._qt_item.savePageFormat() !=
QWebEngineDownloadItem.UnknownSaveFormat)
@pyqtSlot(QWebEngineDownloadItem.DownloadState)
def _on_state_changed(self, state):
state_name = debug.qenum_key(QWebEngineDownloadItem, state)
log.downloads.debug("State for {!r} changed to {}".format(
self, state_name))
if state == QWebEngineDownloadItem.DownloadRequested:
pass
elif state == QWebEngineDownloadItem.DownloadInProgress:
pass
elif state == QWebEngineDownloadItem.DownloadCompleted:
log.downloads.debug("Download {} finished".format(self.basename))
if self._is_page_download():
# Same logging as QtWebKit mhtml downloads.
log.downloads.debug("File successfully written.")
self.successful = True
self.done = True
self.finished.emit()
self.stats.finish()
elif state == QWebEngineDownloadItem.DownloadCancelled:
self.successful = False
self.done = True
self.cancelled.emit()
self.stats.finish()
elif state == QWebEngineDownloadItem.DownloadInterrupted:
self.successful = False
self.done = True
# https://bugreports.qt.io/browse/QTBUG-56839
self.error.emit("Download failed")
self.stats.finish()
else:
raise ValueError("_on_state_changed was called with unknown state "
"{}".format(state_name))
def _do_die(self):
self._qt_item.downloadProgress.disconnect()
self._qt_item.cancel()
def _do_cancel(self):
self._qt_item.cancel()
def retry(self):
# https://bugreports.qt.io/browse/QTBUG-56840
raise downloads.UnsupportedOperationError
def _get_open_filename(self):
return self._filename
def _set_fileobj(self, fileobj):
raise downloads.UnsupportedOperationError
def _set_tempfile(self, fileobj):
self._set_filename(fileobj.name, force_overwrite=True,
remember_directory=False)
def _ensure_can_set_filename(self, filename):
state = self._qt_item.state()
if state != QWebEngineDownloadItem.DownloadRequested:
state_name = debug.qenum_key(QWebEngineDownloadItem, state)
raise ValueError("Trying to set filename {} on {!r} which is "
"state {} (not in requested state)!".format(
filename, self, state_name))
def _ask_confirm_question(self, title, msg):
no_action = functools.partial(self.cancel, remove_data=False)
question = usertypes.Question()
question.title = title
question.text = msg
question.mode = usertypes.PromptMode.yesno
question.answered_yes.connect(self._after_set_filename)
question.answered_no.connect(no_action)
question.cancelled.connect(no_action)
self.cancelled.connect(question.abort)
self.error.connect(question.abort)
message.global_bridge.ask(question, blocking=True)
def _after_set_filename(self):
self._qt_item.setPath(self._filename)
self._qt_item.accept()
def _get_suggested_filename(path):
"""Convert a path we got from chromium to a suggested filename.
Chromium thinks we want to download stuff to ~/Download, so even if we
don't, we get downloads with a suffix like (1) for files existing there.
We simply strip the suffix off via regex.
See https://bugreports.qt.io/browse/QTBUG-56978
"""
filename = os.path.basename(path)
filename = re.sub(r'\([0-9]+\)$', '', filename)
if not qtutils.version_check('5.8.1'):
# https://bugreports.qt.io/browse/QTBUG-58155
filename = urllib.parse.unquote(filename)
# Doing basename a *second* time because there could be a %2F in
# there...
filename = os.path.basename(filename)
return filename
class DownloadManager(downloads.AbstractDownloadManager):
"""Manager for currently running downloads.
Attributes:
_mhtml_target: DownloadTarget for the next MHTML download.
"""
def __init__(self, parent=None):
super().__init__(parent)
self._mhtml_target = None
def install(self, profile):
"""Set up the download manager on a QWebEngineProfile."""
profile.downloadRequested.connect(self.handle_download,
Qt.DirectConnection)
@pyqtSlot(QWebEngineDownloadItem)
def handle_download(self, qt_item):
"""Start a download coming from a QWebEngineProfile."""
suggested_filename = _get_suggested_filename(qt_item.path())
download = DownloadItem(qt_item)
self._init_item(download, auto_remove=False,
suggested_filename=suggested_filename)
if self._mhtml_target is not None:
download.set_target(self._mhtml_target)
self._mhtml_target = None
return
filename = downloads.immediate_download_path()
if filename is not None:
# User doesn't want to be asked, so just use the download_dir
target = downloads.FileDownloadTarget(filename)
download.set_target(target)
return
# Ask the user for a filename - needs to be blocking!
question = downloads.get_filename_question(
suggested_filename=suggested_filename, url=qt_item.url(),
parent=self)
self._init_filename_question(question, download)
message.global_bridge.ask(question, blocking=True)
# The filename is set via the question.answered signal, connected in
# _init_filename_question.
def get_mhtml(self, tab, target):
"""Download the given tab as mhtml to the given target."""
assert tab.backend == usertypes.Backend.QtWebEngine
assert self._mhtml_target is None, self._mhtml_target
self._mhtml_target = target
tab.action.save_page()

View File

@@ -0,0 +1,193 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
# FIXME:qtwebengine remove this once the stubs are gone
# pylint: disable=unused-variable
"""QtWebEngine specific part of the web element API."""
from PyQt5.QtCore import QRect, Qt, QPoint, QEventLoop
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QApplication
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEngineSettings
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.utils import log, javascript
from qutebrowser.browser import webelem
class WebEngineElement(webelem.AbstractWebElement):
"""A web element for QtWebEngine, using JS under the hood."""
def __init__(self, js_dict, tab):
super().__init__(tab)
self._id = js_dict['id']
self._js_dict = js_dict
def __str__(self):
return self._js_dict.get('text', '')
def __eq__(self, other):
if not isinstance(other, WebEngineElement):
return NotImplemented
return self._id == other._id # pylint: disable=protected-access
def __getitem__(self, key):
attrs = self._js_dict['attributes']
return attrs[key]
def __setitem__(self, key, val):
self._js_dict['attributes'][key] = val
js_code = javascript.assemble('webelem', 'set_attribute', self._id,
key, val)
self._tab.run_js_async(js_code)
def __delitem__(self, key):
log.stub()
def __iter__(self):
return iter(self._js_dict['attributes'])
def __len__(self):
return len(self._js_dict['attributes'])
def has_frame(self):
return True
def geometry(self):
log.stub()
return QRect()
def style_property(self, name, *, strategy):
log.stub()
return ''
def classes(self):
"""Get a list of classes assigned to this element."""
return self._js_dict['class_name'].split()
def tag_name(self):
"""Get the tag name of this element.
The returned name will always be lower-case.
"""
return self._js_dict['tag_name'].lower()
def outer_xml(self):
"""Get the full HTML representation of this element."""
return self._js_dict['outer_xml']
def value(self):
return self._js_dict.get('value', None)
def set_value(self, value):
js_code = javascript.assemble('webelem', 'set_value', self._id, value)
self._tab.run_js_async(js_code)
def insert_text(self, text):
if not self.is_editable(strict=True):
raise webelem.Error("Element is not editable!")
log.webelem.debug("Inserting text into element {!r}".format(self))
js_code = javascript.assemble('webelem', 'insert_text', self._id, text)
self._tab.run_js_async(js_code)
def rect_on_view(self, *, elem_geometry=None, no_js=False):
"""Get the geometry of the element relative to the webview.
Skipping of small rectangles is due to <a> elements containing other
elements with "display:block" style, see
https://github.com/qutebrowser/qutebrowser/issues/1298
Args:
elem_geometry: The geometry of the element, or None.
Calling QWebElement::geometry is rather expensive so
we want to avoid doing it twice.
no_js: Fall back to the Python implementation
"""
rects = self._js_dict['rects']
for rect in rects:
# FIXME:qtwebengine
# width = rect.get("width", 0)
# height = rect.get("height", 0)
width = rect['width']
height = rect['height']
left = rect['left']
top = rect['top']
if width > 1 and height > 1:
# Fix coordinates according to zoom level
# We're not checking for zoom-text-only here as that doesn't
# exist for QtWebEngine.
zoom = self._tab.zoom.factor()
rect = QRect(left * zoom, top * zoom,
width * zoom, height * zoom)
# FIXME:qtwebengine
# frame = self._elem.webFrame()
# while frame is not None:
# # Translate to parent frames' position (scroll position
# # is taken care of inside getClientRects)
# rect.translate(frame.geometry().topLeft())
# frame = frame.parentFrame()
return rect
log.webelem.debug("Couldn't find rectangle for {!r} ({})".format(
self, rects))
return QRect()
def remove_blank_target(self):
if self._js_dict['attributes'].get('target') == '_blank':
self._js_dict['attributes']['target'] = '_top'
js_code = javascript.assemble('webelem', 'remove_blank_target',
self._id)
self._tab.run_js_async(js_code)
def _click_editable(self, click_target):
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-58515
# pylint doesn't know about Qt.MouseEventSynthesizedBySystem
# because it was added in Qt 5.6, but we can be sure we use that with
# QtWebEngine.
# pylint: disable=no-member
ev = QMouseEvent(QMouseEvent.MouseButtonPress, QPoint(0, 0),
QPoint(0, 0), QPoint(0, 0), Qt.NoButton, Qt.NoButton,
Qt.NoModifier, Qt.MouseEventSynthesizedBySystem)
# pylint: enable=no-member
self._tab.send_event(ev)
# This actually "clicks" the element by calling focus() on it in JS.
js_code = javascript.assemble('webelem', 'focus', self._id)
self._tab.run_js_async(js_code)
def _click_js(self, _click_target):
settings = QWebEngineSettings.globalSettings()
attribute = QWebEngineSettings.JavascriptCanOpenWindows
could_open_windows = settings.testAttribute(attribute)
settings.setAttribute(attribute, True)
# Get QtWebEngine do apply the settings
# (it does so with a 0ms QTimer...)
# This is also used in Qt's tests:
# https://github.com/qt/qtwebengine/commit/5e572e88efa7ba7c2b9138ec19e606d3e345ac90
qapp = QApplication.instance()
qapp.processEvents(QEventLoop.ExcludeSocketNotifiers |
QEventLoop.ExcludeUserInputEvents)
def reset_setting(_arg):
settings.setAttribute(attribute, could_open_windows)
js_code = javascript.assemble('webelem', 'click', self._id)
self._tab.run_js_async(js_code, reset_setting)

View File

@@ -0,0 +1,52 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Customized QWebInspector for QtWebEngine."""
import os
from PyQt5.QtCore import QUrl
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEngineView
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import inspector
class WebEngineInspector(inspector.AbstractWebInspector):
"""A web inspector for QtWebEngine."""
def __init__(self, parent=None):
super().__init__(parent)
self.port = None
view = QWebEngineView()
self._set_widget(view)
def inspect(self, _page):
"""Set up the inspector."""
try:
port = int(os.environ['QTWEBENGINE_REMOTE_DEBUGGING'])
except KeyError:
raise inspector.WebInspectorError(
"Debugging is not enabled. See 'qutebrowser --help' for "
"details.")
url = QUrl('http://localhost:{}/'.format(port))
self._widget.load(url)
self.show()

View File

@@ -0,0 +1,78 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QtWebEngine specific qute:* handlers and glue code."""
from PyQt5.QtCore import QBuffer, QIODevice
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler,
QWebEngineUrlRequestJob)
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import qutescheme
from qutebrowser.utils import log
class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
"""Handle qute:* requests on QtWebEngine."""
def install(self, profile):
"""Install the handler for qute: URLs on the given profile."""
profile.installUrlSchemeHandler(b'qute', self)
def requestStarted(self, job):
"""Handle a request for a qute: scheme.
This method must be reimplemented by all custom URL scheme handlers.
The request is asynchronous and does not need to be handled right away.
Args:
job: QWebEngineUrlRequestJob
"""
url = job.requestUrl()
assert job.requestMethod() == b'GET'
assert url.scheme() == 'qute'
log.misc.debug("Got request for {}".format(url.toDisplayString()))
try:
mimetype, data = qutescheme.data_for_url(url)
except qutescheme.NoHandlerFound:
log.misc.debug("No handler found for {}".format(
url.toDisplayString()))
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
except qutescheme.QuteSchemeOSError:
# FIXME:qtwebengine how do we show a better error here?
log.misc.exception("OSError while handling qute:* URL")
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
except qutescheme.QuteSchemeError:
# FIXME:qtwebengine how do we show a better error here?
log.misc.exception("Error while handling qute:* URL")
job.fail(QWebEngineUrlRequestJob.RequestFailed)
else:
log.misc.debug("Returning {} data".format(mimetype))
# We can't just use the QBuffer constructor taking a QByteArray,
# because that somehow segfaults...
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
buf = QBuffer(parent=self)
buf.open(QIODevice.WriteOnly)
buf.write(data)
buf.seek(0)
buf.close()
job.reply(mimetype.encode('ascii'), buf)

View File

@@ -0,0 +1,288 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Bridge from QWebEngineSettings to our own settings.
Module attributes:
ATTRIBUTES: A mapping from internal setting names to QWebEngineSetting enum
constants.
"""
import os
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
QWebEngineScript)
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import shared
from qutebrowser.config import config, websettings
from qutebrowser.utils import objreg, utils, standarddir, javascript
class Attribute(websettings.Attribute):
"""A setting set via QWebEngineSettings::setAttribute."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
ENUM_BASE = QWebEngineSettings
class Setter(websettings.Setter):
"""A setting set via QWebEngineSettings getter/setter methods."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
class NullStringSetter(websettings.NullStringSetter):
"""A setter for settings requiring a null QString as default."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
class StaticSetter(websettings.StaticSetter):
"""A setting set via static QWebEngineSettings getter/setter methods."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
class ProfileSetter(websettings.Base):
"""A setting set on the QWebEngineProfile."""
def __init__(self, getter, setter):
super().__init__()
profile = QWebEngineProfile.defaultProfile()
self._getter = getattr(profile, getter)
self._setter = getattr(profile, setter)
def get(self, settings=None):
utils.unused(settings)
return self._getter()
def _set(self, value, settings=None):
utils.unused(settings)
self._setter(value)
class PersistentCookiePolicy(ProfileSetter):
"""The cookies -> store setting is different from other settings."""
def __init__(self):
super().__init__(getter='persistentCookiesPolicy',
setter='setPersistentCookiesPolicy')
def get(self, settings=None):
utils.unused(settings)
return config.get('content', 'cookies-store')
def _set(self, value, settings=None):
utils.unused(settings)
self._setter(
QWebEngineProfile.AllowPersistentCookies if value else
QWebEngineProfile.NoPersistentCookies
)
def _init_stylesheet(profile):
"""Initialize custom stylesheets.
Mostly inspired by QupZilla:
https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101
https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/tools/scripts.cpp#L119-L132
FIXME:qtwebengine Use QWebEngineStyleSheet once that's available
https://codereview.qt-project.org/#/c/148671/
"""
old_script = profile.scripts().findScript('_qute_stylesheet')
if not old_script.isNull():
profile.scripts().remove(old_script)
css = shared.get_user_stylesheet()
source = """
(function() {{
var css = document.createElement('style');
css.setAttribute('type', 'text/css');
css.appendChild(document.createTextNode('{}'));
document.getElementsByTagName('head')[0].appendChild(css);
}})()
""".format(javascript.string_escape(css))
script = QWebEngineScript()
script.setName('_qute_stylesheet')
script.setInjectionPoint(QWebEngineScript.DocumentReady)
script.setWorldId(QWebEngineScript.ApplicationWorld)
script.setRunsOnSubFrames(True)
script.setSourceCode(source)
profile.scripts().insert(script)
def _init_profile(profile):
"""Initialize settings set on the QWebEngineProfile."""
profile.setCachePath(os.path.join(standarddir.cache(), 'webengine'))
profile.setPersistentStoragePath(
os.path.join(standarddir.data(), 'webengine'))
def update_settings(section, option):
"""Update global settings when qwebsettings changed."""
websettings.update_mappings(MAPPINGS, section, option)
profile = QWebEngineProfile.defaultProfile()
if section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
_init_stylesheet(profile)
def init(args):
"""Initialize the global QWebSettings."""
if args.enable_webengine_inspector:
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
profile = QWebEngineProfile.defaultProfile()
_init_profile(profile)
_init_stylesheet(profile)
# We need to do this here as a WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58650
PersistentCookiePolicy().set(config.get('content', 'cookies-store'))
Attribute(QWebEngineSettings.FullScreenSupportEnabled).set(True)
websettings.init_mappings(MAPPINGS)
objreg.get('config').changed.connect(update_settings)
def shutdown():
# FIXME:qtwebengine do we need to do something for a clean shutdown here?
pass
# Missing QtWebEngine attributes:
# - ScreenCaptureEnabled
# - Accelerated2dCanvasEnabled
# - AutoLoadIconsForPage
# - TouchIconsEnabled
# - FocusOnNavigationEnabled (5.8)
# - AllowRunningInsecureContent (5.8)
#
# Missing QtWebEngine fonts:
# - FantasyFont
# - PictographFont
MAPPINGS = {
'content': {
'allow-images':
Attribute(QWebEngineSettings.AutoLoadImages),
'allow-javascript':
Attribute(QWebEngineSettings.JavascriptEnabled),
'javascript-can-open-windows-automatically':
Attribute(QWebEngineSettings.JavascriptCanOpenWindows),
'javascript-can-access-clipboard':
Attribute(QWebEngineSettings.JavascriptCanAccessClipboard),
'allow-plugins':
Attribute(QWebEngineSettings.PluginsEnabled),
'hyperlink-auditing':
Attribute(QWebEngineSettings.HyperlinkAuditingEnabled),
'local-content-can-access-remote-urls':
Attribute(QWebEngineSettings.LocalContentCanAccessRemoteUrls),
'local-content-can-access-file-urls':
Attribute(QWebEngineSettings.LocalContentCanAccessFileUrls),
# https://bugreports.qt.io/browse/QTBUG-58650
# 'cookies-store':
# PersistentCookiePolicy(),
'webgl':
Attribute(QWebEngineSettings.WebGLEnabled),
},
'input': {
'spatial-navigation':
Attribute(QWebEngineSettings.SpatialNavigationEnabled),
'links-included-in-focus-chain':
Attribute(QWebEngineSettings.LinksIncludedInFocusChain),
},
'fonts': {
'web-family-standard':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.StandardFont]),
'web-family-fixed':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.FixedFont]),
'web-family-serif':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.SerifFont]),
'web-family-sans-serif':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.SansSerifFont]),
'web-family-cursive':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.CursiveFont]),
'web-family-fantasy':
Setter(getter=QWebEngineSettings.fontFamily,
setter=QWebEngineSettings.setFontFamily,
args=[QWebEngineSettings.FantasyFont]),
'web-size-minimum':
Setter(getter=QWebEngineSettings.fontSize,
setter=QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.MinimumFontSize]),
'web-size-minimum-logical':
Setter(getter=QWebEngineSettings.fontSize,
setter=QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.MinimumLogicalFontSize]),
'web-size-default':
Setter(getter=QWebEngineSettings.fontSize,
setter=QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.DefaultFontSize]),
'web-size-default-fixed':
Setter(getter=QWebEngineSettings.fontSize,
setter=QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.DefaultFixedFontSize]),
},
'ui': {
'smooth-scrolling':
Attribute(QWebEngineSettings.ScrollAnimatorEnabled),
},
'storage': {
'local-storage':
Attribute(QWebEngineSettings.LocalStorageEnabled),
'cache-size':
ProfileSetter(getter='httpCacheMaximumSize',
setter='setHttpCacheMaximumSize')
},
'general': {
'xss-auditing':
Attribute(QWebEngineSettings.XSSAuditingEnabled),
'default-encoding':
Setter(getter=QWebEngineSettings.defaultTextEncoding,
setter=QWebEngineSettings.setDefaultTextEncoding),
}
}
try:
MAPPINGS['general']['print-element-backgrounds'] = Attribute(
QWebEngineSettings.PrintElementBackgrounds)
except AttributeError:
# Added in Qt 5.8
pass

View File

@@ -22,16 +22,77 @@
"""Wrapper over a QWebEngineView."""
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint
from PyQt5.QtGui import QKeyEvent, QIcon
from PyQt5.QtWidgets import QApplication
import functools
import sip
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QUrl, QTimer
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtNetwork import QAuthenticator
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import (QWebEnginePage, QWebEngineScript,
QWebEngineProfile)
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import browsertab
from qutebrowser.browser.webengine import webview
from qutebrowser.utils import usertypes, qtutils, log, utils
from qutebrowser.browser import browsertab, mouse, shared
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
interceptor, webenginequtescheme,
webenginedownloads)
from qutebrowser.misc import miscwidgets
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
objreg, jinja)
_qute_scheme_handler = None
def init():
"""Initialize QtWebEngine-specific modules."""
# For some reason we need to keep a reference, otherwise the scheme handler
# won't work...
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
global _qute_scheme_handler
app = QApplication.instance()
profile = QWebEngineProfile.defaultProfile()
log.init.debug("Initializing qute:* handler...")
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
_qute_scheme_handler.install(profile)
log.init.debug("Initializing request interceptor...")
host_blocker = objreg.get('host-blocker')
req_interceptor = interceptor.RequestInterceptor(
host_blocker, parent=app)
req_interceptor.install(profile)
log.init.debug("Initializing QtWebEngine downloads...")
download_manager = webenginedownloads.DownloadManager(parent=app)
download_manager.install(profile)
objreg.register('webengine-download-manager', download_manager)
# Mapping worlds from usertypes.JsWorld to QWebEngineScript world IDs.
_JS_WORLD_MAP = {
usertypes.JsWorld.main: QWebEngineScript.MainWorld,
usertypes.JsWorld.application: QWebEngineScript.ApplicationWorld,
usertypes.JsWorld.user: QWebEngineScript.UserWorld,
usertypes.JsWorld.jseval: QWebEngineScript.UserWorld + 1,
}
class WebEngineAction(browsertab.AbstractAction):
"""QtWebKit implementations related to web actions."""
def _action(self, action):
self._widget.triggerPageAction(action)
def exit_fullscreen(self):
self._action(QWebEnginePage.ExitFullScreen)
def save_page(self):
"""Save the current page."""
self._action(QWebEnginePage.SavePage)
class WebEnginePrinting(browsertab.AbstractPrinting):
@@ -39,20 +100,24 @@ class WebEnginePrinting(browsertab.AbstractPrinting):
"""QtWebEngine implementations related to printing."""
def check_pdf_support(self):
if not hasattr(self._widget.page(), 'printToPdf'):
raise browsertab.WebTabError(
"Printing to PDF is unsupported with QtWebEngine on Qt > 5.7")
return True
def check_printer_support(self):
if not hasattr(self._widget.page(), 'print'):
raise browsertab.WebTabError(
"Printing is unsupported with QtWebEngine on Qt < 5.8")
def check_preview_support(self):
raise browsertab.WebTabError(
"Printing is unsupported with QtWebEngine")
"Print previews are unsupported with QtWebEngine")
def to_pdf(self, filename):
self._widget.page().printToPdf(filename)
def to_printer(self, printer):
# Should never be called
assert False
def to_printer(self, printer, callback=None):
if callback is None:
callback = lambda _ok: None
self._widget.page().print(printer, callback)
class WebEngineSearch(browsertab.AbstractSearch):
@@ -95,7 +160,7 @@ class WebEngineSearch(browsertab.AbstractSearch):
flags &= ~QWebEnginePage.FindBackward
else:
flags |= QWebEnginePage.FindBackward
self._find(self.text, self._flags, result_cb)
self._find(self.text, flags, result_cb)
def next_result(self, *, result_cb=None):
self._find(self.text, self._flags, result_cb)
@@ -107,11 +172,11 @@ class WebEngineCaret(browsertab.AbstractCaret):
@pyqtSlot(usertypes.KeyMode)
def _on_mode_entered(self, mode):
log.stub()
pass
@pyqtSlot(usertypes.KeyMode)
def _on_mode_left(self):
log.stub()
pass
def move_to_next_line(self, count=1):
log.stub()
@@ -169,7 +234,7 @@ class WebEngineCaret(browsertab.AbstractCaret):
def selection(self, html=False):
if html:
raise NotImplementedError
raise browsertab.UnsupportedOperationError
return self._widget.selectedText()
def follow_selected(self, *, tab=False):
@@ -182,45 +247,55 @@ class WebEngineScroller(browsertab.AbstractScroller):
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
self._pos_perc = (None, None)
self._pos_perc = (0, 0)
self._pos_px = QPoint()
self._at_bottom = False
def _init_widget(self, widget):
super()._init_widget(widget)
page = widget.page()
try:
page.scrollPositionChanged.connect(
self._on_scroll_pos_changed)
except AttributeError:
log.stub('scrollPositionChanged, on Qt < 5.7')
self._on_scroll_pos_changed()
page.scrollPositionChanged.connect(self._update_pos)
def _key_press(self, key, count=1):
# FIXME:qtwebengine Abort scrolling if the minimum/maximum was reached.
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier, 0, 0, 0)
recipient = self._widget.focusProxy()
for _ in range(count):
# If we get a segfault here, we might want to try sendEvent
# instead.
QApplication.postEvent(recipient, press_evt)
QApplication.postEvent(recipient, release_evt)
for _ in range(min(count, 5000)):
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier,
0, 0, 0)
self._tab.send_event(press_evt)
self._tab.send_event(release_evt)
@pyqtSlot()
def _on_scroll_pos_changed(self):
def _update_pos(self):
"""Update the scroll position attributes when it changed."""
def update_scroll_pos(jsret):
def update_pos_cb(jsret):
"""Callback after getting scroll position via JS."""
assert isinstance(jsret, dict)
self._pos_perc = (jsret['perc']['x'], jsret['perc']['y'])
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'])
dx = jsret['scroll']['width'] - jsret['inner']['width']
if dx == 0:
perc_x = 0
else:
perc_x = min(100, round(100 / dx * jsret['px']['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']))
self._at_bottom = dy >= jsret['px']['y']
self._pos_perc = perc_x, perc_y
self.perc_changed.emit(*self._pos_perc)
js_code = """
{scroll_js}
scroll_pos();
""".format(scroll_js=utils.read_file('javascript/scroll.js'))
self._tab.run_js_async(js_code, update_scroll_pos)
js_code = javascript.assemble('scroll', 'pos')
self._tab.run_js_async(js_code, update_pos_cb)
def pos_px(self):
return self._pos_px
@@ -229,26 +304,18 @@ class WebEngineScroller(browsertab.AbstractScroller):
return self._pos_perc
def to_perc(self, x=None, y=None):
js_code = """
{scroll_js}
scroll_to_perc({x}, {y});
""".format(scroll_js=utils.read_file('javascript/scroll.js'),
x='undefined' if x is None else x,
y='undefined' if y is None else y)
js_code = javascript.assemble('scroll', 'to_perc', x, y)
self._tab.run_js_async(js_code)
def to_point(self, point):
self._tab.run_js_async("window.scroll({x}, {y});".format(
x=point.x(), y=point.y()))
js_code = javascript.assemble('window', 'scroll', point.x(), point.y())
self._tab.run_js_async(js_code)
def delta(self, x=0, y=0):
self._tab.run_js_async("window.scrollBy({x}, {y});".format(x=x, y=y))
self._tab.run_js_async(javascript.assemble('window', 'scrollBy', x, y))
def delta_page(self, x=0, y=0):
js_code = """
{scroll_js}
scroll_delta_page({x}, {y});
""".format(scroll_js=utils.read_file('javascript/scroll.js'), x=x, y=y)
js_code = javascript.assemble('scroll', 'delta_page', x, y)
self._tab.run_js_async(js_code)
def up(self, count=1):
@@ -279,7 +346,7 @@ class WebEngineScroller(browsertab.AbstractScroller):
return self.pos_px().y() == 0
def at_bottom(self):
log.stub()
return self._at_bottom
class WebEngineHistory(browsertab.AbstractHistory):
@@ -302,13 +369,26 @@ class WebEngineHistory(browsertab.AbstractHistory):
return self._history.canGoForward()
def serialize(self):
# WORKAROUND for https://github.com/qutebrowser/qutebrowser/issues/2289
# FIXME:qtwebengine can we get rid of this with Qt 5.8.1?
scheme = self._history.currentItem().url().scheme()
if scheme in ['view-source', 'chrome']:
raise browsertab.WebTabError("Can't serialize special URL!")
return qtutils.serialize(self._history)
def deserialize(self, data):
return qtutils.deserialize(data, self._history)
def load_items(self, items):
log.stub()
stream, _data, cur_data = tabhistory.serialize(items)
qtutils.deserialize_stream(stream, self._history)
if cur_data is not None:
if 'zoom' in cur_data:
self._tab.zoom.set_factor(cur_data['zoom'])
if ('scroll-pos' in cur_data and
self._tab.scroller.pos_px() == QPoint(0, 0)):
QTimer.singleShot(0, functools.partial(
self._tab.scroller.to_point, cur_data['scroll-pos']))
class WebEngineZoom(browsertab.AbstractZoom):
@@ -322,13 +402,80 @@ class WebEngineZoom(browsertab.AbstractZoom):
return self._widget.zoomFactor()
class WebEngineElements(browsertab.AbstractElements):
"""QtWebEngine implemementations related to elements on the page."""
def _js_cb_multiple(self, callback, js_elems):
"""Handle found elements coming from JS and call the real callback.
Args:
callback: The callback to call with the found elements.
Called with None if there was an error.
js_elems: The elements serialized from javascript.
"""
if js_elems is None:
callback(None)
return
elems = []
for js_elem in js_elems:
elem = webengineelem.WebEngineElement(js_elem, tab=self._tab)
elems.append(elem)
callback(elems)
def _js_cb_single(self, callback, js_elem):
"""Handle a found focus elem coming from JS and call the real callback.
Args:
callback: The callback to call with the found element.
Called with a WebEngineElement or None.
js_elem: The element serialized from javascript.
"""
debug_str = ('None' if js_elem is None
else utils.elide(repr(js_elem), 1000))
log.webview.debug("Got element from JS: {}".format(debug_str))
if js_elem is None:
callback(None)
else:
elem = webengineelem.WebEngineElement(js_elem, tab=self._tab)
callback(elem)
def find_css(self, selector, callback, *, only_visible=False):
js_code = javascript.assemble('webelem', 'find_all', selector,
only_visible)
js_cb = functools.partial(self._js_cb_multiple, callback)
self._tab.run_js_async(js_code, js_cb)
def find_id(self, elem_id, callback):
js_code = javascript.assemble('webelem', 'element_by_id', elem_id)
js_cb = functools.partial(self._js_cb_single, callback)
self._tab.run_js_async(js_code, js_cb)
def find_focused(self, callback):
js_code = javascript.assemble('webelem', 'focus_element')
js_cb = functools.partial(self._js_cb_single, callback)
self._tab.run_js_async(js_code, js_cb)
def find_at_pos(self, pos, callback):
assert pos.x() >= 0
assert pos.y() >= 0
pos /= self._tab.zoom.factor()
js_code = javascript.assemble('webelem', 'element_at_pos',
pos.x(), pos.y())
js_cb = functools.partial(self._js_cb_single, callback)
self._tab.run_js_async(js_code, js_cb)
class WebEngineTab(browsertab.AbstractTab):
"""A QtWebEngine tab in the browser."""
def __init__(self, win_id, mode_manager, parent=None):
super().__init__(win_id)
widget = webview.WebEngineView()
super().__init__(win_id=win_id, mode_manager=mode_manager,
parent=parent)
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id)
self.history = WebEngineHistory(self)
self.scroller = WebEngineScroller(self, parent=self)
self.caret = WebEngineCaret(win_id=win_id, mode_manager=mode_manager,
@@ -336,16 +483,57 @@ class WebEngineTab(browsertab.AbstractTab):
self.zoom = WebEngineZoom(win_id=win_id, parent=self)
self.search = WebEngineSearch(parent=self)
self.printing = WebEnginePrinting()
self.elements = WebEngineElements(self)
self.action = WebEngineAction()
self._set_widget(widget)
self._connect_signals()
self.backend = usertypes.Backend.QtWebEngine
self._init_js()
self._child_event_filter = None
self._saved_zoom = None
def _init_js(self):
js_code = '\n'.join([
'"use strict";',
'window._qutebrowser = {};',
utils.read_file('javascript/scroll.js'),
utils.read_file('javascript/webelem.js'),
])
script = QWebEngineScript()
script.setInjectionPoint(QWebEngineScript.DocumentCreation)
script.setSourceCode(js_code)
page = self._widget.page()
script.setWorldId(QWebEngineScript.ApplicationWorld)
# FIXME:qtwebengine what about runsOnSubFrames?
page.scripts().insert(script)
def _install_event_filter(self):
self._widget.focusProxy().installEventFilter(self._mouse_event_filter)
self._child_event_filter = mouse.ChildEventFilter(
eventfilter=self._mouse_event_filter, widget=self._widget,
parent=self)
self._widget.installEventFilter(self._child_event_filter)
@pyqtSlot()
def _restore_zoom(self):
if self._saved_zoom is None:
return
self.zoom.set_factor(self._saved_zoom)
self._saved_zoom = None
def openurl(self, url):
self._saved_zoom = self.zoom.factor()
self._openurl_prepare(url)
self._widget.load(url)
def url(self):
return self._widget.url()
def url(self, requested=False):
page = self._widget.page()
if requested:
return page.requestedUrl()
else:
return page.url()
def dump_async(self, callback, *, plain=False):
if plain:
@@ -353,31 +541,25 @@ class WebEngineTab(browsertab.AbstractTab):
else:
self._widget.page().toHtml(callback)
def run_js_async(self, code, callback=None):
if callback is None:
self._widget.page().runJavaScript(code)
def run_js_async(self, code, callback=None, *, world=None):
if world is None:
world_id = QWebEngineScript.ApplicationWorld
elif isinstance(world, int):
world_id = world
else:
self._widget.page().runJavaScript(code, callback)
world_id = _JS_WORLD_MAP[world]
def run_js_blocking(self, code):
unset = object()
loop = qtutils.EventLoop()
js_ret = unset
def js_cb(val):
"""Handle return value from JS and stop blocking."""
nonlocal js_ret
js_ret = val
loop.quit()
self.run_js_async(code, js_cb)
loop.exec_() # blocks until loop.quit() in js_cb
assert js_ret is not unset
return js_ret
if callback is None:
self._widget.page().runJavaScript(code, world_id)
else:
self._widget.page().runJavaScript(code, world_id, callback)
def shutdown(self):
log.stub()
self.shutting_down.emit()
# WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58563
self.search.clear()
self._widget.shutdown()
def reload(self, *, force=False):
if force:
@@ -393,35 +575,119 @@ class WebEngineTab(browsertab.AbstractTab):
return self._widget.title()
def icon(self):
try:
return self._widget.icon()
except AttributeError:
log.stub('on Qt < 5.7')
return QIcon()
return self._widget.icon()
def set_html(self, html, base_url):
def set_html(self, html, base_url=None):
# FIXME:qtwebengine
# check this and raise an exception if too big:
# Warning: The content will be percent encoded before being sent to the
# renderer via IPC. This may increase its size. The maximum size of the
# percent encoded content is 2 megabytes minus 30 bytes.
if base_url is None:
base_url = QUrl()
self._widget.setHtml(html, base_url)
def networkaccessmanager(self):
return None
def user_agent(self):
return None
def clear_ssl_errors(self):
log.stub()
raise browsertab.UnsupportedOperationError
@pyqtSlot()
def _on_history_trigger(self):
url = self.url()
requested_url = self.url(requested=True)
# Don't save the title if it's generated from the URL
title = self.title()
title_url = QUrl(url)
title_url.setScheme('')
if title == title_url.toDisplayString(QUrl.RemoveScheme).strip('/'):
title = ""
# Don't add history entry if the URL is invalid anyways
if not url.isValid():
log.misc.debug("Ignoring invalid URL being added to history")
return
self.add_history_item.emit(url, requested_url, title)
@pyqtSlot(QUrl, 'QAuthenticator*')
def _on_authentication_required(self, url, authenticator):
# FIXME:qtwebengine support .netrc
answer = shared.authentication_required(
url, authenticator, abort_on=[self.shutting_down,
self.load_started])
if answer is None:
try:
# pylint: disable=no-member, useless-suppression
sip.assign(authenticator, QAuthenticator())
except AttributeError:
# WORKAROUND for
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-December/038400.html
url_string = url.toDisplayString()
error_page = jinja.render(
'error.html',
title="Error loading page: {}".format(url_string),
url=url_string, error="Authentication required", icon='')
self.set_html(error_page)
@pyqtSlot('QWebEngineFullScreenRequest')
def _on_fullscreen_requested(self, request):
request.accept()
on = request.toggleOn()
self.fullscreen_requested.emit(on)
if on:
notification = miscwidgets.FullscreenNotification(self)
notification.show()
notification.set_timeout(3000)
@pyqtSlot(QWebEnginePage.RenderProcessTerminationStatus, int)
def _on_render_process_terminated(self, status, exitcode):
"""Show an error when the renderer process terminated."""
if (status == QWebEnginePage.AbnormalTerminationStatus and
exitcode == 256):
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-58697
status = QWebEnginePage.CrashedTerminationStatus
status_map = {
QWebEnginePage.NormalTerminationStatus:
browsertab.TerminationStatus.normal,
QWebEnginePage.AbnormalTerminationStatus:
browsertab.TerminationStatus.abnormal,
QWebEnginePage.CrashedTerminationStatus:
browsertab.TerminationStatus.crashed,
QWebEnginePage.KilledTerminationStatus:
browsertab.TerminationStatus.killed,
-1:
browsertab.TerminationStatus.unknown,
}
self.renderer_process_terminated.emit(status_map[status], exitcode)
def _connect_signals(self):
view = self._widget
page = view.page()
page.windowCloseRequested.connect(self.window_close_requested)
page.linkHovered.connect(self.link_hovered)
page.loadProgress.connect(self._on_load_progress)
page.loadStarted.connect(self._on_load_started)
view.titleChanged.connect(self.title_changed)
view.urlChanged.connect(self._on_url_changed)
page.loadFinished.connect(self._on_history_trigger)
page.loadFinished.connect(self._restore_zoom)
page.loadFinished.connect(self._on_load_finished)
page.certificate_error.connect(self._on_ssl_errors)
try:
view.iconChanged.connect(self.icon_changed)
except AttributeError:
log.stub('iconChanged, on Qt < 5.7')
page.authenticationRequired.connect(self._on_authentication_required)
page.fullScreenRequested.connect(self._on_fullscreen_requested)
page.contentsSizeChanged.connect(self.contents_size_changed)
view.titleChanged.connect(self.title_changed)
view.urlChanged.connect(self._on_url_changed)
view.renderProcessTerminated.connect(
self._on_render_process_terminated)
view.iconChanged.connect(self.icon_changed)
def event_target(self):
return self._widget.focusProxy()

View File

@@ -19,48 +19,256 @@
"""The main browser widget for QtWebEngine."""
import functools
from PyQt5.QtCore import pyqtSignal, Qt, QPoint
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, PYQT_VERSION
from PyQt5.QtGui import QPalette
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import certificateerror
from qutebrowser.config import config
from qutebrowser.utils import log
from qutebrowser.utils import (log, debug, usertypes, jinja, urlutils, message,
objreg)
class WebEngineView(QWebEngineView):
"""Custom QWebEngineView subclass with qutebrowser-specific features."""
mouse_wheel_zoom = pyqtSignal(QPoint)
def __init__(self, parent=None):
def __init__(self, tabdata, win_id, parent=None):
super().__init__(parent)
self.setPage(WebEnginePage(self))
self._win_id = win_id
self._tabdata = tabdata
def wheelEvent(self, e):
"""Zoom on Ctrl-Mousewheel.
theme_color = self.style().standardPalette().color(QPalette.Base)
page = WebEnginePage(theme_color=theme_color, parent=self)
self.setPage(page)
def shutdown(self):
self.page().shutdown()
def createWindow(self, wintype):
"""Called by Qt when a page wants to create a new window.
This function is called from the createWindow() method of the
associated QWebEnginePage, each time the page wants to create a new
window of the given type. This might be the result, for example, of a
JavaScript request to open a document in a new window.
Args:
e: The QWheelEvent.
wintype: This enum describes the types of window that can be
created by the createWindow() function.
QWebEnginePage::WebBrowserWindow:
A complete web browser window.
QWebEnginePage::WebBrowserTab:
A web browser tab.
QWebEnginePage::WebDialog:
A window without decoration.
QWebEnginePage::WebBrowserBackgroundTab:
A web browser tab without hiding the current visible
WebEngineView.
Return:
The new QWebEngineView object.
"""
if e.modifiers() & Qt.ControlModifier:
e.accept()
self.mouse_wheel_zoom.emit(e.angleDelta())
debug_type = debug.qenum_key(QWebEnginePage, wintype)
background_tabs = config.get('tabs', 'background-tabs')
log.webview.debug("createWindow with type {}, background_tabs "
"{}".format(debug_type, background_tabs))
if wintype == QWebEnginePage.WebBrowserWindow:
# Shift-Alt-Click
target = usertypes.ClickTarget.window
elif wintype == QWebEnginePage.WebDialog:
log.webview.warning("{} requested, but we don't support "
"that!".format(debug_type))
target = usertypes.ClickTarget.tab
elif wintype == QWebEnginePage.WebBrowserTab:
# Middle-click / Ctrl-Click with Shift
# FIXME:qtwebengine this also affects target=_blank links...
if background_tabs:
target = usertypes.ClickTarget.tab
else:
target = usertypes.ClickTarget.tab_bg
elif wintype == QWebEnginePage.WebBrowserBackgroundTab:
# Middle-click / Ctrl-Click
if background_tabs:
target = usertypes.ClickTarget.tab_bg
else:
target = usertypes.ClickTarget.tab
else:
super().wheelEvent(e)
raise ValueError("Invalid wintype {}".format(debug_type))
tab = shared.get_tab(self._win_id, target)
return tab._widget # pylint: disable=protected-access
class WebEnginePage(QWebEnginePage):
"""Custom QWebEnginePage subclass with qutebrowser-specific features."""
"""Custom QWebEnginePage subclass with qutebrowser-specific features.
Attributes:
_is_shutting_down: Whether the page is currently shutting down.
_theme_color: The theme background color.
Signals:
certificate_error: Emitted on certificate errors.
shutting_down: Emitted when the page is shutting down.
"""
certificate_error = pyqtSignal()
shutting_down = pyqtSignal()
def __init__(self, theme_color, parent=None):
super().__init__(parent)
self._is_shutting_down = False
self.featurePermissionRequested.connect(
self._on_feature_permission_requested)
self._theme_color = theme_color
self._set_bg_color()
objreg.get('config').changed.connect(self._set_bg_color)
@config.change_filter('colors', 'webpage.bg')
def _set_bg_color(self):
col = config.get('colors', 'webpage.bg')
if col is None:
col = self._theme_color
self.setBackgroundColor(col)
@pyqtSlot(QUrl, 'QWebEnginePage::Feature')
def _on_feature_permission_requested(self, url, feature):
"""Ask the user for approval for geolocation/media/etc.."""
options = {
QWebEnginePage.Geolocation: ('content', 'geolocation'),
QWebEnginePage.MediaAudioCapture: ('content', 'media-capture'),
QWebEnginePage.MediaVideoCapture: ('content', 'media-capture'),
QWebEnginePage.MediaAudioVideoCapture:
('content', 'media-capture'),
}
messages = {
QWebEnginePage.Geolocation: 'access your location',
QWebEnginePage.MediaAudioCapture: 'record audio',
QWebEnginePage.MediaVideoCapture: 'record video',
QWebEnginePage.MediaAudioVideoCapture: 'record audio/video',
}
assert options.keys() == messages.keys()
if feature not in options:
log.webview.error("Unhandled feature permission {}".format(
debug.qenum_key(QWebEnginePage, feature)))
self.setFeaturePermission(url, feature,
QWebEnginePage.PermissionDeniedByUser)
return
yes_action = functools.partial(
self.setFeaturePermission, url, feature,
QWebEnginePage.PermissionGrantedByUser)
no_action = functools.partial(
self.setFeaturePermission, url, feature,
QWebEnginePage.PermissionDeniedByUser)
question = shared.feature_permission(
url=url, option=options[feature], msg=messages[feature],
yes_action=yes_action, no_action=no_action,
abort_on=[self.shutting_down, self.loadStarted])
if question is not None:
self.featurePermissionRequestCanceled.connect(
functools.partial(self._on_feature_permission_cancelled,
question, url, feature))
def _on_feature_permission_cancelled(self, question, url, feature,
cancelled_url, cancelled_feature):
"""Slot invoked when a feature permission request was cancelled.
To be used with functools.partial.
"""
if url == cancelled_url and feature == cancelled_feature:
try:
question.abort()
except RuntimeError:
# The question could already be deleted, e.g. because it was
# aborted after a loadStarted signal.
pass
def shutdown(self):
self._is_shutting_down = True
self.shutting_down.emit()
def certificateError(self, error):
"""Handle certificate errors coming from Qt."""
self.certificate_error.emit()
return super().certificateError(error)
url = error.url()
error = certificateerror.CertificateErrorWrapper(error)
log.webview.debug("Certificate error: {}".format(error))
url_string = url.toDisplayString()
error_page = jinja.render(
'error.html', title="Error loading page: {}".format(url_string),
url=url_string, error=str(error), icon='')
if error.is_overridable():
ignore = shared.ignore_certificate_errors(
url, [error], abort_on=[self.loadStarted, self.shutting_down])
else:
log.webview.error("Non-overridable certificate error: "
"{}".format(error))
ignore = False
# We can't really know when to show an error page, as the error might
# have happened when loading some resource.
# However, self.url() is not available yet and self.requestedUrl()
# might not match the URL we get from the error - so we just apply a
# heuristic here.
# See https://bugreports.qt.io/browse/QTBUG-56207
log.webview.debug("ignore {}, URL {}, requested {}".format(
ignore, url, self.requestedUrl()))
if not ignore and url.matches(self.requestedUrl(), QUrl.RemoveScheme):
self.setHtml(error_page)
return ignore
def javaScriptConfirm(self, url, js_msg):
"""Override javaScriptConfirm to use qutebrowser prompts."""
if self._is_shutting_down:
return False
try:
return shared.javascript_confirm(url, js_msg,
abort_on=[self.loadStarted,
self.shutting_down])
except shared.CallSuper:
return super().javaScriptConfirm(url, js_msg)
if PYQT_VERSION > 0x050700:
# WORKAROUND
# Can't override javaScriptPrompt with older PyQt versions
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-November/038293.html
def javaScriptPrompt(self, url, js_msg, default):
"""Override javaScriptPrompt to use qutebrowser prompts."""
if self._is_shutting_down:
return (False, "")
try:
return shared.javascript_prompt(url, js_msg, default,
abort_on=[self.loadStarted,
self.shutting_down])
except shared.CallSuper:
return super().javaScriptPrompt(url, js_msg, default)
def javaScriptAlert(self, url, js_msg):
"""Override javaScriptAlert to use qutebrowser prompts."""
if self._is_shutting_down:
return
try:
shared.javascript_alert(url, js_msg,
abort_on=[self.loadStarted,
self.shutting_down])
except shared.CallSuper:
super().javaScriptAlert(url, js_msg)
def javaScriptConsoleMessage(self, level, msg, line, source):
"""Log javascript messages to qutebrowser's log."""
@@ -77,3 +285,23 @@ class WebEnginePage(QWebEnginePage):
logstring = "[{}:{}] {}".format(source, line, msg)
logger = level_to_logger[level]
logger(logstring)
def acceptNavigationRequest(self,
url: QUrl,
typ: QWebEnginePage.NavigationType,
is_main_frame: bool):
"""Override acceptNavigationRequest to handle clicked links.
This only show an error on invalid links - everything else is handled
in createWindow.
"""
log.webview.debug("navigation request: url {}, type {}, is_main_frame "
"{}".format(url.toDisplayString(),
debug.qenum_key(QWebEnginePage, typ),
is_main_frame))
if (typ == QWebEnginePage.NavigationTypeLinkClicked and
not url.isValid()):
msg = urlutils.get_errstring(url, "Invalid link clicked")
message.error(msg)
return False
return True

View File

@@ -32,23 +32,14 @@ class DiskCache(QNetworkDiskCache):
"""Disk cache which sets correct cache dir and size.
If the cache is deactivated via the command line argument --cachedir="",
both attributes _cache_dir and _http_cache_dir are set to None.
Attributes:
_activated: Whether the cache should be used.
_cache_dir: The base directory for cache files (standarddir.cache()) or
None.
_http_cache_dir: the HTTP subfolder in _cache_dir or None.
_cache_dir: The base directory for cache files (standarddir.cache())
"""
def __init__(self, cache_dir, parent=None):
super().__init__(parent)
self._cache_dir = cache_dir
if cache_dir is None:
self._http_cache_dir = None
else:
self._http_cache_dir = os.path.join(cache_dir, 'http')
self._maybe_activate()
objreg.get('config').changed.connect(self.on_config_changed)
@@ -57,21 +48,27 @@ class DiskCache(QNetworkDiskCache):
maxsize=self.maximumCacheSize(),
path=self.cacheDirectory())
def _set_cache_size(self):
"""Set the cache size based on the config."""
size = config.get('storage', 'cache-size')
if size is None:
size = 1024 * 1024 * 50 # default from QNetworkDiskCachePrivate
self.setMaximumCacheSize(size)
def _maybe_activate(self):
"""Activate/deactivate the cache based on the config."""
if (config.get('general', 'private-browsing') or
self._cache_dir is None):
if config.get('general', 'private-browsing'):
self._activated = False
else:
self._activated = True
self.setCacheDirectory(self._http_cache_dir)
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
self.setCacheDirectory(os.path.join(self._cache_dir, 'http'))
self._set_cache_size()
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
"""Update cache size/activated if the config was changed."""
if (section, option) == ('storage', 'cache-size'):
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
self._set_cache_size()
elif (section, option) == ('general', # pragma: no branch
'private-browsing'):
self._maybe_activate()

View File

@@ -0,0 +1,52 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Wrapper over a QSslError."""
from PyQt5.QtNetwork import QSslError
from qutebrowser.utils import usertypes, utils, debug
class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper):
"""A wrapper over a QSslError."""
def __str__(self):
return self._error.errorString()
def __repr__(self):
return utils.get_repr(
self, error=debug.qenum_key(QSslError, self._error.error()),
string=str(self))
def __hash__(self):
try:
# Qt >= 5.4
return hash(self._error)
except TypeError:
return hash((self._error.certificate().toDer(),
self._error.error()))
def __eq__(self, other):
return self._error == other._error # pylint: disable=protected-access
def is_overridable(self):
return True

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,8 @@ def parse_content_disposition(reply):
# os.path.basename later.
try:
value = bytes(reply.rawHeader(content_disposition_header))
log.rfc6266.debug("Parsing Content-Disposition: {}".format(value))
log.rfc6266.debug("Parsing Content-Disposition: {!r}".format(
value))
content_disposition = rfc6266.parse_headers(value)
filename = content_disposition.filename()
except (SyntaxError, UnicodeDecodeError, rfc6266.Error):

View File

@@ -19,6 +19,7 @@
"""Utils for writing an MHTML file."""
import html
import functools
import io
import os
@@ -31,20 +32,14 @@ import email.generator
import email.encoders
import email.mime.multipart
import email.message
import quopri
from PyQt5.QtCore import QUrl
from qutebrowser.browser.webkit import webelem, downloads
from qutebrowser.browser import downloads
from qutebrowser.browser.webkit import webkitelem
from qutebrowser.utils import log, objreg, message, usertypes, utils, urlutils
try:
import cssutils
except (ImportError, re.error):
# Catching re.error because cssutils in earlier releases (<= 1.0) is broken
# on Python 3.5
# See https://bitbucket.org/cthedot/cssutils/issues/52
cssutils = None
_File = collections.namedtuple('_File',
['content', 'content_type', 'content_location',
'transfer_encoding'])
@@ -85,6 +80,14 @@ def _get_css_imports_cssutils(data, inline=False):
data: The content of the stylesheet to scan as string.
inline: True if the argument is an inline HTML style attribute.
"""
try:
import cssutils
except (ImportError, re.error):
# Catching re.error because cssutils in earlier releases (<= 1.0) is
# broken on Python 3.5
# See https://bitbucket.org/cthedot/cssutils/issues/52
return None
# We don't care about invalid CSS data, this will only litter the log
# output with CSS errors
parser = cssutils.CSSParser(loglevel=100,
@@ -114,10 +117,10 @@ def _get_css_imports(data, inline=False):
data: The content of the stylesheet to scan as string.
inline: True if the argument is an inline HTML style attribute.
"""
if cssutils is None:
return _get_css_imports_regex(data)
else:
return _get_css_imports_cssutils(data, inline)
imports = _get_css_imports_cssutils(data, inline)
if imports is None:
imports = _get_css_imports_regex(data)
return imports
def _check_rel(element):
@@ -136,6 +139,22 @@ def _check_rel(element):
return any(rel in rels for rel in must_have)
def _encode_quopri_mhtml(msg):
"""Encode the message's payload in quoted-printable.
Substitute for quopri's default 'encode_quopri' method, which needlessly
encodes all spaces and tabs, instead of only those at the end on the
line.
Args:
msg: Email message to quote.
"""
orig = msg.get_payload(decode=True)
encdata = quopri.encodestring(orig, quotetabs=False)
msg.set_payload(encdata)
msg['Content-Transfer-Encoding'] = 'quoted-printable'
MHTMLPolicy = email.policy.default.clone(linesep='\r\n', max_line_length=0)
@@ -144,7 +163,7 @@ E_BASE64 = email.encoders.encode_base64
# Encode the file using MIME quoted-printable encoding.
E_QUOPRI = email.encoders.encode_quopri
E_QUOPRI = _encode_quopri_mhtml
class MHTMLWriter:
@@ -223,7 +242,7 @@ class _Downloader:
Attributes:
tab: The AbstractTab which contains the website that will be saved.
dest: Destination filename.
target: DownloadTarget where the file should be downloaded to.
writer: The MHTMLWriter object which is used to save the page.
loaded_urls: A set of QUrls of finished asset downloads.
pending_downloads: A set of unfinished (url, DownloadItem) tuples.
@@ -233,9 +252,9 @@ class _Downloader:
_win_id: The window this downloader belongs to.
"""
def __init__(self, tab, dest):
def __init__(self, tab, target):
self.tab = tab
self.dest = dest
self.target = target
self.writer = None
self.loaded_urls = {tab.url()}
self.pending_downloads = set()
@@ -271,7 +290,7 @@ class _Downloader:
elements = web_frame.findAllElements('link, script, img')
for element in elements:
element = webelem.WebElementWrapper(element)
element = webkitelem.WebKitElement(element, tab=self.tab)
# Websites are free to set whatever rel=... attribute they want.
# We just care about stylesheets and icons.
if not _check_rel(element):
@@ -288,7 +307,7 @@ class _Downloader:
styles = web_frame.findAllElements('style')
for style in styles:
style = webelem.WebElementWrapper(style)
style = webkitelem.WebKitElement(style, tab=self.tab)
# The Mozilla Developer Network says:
# type: This attribute defines the styling language as a MIME type
# (charset should not be specified). This attribute is optional and
@@ -301,7 +320,7 @@ class _Downloader:
# Search for references in inline styles
for element in web_frame.findAllElements('[style]'):
element = webelem.WebElementWrapper(element)
element = webkitelem.WebKitElement(element, tab=self.tab)
style = element['style']
for element_url in _get_css_imports(style, inline=True):
self._fetch_url(web_url.resolved(QUrl(element_url)))
@@ -330,8 +349,8 @@ class _Downloader:
# Using the download manager to download host-blocked urls might crash
# qute, see the comments/discussion on
# https://github.com/The-Compiler/qutebrowser/pull/962#discussion_r40256987
# and https://github.com/The-Compiler/qutebrowser/issues/1053
# https://github.com/qutebrowser/qutebrowser/pull/962#discussion_r40256987
# and https://github.com/qutebrowser/qutebrowser/issues/1053
host_blocker = objreg.get('host-blocker')
if host_blocker.is_blocked(url):
log.downloads.debug("Skipping {}, host-blocked".format(url))
@@ -341,9 +360,9 @@ class _Downloader:
self.writer.add_file(urlutils.encoded_url(url), b'')
return
download_manager = objreg.get('download-manager', scope='window',
window=self._win_id)
target = usertypes.FileObjDownloadTarget(_NoCloseBytesIO())
download_manager = objreg.get('qtnetwork-download-manager',
scope='window', window=self._win_id)
target = downloads.FileObjDownloadTarget(_NoCloseBytesIO())
item = download_manager.get(url, target=target,
auto_remove=True)
self.pending_downloads.add((url, item))
@@ -443,15 +462,34 @@ class _Downloader:
return
self._finished_file = True
log.downloads.debug("All assets downloaded, ready to finish off!")
if isinstance(self.target, downloads.FileDownloadTarget):
fobj = open(self.target.filename, 'wb')
elif isinstance(self.target, downloads.FileObjDownloadTarget):
fobj = self.target.fileobj
elif isinstance(self.target, downloads.OpenFileDownloadTarget):
try:
fobj = downloads.temp_download_manager.get_tmpfile(
self.tab.title() + '.mhtml')
except OSError as exc:
msg = "Download error: {}".format(exc)
message.error(msg)
return
else:
raise ValueError("Invalid DownloadTarget given: {!r}"
.format(self.target))
try:
with open(self.dest, 'wb') as file_output:
self.writer.write_to(file_output)
with fobj:
self.writer.write_to(fobj)
except OSError as error:
message.error(self._win_id,
"Could not save file: {}".format(error))
message.error("Could not save file: {}".format(error))
return
log.downloads.debug("File successfully written.")
message.info(self._win_id, "Page saved as {}".format(self.dest))
message.info("Page saved as {}".format(self.target))
if isinstance(self.target, downloads.OpenFileDownloadTarget):
utils.open_file(fobj.name, self.target.cmdline)
def _collect_zombies(self):
"""Collect done downloads and add their data to the MHTML file.
@@ -483,34 +521,37 @@ class _NoCloseBytesIO(io.BytesIO):
super().close()
def _start_download(dest, tab):
def _start_download(target, tab):
"""Start downloading the current page and all assets to an MHTML file.
This will overwrite dest if it already exists.
Args:
dest: The filename where the resulting file should be saved.
target: The DownloadTarget where the resulting file should be saved.
tab: Specify the tab whose page should be loaded.
"""
loader = _Downloader(tab, dest)
loader = _Downloader(tab, target)
loader.run()
def start_download_checked(dest, tab):
def start_download_checked(target, tab):
"""First check if dest is already a file, then start the download.
Args:
dest: The filename where the resulting file should be saved.
target: The DownloadTarget where the resulting file should be saved.
tab: Specify the tab whose page should be loaded.
"""
# The default name is 'page title.mht'
if not isinstance(target, downloads.FileDownloadTarget):
_start_download(target, tab)
return
# The default name is 'page title.mhtml'
title = tab.title()
default_name = utils.sanitize_filename(title + '.mht')
default_name = utils.sanitize_filename(title + '.mhtml')
# Remove characters which cannot be expressed in the file system encoding
encoding = sys.getfilesystemencoding()
default_name = utils.force_encoding(default_name, encoding)
dest = utils.force_encoding(dest, encoding)
dest = utils.force_encoding(target.filename, encoding)
dest = os.path.expanduser(dest)
@@ -528,20 +569,20 @@ def start_download_checked(dest, tab):
# saving the file anyway.
if not os.path.isdir(os.path.dirname(path)):
folder = os.path.dirname(path)
message.error(tab.win_id,
"Directory {} does not exist.".format(folder))
message.error("Directory {} does not exist.".format(folder))
return
target = downloads.FileDownloadTarget(path)
if not os.path.isfile(path):
_start_download(path, tab=tab)
_start_download(target, tab=tab)
return
q = usertypes.Question()
q.mode = usertypes.PromptMode.yesno
q.text = "{} exists. Overwrite?".format(path)
q.title = "Overwrite existing file?"
q.text = "<b>{}</b> already exists. Overwrite?".format(
html.escape(path))
q.completed.connect(q.deleteLater)
q.answered_yes.connect(functools.partial(
_start_download, path, tab=tab))
message_bridge = objreg.get('message-bridge', scope='window',
window=tab.win_id)
message_bridge.ask(q, blocking=False)
_start_download, target, tab=tab))
message.global_bridge.ask(q, blocking=False)

View File

@@ -22,17 +22,19 @@
import os
import collections
import netrc
import html
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication,
QUrl, QByteArray)
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkReply, QSslError,
QSslSocket)
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QSslSocket
from qutebrowser.config import config
from qutebrowser.utils import (message, log, usertypes, utils, objreg, qtutils,
urlutils, debug)
from qutebrowser.browser.webkit.network import qutescheme, networkreply
from qutebrowser.browser.webkit.network import filescheme
urlutils)
from qutebrowser.browser import shared
from qutebrowser.browser.webkit import certificateerror
from qutebrowser.browser.webkit.network import (webkitqutescheme, networkreply,
filescheme)
HOSTBLOCK_ERROR_STRING = '%HOSTBLOCK%'
@@ -109,24 +111,6 @@ def init():
QSslSocket.setDefaultCiphers(good_ciphers)
class SslError(QSslError):
"""A QSslError subclass which provides __hash__ on Qt < 5.4."""
def __hash__(self):
try:
# Qt >= 5.4
# pylint: disable=not-callable,useless-suppression
return super().__hash__()
except TypeError:
return hash((self.certificate().toDer(), self.error()))
def __repr__(self):
return utils.get_repr(
self, error=debug.qenum_key(QSslError, self.error()),
string=self.errorString())
class NetworkManager(QNetworkAccessManager):
"""Our own QNetworkAccessManager.
@@ -163,7 +147,7 @@ class NetworkManager(QNetworkAccessManager):
self._tab_id = tab_id
self._requests = []
self._scheme_handlers = {
'qute': qutescheme.QuteSchemeHandler(win_id),
'qute': webkitqutescheme.QuteSchemeHandler(win_id),
'file': filescheme.FileSchemeHandler(win_id),
}
self._set_cookiejar(private=config.get('general', 'private-browsing'))
@@ -206,36 +190,18 @@ class NetworkManager(QNetworkAccessManager):
self.setCache(cache)
cache.setParent(app)
def _ask(self, text, mode, owner=None):
"""Ask a blocking question in the statusbar.
Args:
text: The text to display to the user.
mode: A PromptMode.
owner: An object which will abort the question if destroyed, or
None.
Return:
The answer the user gave or None if the prompt was cancelled.
"""
q = usertypes.Question()
q.text = text
q.mode = mode
self.shutting_down.connect(q.abort)
def _get_abort_signals(self, owner=None):
"""Get a list of signals which should abort a question."""
abort_on = [self.shutting_down]
if owner is not None:
owner.destroyed.connect(q.abort)
abort_on.append(owner.destroyed)
# This might be a generic network manager, e.g. one belonging to a
# DownloadManager. In this case, just skip the webview thing.
if self._tab_id is not None:
tab = objreg.get('tab', scope='tab', window=self._win_id,
tab=self._tab_id)
tab.load_started.connect(q.abort)
bridge = objreg.get('message-bridge', scope='window',
window=self._win_id)
bridge.ask(q, blocking=True)
q.deleteLater()
return q.answer
abort_on.append(tab.load_started)
return abort_on
def shutdown(self):
"""Abort all running requests."""
@@ -245,7 +211,8 @@ class NetworkManager(QNetworkAccessManager):
request.deleteLater()
self.shutting_down.emit()
@pyqtSlot('QNetworkReply*', 'QList<QSslError>')
# No @pyqtSlot here, see
# https://github.com/qutebrowser/qutebrowser/issues/2213
def on_ssl_errors(self, reply, errors): # pragma: no mccabe
"""Decide if SSL errors should be ignored or not.
@@ -255,11 +222,9 @@ class NetworkManager(QNetworkAccessManager):
reply: The QNetworkReply that is encountering the errors.
errors: A list of errors.
"""
errors = [SslError(e) for e in errors]
ssl_strict = config.get('network', 'ssl-strict')
log.webview.debug("SSL errors {!r}, strict {}".format(
errors, ssl_strict))
errors = [certificateerror.CertificateErrorWrapper(e) for e in errors]
log.webview.debug("Certificate errors: {!r}".format(
' / '.join(str(err) for err in errors)))
try:
host_tpl = urlutils.host_tuple(reply.url())
except ValueError:
@@ -275,33 +240,22 @@ class NetworkManager(QNetworkAccessManager):
log.webview.debug("Already accepted: {} / "
"rejected {}".format(is_accepted, is_rejected))
if (ssl_strict and ssl_strict != 'ask') or is_rejected:
if is_rejected:
return
elif is_accepted:
reply.ignoreSslErrors()
return
if ssl_strict == 'ask':
err_string = '\n'.join('- ' + err.errorString() for err in errors)
answer = self._ask('SSL errors - continue?\n{}'.format(err_string),
mode=usertypes.PromptMode.yesno, owner=reply)
log.webview.debug("Asked for SSL errors, answer {}".format(answer))
if answer:
reply.ignoreSslErrors()
err_dict = self._accepted_ssl_errors
else:
err_dict = self._rejected_ssl_errors
if host_tpl is not None:
err_dict[host_tpl] += errors
else:
log.webview.debug("ssl-strict is False, only warning about errors")
for err in errors:
# FIXME we might want to use warn here (non-fatal error)
# https://github.com/The-Compiler/qutebrowser/issues/114
message.error(self._win_id, 'SSL error: {}'.format(
err.errorString()))
abort_on = self._get_abort_signals(reply)
ignore = shared.ignore_certificate_errors(reply.url(), errors,
abort_on=abort_on)
if ignore:
reply.ignoreSslErrors()
self._accepted_ssl_errors[host_tpl] += errors
err_dict = self._accepted_ssl_errors
else:
err_dict = self._rejected_ssl_errors
if host_tpl is not None:
err_dict[host_tpl] += errors
def clear_all_ssl_errors(self):
"""Clear all remembered SSL errors."""
@@ -330,7 +284,7 @@ class NetworkManager(QNetworkAccessManager):
# altogether.
reply.netrc_used = True
try:
net = netrc.netrc()
net = netrc.netrc(config.get('network', 'netrc-file'))
authenticators = net.authenticators(reply.url().host())
if authenticators is not None:
(user, _account, password) = authenticators
@@ -341,16 +295,13 @@ class NetworkManager(QNetworkAccessManager):
except netrc.NetrcParseError:
log.misc.exception("Error when parsing the netrc file")
if user is None:
# netrc check failed
answer = self._ask("Username ({}):".format(authenticator.realm()),
mode=usertypes.PromptMode.user_pwd,
owner=reply)
if answer is not None:
user, password = answer.user, answer.password
if user is not None:
authenticator.setUser(user)
authenticator.setPassword(password)
else:
abort_on = self._get_abort_signals(reply)
shared.authentication_required(reply.url(), authenticator,
abort_on=abort_on)
@pyqtSlot('QNetworkProxy', 'QAuthenticator*')
def on_proxy_authentication_required(self, proxy, authenticator):
@@ -361,9 +312,13 @@ class NetworkManager(QNetworkAccessManager):
authenticator.setUser(user)
authenticator.setPassword(password)
else:
answer = self._ask(
"Proxy username ({}):".format(authenticator.realm()),
mode=usertypes.PromptMode.user_pwd)
msg = '<b>{}</b> says:<br/>{}'.format(
html.escape(proxy.hostName()),
html.escape(authenticator.realm()))
abort_on = self._get_abort_signals()
answer = message.ask(
title="Proxy authentication required", text=msg,
mode=usertypes.PromptMode.user_pwd, abort_on=abort_on)
if answer is not None:
authenticator.setUser(answer.user)
authenticator.setPassword(answer.password)
@@ -400,7 +355,7 @@ class NetworkManager(QNetworkAccessManager):
log.downloads.debug("Adopted download, {} adopted.".format(
self.adopted_downloads))
download.destroyed.connect(self.on_adopted_download_destroyed)
download.do_retry.connect(self.adopt_download)
download.adopt_download.connect(self.adopt_download)
def set_referer(self, req, current_url):
"""Set the referer header."""
@@ -442,6 +397,14 @@ class NetworkManager(QNetworkAccessManager):
Return:
A QNetworkReply.
"""
proxy_factory = objreg.get('proxy-factory', None)
if proxy_factory is not None:
proxy_error = proxy_factory.get_error()
if proxy_error is not None:
return networkreply.ErrorNetworkReply(
req, proxy_error, QNetworkReply.UnknownProxyError,
self)
scheme = req.url().scheme()
if scheme in self._scheme_handlers:
result = self._scheme_handlers[scheme].createRequest(
@@ -449,6 +412,9 @@ class NetworkManager(QNetworkAccessManager):
if result is not None:
return result
for header, value in shared.custom_headers():
req.setRawHeader(header, value)
host_blocker = objreg.get('host-blocker')
if (op == QNetworkAccessManager.GetOperation and
host_blocker.is_blocked(req.url())):
@@ -458,20 +424,6 @@ class NetworkManager(QNetworkAccessManager):
req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied,
self)
if config.get('network', 'do-not-track'):
dnt = '1'.encode('ascii')
else:
dnt = '0'.encode('ascii')
req.setRawHeader('DNT'.encode('ascii'), dnt)
req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt)
# Load custom headers
custom_headers = config.get('network', 'custom-headers')
if custom_headers is not None:
for header, value in custom_headers.items():
req.setRawHeader(header.encode('ascii'), value.encode('ascii'))
# There are some scenarios where we can't figure out current_url:
# - There's a generic NetworkManager, e.g. for downloads
# - The download was in a tab which is now closed.
@@ -483,17 +435,13 @@ class NetworkManager(QNetworkAccessManager):
tab=self._tab_id)
current_url = tab.url()
except (KeyError, RuntimeError, TypeError):
# https://github.com/The-Compiler/qutebrowser/issues/889
# https://github.com/qutebrowser/qutebrowser/issues/889
# Catching RuntimeError and TypeError because we could be in
# the middle of the webpage shutdown here.
current_url = QUrl()
self.set_referer(req, current_url)
accept_language = config.get('network', 'accept-language')
if accept_language is not None:
req.setRawHeader('Accept-Language'.encode('ascii'),
accept_language.encode('ascii'))
if PYQT_VERSION < 0x050301:
# WORKAROUND (remove this when we bump the requirements to 5.3.1)
#

View File

@@ -1,275 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Handler functions for different qute:... pages.
Module attributes:
pyeval_output: The output of the last :pyeval command.
"""
import functools
import configparser
import mimetypes
import urllib.parse
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QNetworkReply
import qutebrowser
from qutebrowser.browser import pdfjs
from qutebrowser.browser.webkit.network import schemehandler, networkreply
from qutebrowser.utils import (version, utils, jinja, log, message, docutils,
objreg)
from qutebrowser.config import configexc, configdata
pyeval_output = ":pyeval was never called"
HANDLERS = {}
def add_handler(name):
"""Add a handler to the qute: scheme."""
def namedecorator(function):
HANDLERS[name] = function
return function
return namedecorator
class QuteSchemeError(Exception):
"""Exception to signal that a handler should return an ErrorReply.
Attributes correspond to the arguments in
networkreply.ErrorNetworkReply.
Attributes:
errorstring: Error string to print.
error: Numerical error value.
"""
def __init__(self, errorstring, error):
"""Constructor."""
self.errorstring = errorstring
self.error = error
super().__init__(errorstring)
class QuteSchemeHandler(schemehandler.SchemeHandler):
"""Scheme handler for qute: URLs."""
def createRequest(self, _op, request, _outgoing_data):
"""Create a new request.
Args:
request: const QNetworkRequest & req
_op: Operation op
_outgoing_data: QIODevice * outgoingData
Return:
A QNetworkReply.
"""
path = request.url().path()
host = request.url().host()
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
log.misc.debug("url: {}, path: {}, host {}".format(
request.url().toDisplayString(), path, host))
try:
handler = HANDLERS[path]
except KeyError:
try:
handler = HANDLERS[host]
except KeyError:
errorstr = "No handler found for {}!".format(
request.url().toDisplayString())
return networkreply.ErrorNetworkReply(
request, errorstr, QNetworkReply.ContentNotFoundError,
self.parent())
try:
data = handler(self._win_id, request)
except OSError as e:
return networkreply.ErrorNetworkReply(
request, str(e), QNetworkReply.ContentNotFoundError,
self.parent())
except QuteSchemeError as e:
return networkreply.ErrorNetworkReply(request, e.errorstring,
e.error, self.parent())
mimetype, _encoding = mimetypes.guess_type(request.url().fileName())
if mimetype is None:
mimetype = 'text/html'
return networkreply.FixedDataNetworkReply(request, data, mimetype,
self.parent())
class JSBridge(QObject):
"""Javascript-bridge for special qute:... pages."""
@pyqtSlot(int, str, str, str)
def set(self, win_id, sectname, optname, value):
"""Slot to set a setting from qute:settings."""
# https://github.com/The-Compiler/qutebrowser/issues/727
if ((sectname, optname) == ('content', 'allow-javascript') and
value == 'false'):
message.error(win_id, "Refusing to disable javascript via "
"qute:settings as it needs javascript support.")
return
try:
objreg.get('config').set('conf', sectname, optname, value)
except (configexc.Error, configparser.Error) as e:
message.error(win_id, e)
@add_handler('pyeval')
def qute_pyeval(_win_id, _request):
"""Handler for qute:pyeval. Return HTML content as bytes."""
html = jinja.render('pre.html', title='pyeval', content=pyeval_output)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('version')
@add_handler('verizon')
def qute_version(_win_id, _request):
"""Handler for qute:version. Return HTML content as bytes."""
html = jinja.render('version.html', title='Version info',
version=version.version(),
copyright=qutebrowser.__copyright__)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('plainlog')
def qute_plainlog(_win_id, request):
"""Handler for qute:plainlog. Return HTML content as bytes.
An optional query parameter specifies the minimum log level to print.
For example, qute://log?level=warning prints warnings and errors.
Level can be one of: vdebug, debug, info, warning, error, critical.
"""
if log.ram_handler is None:
text = "Log output was disabled."
else:
try:
level = urllib.parse.parse_qs(request.url().query())['level'][0]
except KeyError:
level = 'vdebug'
text = log.ram_handler.dump_log(html=False, level=level)
html = jinja.render('pre.html', title='log', content=text)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('log')
def qute_log(_win_id, request):
"""Handler for qute:log. Return HTML content as bytes.
An optional query parameter specifies the minimum log level to print.
For example, qute://log?level=warning prints warnings and errors.
Level can be one of: vdebug, debug, info, warning, error, critical.
"""
if log.ram_handler is None:
html_log = None
else:
try:
level = urllib.parse.parse_qs(request.url().query())['level'][0]
except KeyError:
level = 'vdebug'
html_log = log.ram_handler.dump_log(html=True, level=level)
html = jinja.render('log.html', title='log', content=html_log)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('gpl')
def qute_gpl(_win_id, _request):
"""Handler for qute:gpl. Return HTML content as bytes."""
return utils.read_file('html/COPYING.html').encode('ASCII')
@add_handler('help')
def qute_help(win_id, request):
"""Handler for qute:help. Return HTML content as bytes."""
try:
utils.read_file('html/doc/index.html')
except OSError:
html = jinja.render(
'error.html',
title="Error while loading documentation",
url=request.url().toDisplayString(),
error="This most likely means the documentation was not generated "
"properly. If you are running qutebrowser from the git "
"repository, please run scripts/asciidoc2html.py. "
"If you're running a released version this is a bug, please "
"use :report to report it.",
icon='')
return html.encode('UTF-8', errors='xmlcharrefreplace')
urlpath = request.url().path()
if not urlpath or urlpath == '/':
urlpath = 'index.html'
else:
urlpath = urlpath.lstrip('/')
if not docutils.docs_up_to_date(urlpath):
message.error(win_id, "Your documentation is outdated! Please re-run "
"scripts/asciidoc2html.py.")
path = 'html/doc/{}'.format(urlpath)
if urlpath.endswith('.png'):
return utils.read_file(path, binary=True)
else:
data = utils.read_file(path)
return data.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('settings')
def qute_settings(win_id, _request):
"""Handler for qute:settings. View/change qute configuration."""
config_getter = functools.partial(objreg.get('config').get, raw=True)
html = jinja.render('settings.html', win_id=win_id, title='settings',
config=configdata, confget=config_getter)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('pdfjs')
def qute_pdfjs(_win_id, request):
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
urlpath = request.url().path()
try:
return pdfjs.get_pdfjs_res(urlpath)
except pdfjs.PDFJSNotFound as e:
# Logging as the error might get lost otherwise since we're not showing
# the error page if a single asset is missing. This way we don't lose
# information, as the failed pdfjs requests are still in the log.
log.misc.warning(
"pdfjs resource requested but not found: {}".format(e.path))
raise QuteSchemeError("Can't find pdfjs resource '{}'".format(e.path),
QNetworkReply.ContentNotFoundError)
@add_handler('bookmarks')
def qute_bookmarks(_win_id, _request):
"""Handler for qute:bookmarks. Display all quickmarks / bookmarks."""
bookmarks = sorted(objreg.get('bookmark-manager').marks.items(),
key=lambda x: x[1]) # Sort by title
quickmarks = sorted(objreg.get('quickmark-manager').marks.items(),
key=lambda x: x[0]) # Sort by name
html = jinja.render('bookmarks.html',
title='Bookmarks',
bookmarks=bookmarks,
quickmarks=quickmarks)
return html.encode('UTF-8', errors='xmlcharrefreplace')

View File

@@ -0,0 +1,115 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QtWebKit specific qute:* handlers and glue code."""
import mimetypes
import functools
import configparser
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QNetworkReply
from qutebrowser.browser import pdfjs, qutescheme
from qutebrowser.browser.webkit.network import schemehandler, networkreply
from qutebrowser.utils import jinja, log, message, objreg, usertypes
from qutebrowser.config import configexc, configdata
class QuteSchemeHandler(schemehandler.SchemeHandler):
"""Scheme handler for qute: URLs."""
def createRequest(self, _op, request, _outgoing_data):
"""Create a new request.
Args:
request: const QNetworkRequest & req
_op: Operation op
_outgoing_data: QIODevice * outgoingData
Return:
A QNetworkReply.
"""
try:
mimetype, data = qutescheme.data_for_url(request.url())
except qutescheme.NoHandlerFound:
errorstr = "No handler found for {}!".format(
request.url().toDisplayString())
return networkreply.ErrorNetworkReply(
request, errorstr, QNetworkReply.ContentNotFoundError,
self.parent())
except qutescheme.QuteSchemeOSError as e:
return networkreply.ErrorNetworkReply(
request, str(e), QNetworkReply.ContentNotFoundError,
self.parent())
except qutescheme.QuteSchemeError as e:
return networkreply.ErrorNetworkReply(request, e.errorstring,
e.error, self.parent())
return networkreply.FixedDataNetworkReply(request, data, mimetype,
self.parent())
class JSBridge(QObject):
"""Javascript-bridge for special qute:... pages."""
@pyqtSlot(str, str, str)
def set(self, sectname, optname, value):
"""Slot to set a setting from qute:settings."""
# https://github.com/qutebrowser/qutebrowser/issues/727
if ((sectname, optname) == ('content', 'allow-javascript') and
value == 'false'):
message.error("Refusing to disable javascript via qute:settings "
"as it needs javascript support.")
return
try:
objreg.get('config').set('conf', sectname, optname, value)
except (configexc.Error, configparser.Error) as e:
message.error(str(e))
@qutescheme.add_handler('settings', backend=usertypes.Backend.QtWebKit)
def qute_settings(_url):
"""Handler for qute:settings. View/change qute configuration."""
config_getter = functools.partial(objreg.get('config').get, raw=True)
html = jinja.render('settings.html', title='settings', config=configdata,
confget=config_getter)
return 'text/html', html
@qutescheme.add_handler('pdfjs', backend=usertypes.Backend.QtWebKit)
def qute_pdfjs(url):
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
try:
data = pdfjs.get_pdfjs_res(url.path())
except pdfjs.PDFJSNotFound as e:
# Logging as the error might get lost otherwise since we're not showing
# the error page if a single asset is missing. This way we don't lose
# information, as the failed pdfjs requests are still in the log.
log.misc.warning(
"pdfjs resource requested but not found: {}".format(e.path))
raise qutescheme.QuteSchemeError("Can't find pdfjs resource "
"'{}'".format(e.path),
QNetworkReply.ContentNotFoundError)
else:
mimetype, _encoding = mimetypes.guess_type(url.fileName())
assert mimetype is not None, url
return mimetype, data

View File

@@ -117,7 +117,7 @@ class Language(str):
"""A language-tag (RFC 5646, Section 2.1).
FIXME: This grammar is not 100% correct yet.
https://github.com/The-Compiler/qutebrowser/issues/105
https://github.com/qutebrowser/qutebrowser/issues/105
"""
grammar = re.compile('[A-Za-z0-9-]+')
@@ -132,7 +132,7 @@ class ValueChars(str):
"""A value of an attribute.
FIXME: Can we merge this with Value?
https://github.com/The-Compiler/qutebrowser/issues/105
https://github.com/qutebrowser/qutebrowser/issues/105
"""
grammar = re.compile('({}|{})*'.format(attr_char_re, hex_digit_re))

View File

@@ -21,41 +21,9 @@
from PyQt5.QtCore import QByteArray, QDataStream, QIODevice, QUrl
from PyQt5.QtWebKit import qWebKitVersion
from qutebrowser.utils import utils, qtutils
HISTORY_STREAM_VERSION = 2
BACK_FORWARD_TREE_VERSION = 2
class TabHistoryItem:
"""A single item in the tab history.
Attributes:
url: The QUrl of this item.
original_url: The QUrl of this item which was originally requested.
title: The title as string of this item.
active: Whether this item is the item currently navigated to.
user_data: The user data for this item.
"""
def __init__(self, url, title, *, original_url=None, active=False,
user_data=None):
self.url = url
if original_url is None:
self.original_url = url
else:
self.original_url = original_url
self.title = title
self.active = active
self.user_data = user_data
def __repr__(self):
return utils.get_repr(self, constructor=True, url=self.url,
original_url=self.original_url, title=self.title,
active=self.active, user_data=self.user_data)
from qutebrowser.utils import qtutils
def _encode_url(url):
@@ -64,7 +32,54 @@ def _encode_url(url):
return data.decode('ascii')
def _serialize_item(i, item, stream):
def _serialize_ng(items, current_idx, stream):
# {'currentItemIndex': 0,
# 'history': [{'children': [],
# 'documentSequenceNumber': 1485030525573123,
# 'documentState': [],
# 'formContentType': '',
# 'itemSequenceNumber': 1485030525573122,
# 'originalURLString': 'about:blank',
# 'pageScaleFactor': 0.0,
# 'referrer': '',
# 'scrollPosition': {'x': 0, 'y': 0},
# 'target': '',
# 'title': '',
# 'urlString': 'about:blank'}]}
data = {'currentItemIndex': current_idx, 'history': []}
for item in items:
data['history'].append(_serialize_item_ng(item))
stream.writeInt(3) # history stream version
stream.writeQVariantMap(data)
def _serialize_item_ng(item):
data = {
'originalURLString': item.original_url.toString(QUrl.FullyEncoded),
'scrollPosition': {'x': 0, 'y': 0},
'title': item.title,
'urlString': item.url.toString(QUrl.FullyEncoded),
}
try:
data['scrollPosition']['x'] = item.user_data['scroll-pos'].x()
data['scrollPosition']['y'] = item.user_data['scroll-pos'].y()
except (KeyError, TypeError):
pass
return data
def _serialize_old(items, current_idx, stream):
### Source/WebKit/qt/Api/qwebhistory.cpp operator<<
stream.writeInt(2) # history stream version
stream.writeInt(len(items))
stream.writeInt(current_idx)
for i, item in enumerate(items):
_serialize_item_old(i, item, stream)
def _serialize_item_old(i, item, stream):
"""Serialize a single WebHistoryItem into a QDataStream.
Args:
@@ -82,7 +97,7 @@ def _serialize_item(i, item, stream):
### Source/WebCore/history/HistoryItem.cpp decodeBackForwardTree
## backForwardTreeEncodingVersion
stream.writeUInt32(BACK_FORWARD_TREE_VERSION)
stream.writeUInt32(2)
## size (recursion stack)
stream.writeUInt64(0)
## node->m_documentSequenceNumber
@@ -166,14 +181,12 @@ def serialize(items):
else:
current_idx = 0
### Source/WebKit/qt/Api/qwebhistory.cpp operator<<
stream.writeInt(HISTORY_STREAM_VERSION)
stream.writeInt(len(items))
stream.writeInt(current_idx)
if qtutils.is_qtwebkit_ng(qWebKitVersion()):
_serialize_ng(items, current_idx, stream)
else:
_serialize_old(items, current_idx, stream)
for i, item in enumerate(items):
_serialize_item(i, item, stream)
user_data.append(item.user_data)
user_data += [item.user_data for item in items]
stream.device().reset()
qtutils.check_qdatastream(stream)

View File

@@ -1,494 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""Utilities related to QWebElements.
Module attributes:
Group: Enum for different kinds of groups.
SELECTORS: CSS selectors for different groups of elements.
FILTERS: A dictionary of filter functions for the modes.
The filter for "links" filters javascript:-links and a-tags
without "href".
"""
import collections.abc
import functools
from PyQt5.QtCore import QRect, QUrl
from PyQt5.QtWebKit import QWebElement
from qutebrowser.config import config
from qutebrowser.utils import log, usertypes, utils
Group = usertypes.enum('Group', ['all', 'links', 'images', 'url', 'prevnext',
'focus', 'inputs'])
SELECTORS = {
Group.all: ('a, area, textarea, select, input:not([type=hidden]), button, '
'frame, iframe, link, [onclick], [onmousedown], [role=link], '
'[role=option], [role=button], img'),
Group.links: 'a, area, link, [role=link]',
Group.images: 'img',
Group.url: '[src], [href]',
Group.prevnext: 'a, area, button, link, [role=button]',
Group.focus: '*:focus',
Group.inputs: ('input[type=text], input[type=email], input[type=url], '
'input[type=tel], input[type=number], '
'input[type=password], input[type=search], textarea'),
}
def filter_links(elem):
return 'href' in elem and QUrl(elem['href']).scheme() != 'javascript'
FILTERS = {
Group.links: filter_links,
Group.prevnext: filter_links,
}
class IsNullError(Exception):
"""Gets raised by WebElementWrapper if an element is null."""
pass
class WebElementWrapper(collections.abc.MutableMapping):
"""A wrapper around QWebElement to make it more intelligent."""
def __init__(self, elem):
if isinstance(elem, self.__class__):
raise TypeError("Trying to wrap a wrapper!")
if elem.isNull():
raise IsNullError('{} is a null element!'.format(elem))
self._elem = elem
for name in ['addClass', 'appendInside', 'appendOutside',
'attributeNS', 'classes', 'clone', 'document',
'encloseContentsWith', 'encloseWith',
'evaluateJavaScript', 'findAll', 'findFirst',
'firstChild', 'geometry', 'hasAttributeNS',
'hasAttributes', 'hasClass', 'hasFocus', 'lastChild',
'localName', 'namespaceUri', 'nextSibling', 'parent',
'prefix', 'prependInside', 'prependOutside',
'previousSibling', 'removeAllChildren',
'removeAttributeNS', 'removeClass', 'removeFromDocument',
'render', 'replace', 'setAttributeNS', 'setFocus',
'setInnerXml', 'setOuterXml', 'setPlainText',
'setStyleProperty', 'styleProperty', 'tagName',
'takeFromDocument', 'toInnerXml', 'toOuterXml',
'toggleClass', 'webFrame', '__eq__', '__ne__']:
# We don't wrap some methods for which we have better alternatives:
# - Mapping access for attributeNames/hasAttribute/setAttribute/
# attribute/removeAttribute.
# - isNull is checked automagically.
# - str(...) instead of toPlainText
# For the rest, we create a wrapper which checks if the element is
# null.
method = getattr(self._elem, name)
def _wrapper(meth, *args, **kwargs):
self._check_vanished()
return meth(*args, **kwargs)
wrapper = functools.partial(_wrapper, method)
# We used to do functools.update_wrapper here, but for some reason
# when using hints with many links, this accounted for nearly 50%
# of the time when profiling, which is unacceptable.
setattr(self, name, wrapper)
def __str__(self):
self._check_vanished()
return self._elem.toPlainText()
def __repr__(self):
try:
html = self.debug_text()
except IsNullError:
html = None
return utils.get_repr(self, html=html)
def __getitem__(self, key):
self._check_vanished()
if key not in self:
raise KeyError(key)
return self._elem.attribute(key)
def __setitem__(self, key, val):
self._check_vanished()
self._elem.setAttribute(key, val)
def __delitem__(self, key):
self._check_vanished()
if key not in self:
raise KeyError(key)
self._elem.removeAttribute(key)
def __contains__(self, key):
self._check_vanished()
return self._elem.hasAttribute(key)
def __iter__(self):
self._check_vanished()
yield from self._elem.attributeNames()
def __len__(self):
self._check_vanished()
return len(self._elem.attributeNames())
def _check_vanished(self):
"""Raise an exception if the element vanished (is null)."""
if self._elem.isNull():
raise IsNullError('Element {} vanished!'.format(self._elem))
def is_visible(self, mainframe):
"""Check whether the element is currently visible on the screen.
Args:
mainframe: The main QWebFrame.
Return:
True if the element is visible, False otherwise.
"""
return is_visible(self._elem, mainframe)
def rect_on_view(self, **kwargs):
"""Get the geometry of the element relative to the webview."""
return rect_on_view(self._elem, **kwargs)
def is_writable(self):
"""Check whether an element is writable."""
self._check_vanished()
return not ('disabled' in self or 'readonly' in self)
def is_content_editable(self):
"""Check if an element has a contenteditable attribute.
Args:
elem: The QWebElement to check.
Return:
True if the element has a contenteditable attribute,
False otherwise.
"""
self._check_vanished()
try:
return self['contenteditable'].lower() not in ['false', 'inherit']
except KeyError:
return False
def _is_editable_object(self):
"""Check if an object-element is editable."""
if 'type' not in self:
log.webview.debug("<object> without type clicked...")
return False
objtype = self['type'].lower()
if objtype.startswith('application/') or 'classid' in self:
# Let's hope flash/java stuff has an application/* mimetype OR
# at least a classid attribute. Oh, and let's hope images/...
# DON'T have a classid attribute. HTML sucks.
log.webview.debug("<object type='{}'> clicked.".format(objtype))
return config.get('input', 'insert-mode-on-plugins')
else:
# Image/Audio/...
return False
def _is_editable_input(self):
"""Check if an input-element is editable.
Return:
True if the element is editable, False otherwise.
"""
try:
objtype = self['type'].lower()
except KeyError:
return self.is_writable()
else:
if objtype in ['text', 'email', 'url', 'tel', 'number', 'password',
'search']:
return self.is_writable()
else:
return False
def _is_editable_div(self):
"""Check if a div-element is editable.
Return:
True if the element is editable, False otherwise.
"""
# Beginnings of div-classes which are actually some kind of editor.
div_classes = ('CodeMirror', # Javascript editor over a textarea
'kix-', # Google Docs editor
'ace_') # http://ace.c9.io/
for klass in self._elem.classes():
if any([klass.startswith(e) for e in div_classes]):
return True
return False
def is_editable(self, strict=False):
"""Check whether we should switch to insert mode for this element.
Args:
strict: Whether to do stricter checking so only fields where we can
get the value match, for use with the :editor command.
Return:
True if we should switch to insert mode, False otherwise.
"""
self._check_vanished()
roles = ('combobox', 'textbox')
log.misc.debug("Checking if element is editable: {}".format(
repr(self)))
tag = self._elem.tagName().lower()
if self.is_content_editable() and self.is_writable():
return True
elif self.get('role', None) in roles and self.is_writable():
return True
elif tag == 'input':
return self._is_editable_input()
elif tag == 'textarea':
return self.is_writable()
elif tag in ['embed', 'applet']:
# Flash/Java/...
return config.get('input', 'insert-mode-on-plugins') and not strict
elif tag == 'object':
return self._is_editable_object() and not strict
elif tag == 'div':
return self._is_editable_div() and not strict
else:
return False
def is_text_input(self):
"""Check if this element is some kind of text box."""
self._check_vanished()
roles = ('combobox', 'textbox')
tag = self._elem.tagName().lower()
return self.get('role', None) in roles or tag in ['input', 'textarea']
def remove_blank_target(self):
"""Remove target from link."""
elem = self._elem
for _ in range(5):
if elem is None:
break
tag = elem.tagName().lower()
if tag == 'a' or tag == 'area':
if elem.attribute('target') == '_blank':
elem.setAttribute('target', '_top')
break
elem = elem.parent()
def debug_text(self):
"""Get a text based on an element suitable for debug output."""
self._check_vanished()
return utils.compact_text(self._elem.toOuterXml(), 500)
def javascript_escape(text):
"""Escape values special to javascript in strings.
With this we should be able to use something like:
elem.evaluateJavaScript("this.value='{}'".format(javascript_escape(...)))
And all values should work.
"""
# This is a list of tuples because order matters, and using OrderedDict
# makes no sense because we don't actually need dict-like properties.
replacements = (
('\\', r'\\'), # First escape all literal \ signs as \\.
("'", r"\'"), # Then escape ' and " as \' and \".
('"', r'\"'), # (note it won't hurt when we escape the wrong one).
('\n', r'\n'), # We also need to escape newlines for some reason.
('\r', r'\r'),
('\x00', r'\x00'),
('\ufeff', r'\ufeff'),
# http://stackoverflow.com/questions/2965293/
('\u2028', r'\u2028'),
('\u2029', r'\u2029'),
)
for orig, repl in replacements:
text = text.replace(orig, repl)
return text
def get_child_frames(startframe):
"""Get all children recursively of a given QWebFrame.
Loosely based on http://blog.nextgenetics.net/?e=64
Args:
startframe: The QWebFrame to start with.
Return:
A list of children QWebFrame, or an empty list.
"""
results = []
frames = [startframe]
while frames:
new_frames = []
for frame in frames:
results.append(frame)
new_frames += frame.childFrames()
frames = new_frames
return results
def focus_elem(frame):
"""Get the focused element in a web frame.
Args:
frame: The QWebFrame to search in.
"""
elem = frame.findFirstElement(SELECTORS[Group.focus])
return WebElementWrapper(elem)
def rect_on_view(elem, *, elem_geometry=None, adjust_zoom=True, no_js=False):
"""Get the geometry of the element relative to the webview.
We need this as a standalone function (as opposed to a WebElementWrapper
method) because we want to run is_visible before wrapping when hinting for
performance reasons.
Uses the getClientRects() JavaScript method to obtain the collection of
rectangles containing the element and returns the first rectangle which is
large enough (larger than 1px times 1px). If all rectangles returned by
getClientRects() are too small, falls back to elem.rect_on_view().
Skipping of small rectangles is due to <a> elements containing other
elements with "display:block" style, see
https://github.com/The-Compiler/qutebrowser/issues/1298
Args:
elem: The QWebElement to get the rect for.
elem_geometry: The geometry of the element, or None.
Calling QWebElement::geometry is rather expensive so we
want to avoid doing it twice.
adjust_zoom: Whether to adjust the element position based on the
current zoom level.
no_js: Fall back to the Python implementation
"""
if elem.isNull():
raise IsNullError("Got called on a null element!")
# First try getting the element rect via JS, as that's usually more
# accurate
if elem_geometry is None and not no_js:
rects = elem.evaluateJavaScript("this.getClientRects()")
text = utils.compact_text(elem.toOuterXml(), 500)
log.hints.vdebug("Client rectangles of element '{}': {}".format(text,
rects))
for i in range(int(rects.get("length", 0))):
rect = rects[str(i)]
width = rect.get("width", 0)
height = rect.get("height", 0)
if width > 1 and height > 1:
# fix coordinates according to zoom level
zoom = elem.webFrame().zoomFactor()
if not config.get('ui', 'zoom-text-only') and adjust_zoom:
rect["left"] *= zoom
rect["top"] *= zoom
width *= zoom
height *= zoom
rect = QRect(rect["left"], rect["top"], width, height)
frame = elem.webFrame()
while frame is not None:
# Translate to parent frames' position
# (scroll position is taken care of inside getClientRects)
rect.translate(frame.geometry().topLeft())
frame = frame.parentFrame()
return rect
# No suitable rects found via JS, try via the QWebElement API
if elem_geometry is None:
geometry = elem.geometry()
else:
geometry = elem_geometry
frame = elem.webFrame()
rect = QRect(geometry)
while frame is not None:
rect.translate(frame.geometry().topLeft())
rect.translate(frame.scrollPosition() * -1)
frame = frame.parentFrame()
# We deliberately always adjust the zoom here, even with adjust_zoom=False
if elem_geometry is None:
zoom = elem.webFrame().zoomFactor()
if not config.get('ui', 'zoom-text-only'):
rect.moveTo(rect.left() / zoom, rect.top() / zoom)
rect.setWidth(rect.width() / zoom)
rect.setHeight(rect.height() / zoom)
return rect
def is_visible(elem, mainframe):
"""Check if the given element is visible in the frame.
We need this as a standalone function (as opposed to a WebElementWrapper
method) because we want to check this before wrapping when hinting for
performance reasons.
Args:
elem: The QWebElement to check.
mainframe: The QWebFrame in which the element should be visible.
"""
if elem.isNull():
raise IsNullError("Got called on a null element!")
# CSS attributes which hide an element
hidden_attributes = {
'visibility': 'hidden',
'display': 'none',
}
for k, v in hidden_attributes.items():
if elem.styleProperty(k, QWebElement.ComputedStyle) == v:
return False
elem_geometry = elem.geometry()
if not elem_geometry.isValid() and elem_geometry.x() == 0:
# Most likely an invisible link
return False
# First check if the element is visible on screen
elem_rect = rect_on_view(elem, elem_geometry=elem_geometry)
mainframe_geometry = mainframe.geometry()
if elem_rect.isValid():
visible_on_screen = mainframe_geometry.intersects(elem_rect)
else:
# We got an invalid rectangle (width/height 0/0 probably), but this
# can still be a valid link.
visible_on_screen = mainframe_geometry.contains(elem_rect.topLeft())
# Then check if it's visible in its frame if it's not in the main
# frame.
elem_frame = elem.webFrame()
framegeom = QRect(elem_frame.geometry())
if not framegeom.isValid():
visible_in_frame = False
elif elem_frame.parentFrame() is not None:
framegeom.moveTo(0, 0)
framegeom.translate(elem_frame.scrollPosition())
if elem_geometry.isValid():
visible_in_frame = framegeom.intersects(elem_geometry)
else:
# We got an invalid rectangle (width/height 0/0 probably), but
# this can still be a valid link.
visible_in_frame = framegeom.contains(elem_geometry.topLeft())
else:
visible_in_frame = visible_on_screen
return all([visible_on_screen, visible_in_frame])

View File

@@ -0,0 +1,344 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QtWebKit specific part of the web element API."""
from PyQt5.QtCore import QRect
from PyQt5.QtWebKit import QWebElement, QWebSettings
from qutebrowser.config import config
from qutebrowser.utils import log, utils, javascript
from qutebrowser.browser import webelem
class IsNullError(webelem.Error):
"""Gets raised by WebKitElement if an element is null."""
pass
class WebKitElement(webelem.AbstractWebElement):
"""A wrapper around a QWebElement."""
def __init__(self, elem, tab):
super().__init__(tab)
if isinstance(elem, self.__class__):
raise TypeError("Trying to wrap a wrapper!")
if elem.isNull():
raise IsNullError('{} is a null element!'.format(elem))
self._elem = elem
def __str__(self):
self._check_vanished()
return self._elem.toPlainText()
def __eq__(self, other):
if not isinstance(other, WebKitElement):
return NotImplemented
return self._elem == other._elem # pylint: disable=protected-access
def __getitem__(self, key):
self._check_vanished()
if key not in self:
raise KeyError(key)
return self._elem.attribute(key)
def __setitem__(self, key, val):
self._check_vanished()
self._elem.setAttribute(key, val)
def __delitem__(self, key):
self._check_vanished()
if key not in self:
raise KeyError(key)
self._elem.removeAttribute(key)
def __contains__(self, key):
self._check_vanished()
return self._elem.hasAttribute(key)
def __iter__(self):
self._check_vanished()
yield from self._elem.attributeNames()
def __len__(self):
self._check_vanished()
return len(self._elem.attributeNames())
def _check_vanished(self):
"""Raise an exception if the element vanished (is null)."""
if self._elem.isNull():
raise IsNullError('Element {} vanished!'.format(self._elem))
def has_frame(self):
self._check_vanished()
return self._elem.webFrame() is not None
def geometry(self):
self._check_vanished()
return self._elem.geometry()
def style_property(self, name, *, strategy):
self._check_vanished()
strategies = {
# FIXME:qtwebengine which ones do we actually need?
'inline': QWebElement.InlineStyle,
'computed': QWebElement.ComputedStyle,
}
qt_strategy = strategies[strategy]
return self._elem.styleProperty(name, qt_strategy)
def classes(self):
self._check_vanished()
return self._elem.classes()
def tag_name(self):
"""Get the tag name for the current element."""
self._check_vanished()
return self._elem.tagName().lower()
def outer_xml(self):
"""Get the full HTML representation of this element."""
self._check_vanished()
return self._elem.toOuterXml()
def value(self):
self._check_vanished()
return self._elem.evaluateJavaScript('this.value')
def set_value(self, value):
self._check_vanished()
if self.is_content_editable():
log.webelem.debug("Filling {!r} via set_text.".format(self))
self._elem.setPlainText(value)
else:
log.webelem.debug("Filling {!r} via javascript.".format(self))
value = javascript.string_escape(value)
self._elem.evaluateJavaScript("this.value='{}'".format(value))
def insert_text(self, text):
self._check_vanished()
if not self.is_editable(strict=True):
raise webelem.Error("Element is not editable!")
log.webelem.debug("Inserting text into element {!r}".format(self))
self._elem.evaluateJavaScript("""
var text = "{}";
var event = document.createEvent("TextEvent");
event.initTextEvent("textInput", true, true, null, text);
this.dispatchEvent(event);
""".format(javascript.string_escape(text)))
def _parent(self):
"""Get the parent element of this element."""
self._check_vanished()
elem = self._elem.parent()
if elem is None or elem.isNull():
return None
return WebKitElement(elem, tab=self._tab)
def _rect_on_view_js(self):
"""Javascript implementation for rect_on_view."""
# FIXME:qtwebengine maybe we can reuse this?
rects = self._elem.evaluateJavaScript("this.getClientRects()")
if rects is None: # pragma: no cover
# On e.g. Void Linux with musl libc, the stack size is too small
# for jsc, and running JS will fail. If that happens, fall back to
# the Python implementation.
# https://github.com/qutebrowser/qutebrowser/issues/1641
return None
text = utils.compact_text(self._elem.toOuterXml(), 500)
log.webelem.vdebug("Client rectangles of element '{}': {}".format(
text, rects))
for i in range(int(rects.get("length", 0))):
rect = rects[str(i)]
width = rect.get("width", 0)
height = rect.get("height", 0)
if width > 1 and height > 1:
# fix coordinates according to zoom level
zoom = self._elem.webFrame().zoomFactor()
if not config.get('ui', 'zoom-text-only'):
rect["left"] *= zoom
rect["top"] *= zoom
width *= zoom
height *= zoom
rect = QRect(rect["left"], rect["top"], width, height)
frame = self._elem.webFrame()
while frame is not None:
# Translate to parent frames' position (scroll position
# is taken care of inside getClientRects)
rect.translate(frame.geometry().topLeft())
frame = frame.parentFrame()
return rect
return None
def _rect_on_view_python(self, elem_geometry):
"""Python implementation for rect_on_view."""
if elem_geometry is None:
geometry = self._elem.geometry()
else:
geometry = elem_geometry
frame = self._elem.webFrame()
rect = QRect(geometry)
while frame is not None:
rect.translate(frame.geometry().topLeft())
rect.translate(frame.scrollPosition() * -1)
frame = frame.parentFrame()
return rect
def rect_on_view(self, *, elem_geometry=None, no_js=False):
"""Get the geometry of the element relative to the webview.
Uses the getClientRects() JavaScript method to obtain the collection of
rectangles containing the element and returns the first rectangle which
is large enough (larger than 1px times 1px). If all rectangles returned
by getClientRects() are too small, falls back to elem.rect_on_view().
Skipping of small rectangles is due to <a> elements containing other
elements with "display:block" style, see
https://github.com/qutebrowser/qutebrowser/issues/1298
Args:
elem_geometry: The geometry of the element, or None.
Calling QWebElement::geometry is rather expensive so
we want to avoid doing it twice.
no_js: Fall back to the Python implementation
"""
self._check_vanished()
# First try getting the element rect via JS, as that's usually more
# accurate
if elem_geometry is None and not no_js:
rect = self._rect_on_view_js()
if rect is not None:
return rect
# No suitable rects found via JS, try via the QWebElement API
return self._rect_on_view_python(elem_geometry)
def _is_visible(self, mainframe):
"""Check if the given element is visible in the given frame.
This is not public API because it can't be implemented easily here with
QtWebEngine, and is only used via find_css(..., only_visible=True) via
the tab API.
"""
self._check_vanished()
# CSS attributes which hide an element
hidden_attributes = {
'visibility': 'hidden',
'display': 'none',
'opacity': '0',
}
for k, v in hidden_attributes.items():
if (self._elem.styleProperty(k, QWebElement.ComputedStyle) == v and
'ace_text-input' not in self.classes()):
return False
elem_geometry = self._elem.geometry()
if not elem_geometry.isValid() and elem_geometry.x() == 0:
# Most likely an invisible link
return False
# First check if the element is visible on screen
elem_rect = self.rect_on_view(elem_geometry=elem_geometry)
mainframe_geometry = mainframe.geometry()
if elem_rect.isValid():
visible_on_screen = mainframe_geometry.intersects(elem_rect)
else:
# We got an invalid rectangle (width/height 0/0 probably), but this
# can still be a valid link.
visible_on_screen = mainframe_geometry.contains(
elem_rect.topLeft())
# Then check if it's visible in its frame if it's not in the main
# frame.
elem_frame = self._elem.webFrame()
framegeom = QRect(elem_frame.geometry())
if not framegeom.isValid():
visible_in_frame = False
elif elem_frame.parentFrame() is not None:
framegeom.moveTo(0, 0)
framegeom.translate(elem_frame.scrollPosition())
if elem_geometry.isValid():
visible_in_frame = framegeom.intersects(elem_geometry)
else:
# We got an invalid rectangle (width/height 0/0 probably), but
# this can still be a valid link.
visible_in_frame = framegeom.contains(elem_geometry.topLeft())
else:
visible_in_frame = visible_on_screen
return all([visible_on_screen, visible_in_frame])
def remove_blank_target(self):
elem = self
for _ in range(5):
if elem is None:
break
tag = elem.tag_name()
if tag == 'a' or tag == 'area':
if elem.get('target', None) == '_blank':
elem['target'] = '_top'
break
elem = elem._parent() # pylint: disable=protected-access
def _click_editable(self, click_target):
ok = self._elem.evaluateJavaScript('this.focus(); true;')
if not ok:
log.webelem.debug("Failed to focus via JS, falling back to event")
self._click_fake_event(click_target)
def _click_js(self, click_target):
settings = QWebSettings.globalSettings()
attribute = QWebSettings.JavascriptCanOpenWindows
could_open_windows = settings.testAttribute(attribute)
settings.setAttribute(attribute, True)
ok = self._elem.evaluateJavaScript('this.click(); true;')
settings.setAttribute(attribute, could_open_windows)
if not ok:
log.webelem.debug("Failed to click via JS, falling back to event")
self._click_fake_event(click_target)
def _click_fake_event(self, click_target):
self._tab.data.override_target = click_target
super()._click_fake_event(click_target)
def get_child_frames(startframe):
"""Get all children recursively of a given QWebFrame.
Loosely based on http://blog.nextgenetics.net/?e=64
Args:
startframe: The QWebFrame to start with.
Return:
A list of children QWebFrame, or an empty list.
"""
results = []
frames = [startframe]
while frames:
new_frames = []
for frame in frames:
results.append(frame)
new_frames += frame.childFrames()
frames = new_frames
return results

View File

@@ -0,0 +1,61 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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 <http://www.gnu.org/licenses/>.
"""QtWebKit specific part of history."""
from PyQt5.QtWebKit import QWebHistoryInterface
class WebHistoryInterface(QWebHistoryInterface):
"""Glue code between WebHistory and Qt's QWebHistoryInterface.
Attributes:
_history: The WebHistory object.
"""
def __init__(self, webhistory, parent=None):
super().__init__(parent)
self._history = webhistory
def addHistoryEntry(self, url_string):
"""Required for a QWebHistoryInterface impl, obsoleted by add_url."""
pass
def historyContains(self, url_string):
"""Called by WebKit to determine if a URL is contained in the history.
Args:
url_string: The URL (as string) to check for.
Return:
True if the url is in the history, False otherwise.
"""
return url_string in self._history.history_dict
def init(history):
"""Initialize the QWebHistoryInterface.
Args:
history: The WebHistory object.
"""
interface = WebHistoryInterface(history, parent=history)
QWebHistoryInterface.setDefaultInterface(interface)

Some files were not shown because too many files have changed in this diff Show More