Compare commits

...

2165 Commits

Author SHA1 Message Date
Florian Bruhin
55a88ceea6 Release v1.0.2 2017-10-17 07:44:14 +02:00
Florian Bruhin
d4bf04d2c8 Bump up yaml timeout a bit
(cherry picked from commit 1a7612e559)
2017-10-17 06:29:00 +02:00
Florian Bruhin
cb527913dc Show better error message when trying to toggle with :set
(cherry picked from commit d8384ced0a)
2017-10-17 06:27:07 +02:00
Florian Bruhin
ddfa82345c Fix HTML escaping in completion
(cherry picked from commit e766fe14fc)
2017-10-16 12:27:45 +02:00
Florian Bruhin
45c75d5e04 Fix setting monospace fonts with None values
Fixes #3130

(cherry picked from commit 2a65cadb67)
2017-10-16 06:18:29 +02:00
Florian Bruhin
9404c61f10 Add SQLITE_READONLY to environmental errors
(cherry picked from commit fa4a66f7b3)
2017-10-15 21:10:31 +02:00
Florian Bruhin
01d2654c23 Improve history formatting in crashdialog 2017-10-14 22:27:30 +02:00
Florian Bruhin
bad349aacf Fix getting history in crash dialog 2017-10-14 22:23:03 +02:00
Florian Bruhin
5dacf1431f eslint: Disable multiline-comment-style 2017-10-14 21:41:56 +02:00
Florian Bruhin
27c46f20c0 Make sure the config default values are mutable
While the old values meant the same thing, they weren't mutable, so the config
couldn't modify them with a simple .append().

Fixes #3104
2017-10-14 16:40:44 +02:00
Florian Bruhin
97a14c14b3 Update changelog
[ci skip]
2017-10-14 12:50:34 +02:00
Florian Bruhin
0195f717c3 Move QOpenGL imports to the top
We don't support Qt < 5.4 anymore anyways.
2017-10-14 12:11:41 +02:00
Florian Bruhin
b3f395453b Run Nvidia shader workaround earlier
We need to do it before utils.opengl_vendor(), and it fits better there anyway.
This was a regression in v1.0.

See #2554, #3106
2017-10-14 12:10:21 +02:00
Florian Bruhin
d411ec1eba Mark content.notifications as QtWebKit-only 2017-10-13 23:18:36 +02:00
Florian Bruhin
db8fa5fdb6 Skip "History with invalid URL" test on Windows
For some reason, this hangs a lot on AppVeyor
2017-10-13 10:45:40 +02:00
Florian Bruhin
2872ae5641 Release v1.0.1 2017-10-13 09:21:56 +02:00
Florian Bruhin
cbe0ff94a1 Ignore inotify_add_watch Qt warning
This happens on Travis from time to time.
2017-10-13 09:12:31 +02:00
Florian Bruhin
19a0a026dc Update Firefox extension list in README
[ci skip]
2017-10-13 08:07:32 +02:00
Florian Bruhin
2bf9a81451 Prevent empty segfault reports 2017-10-13 07:52:55 +02:00
Florian Bruhin
35d5038ab1 Add missing test 2017-10-12 22:42:58 +02:00
Florian Bruhin
bf1d6acb06 Properly fix up version checks... 2017-10-12 22:41:52 +02:00
Florian Bruhin
07b1b3fbd4 Update changelog
[ci skip]
2017-10-12 19:59:46 +02:00
Florian Bruhin
8539d092df Fix version checking in earlyinit
With the previous commit, we also checked that PyQt was >= 5.7.1, but we want to
support PyQt 5.7.0. Instead, we now check the individual components by hand.

Also, the previous check accidentally allowed PyQt >= 5.2.0 instead of 5.7.0.
2017-10-12 19:41:49 +02:00
Florian Bruhin
dfe2f9e38c Also check PyQt version for qtutils.version_check()
With an older PyQt built against a newer Qt, we still don't have its features
available.

This also drops support for exact=True with compiled=True as the semantics for
that are unclear, and it's not used.
2017-10-12 19:13:20 +02:00
Florian Bruhin
4f870f902c Fix loading of monospace fonts in configtypes.QtFont
See #3096
2017-10-12 18:26:54 +02:00
Florian Bruhin
e9f9449237 Release v1.0.0 2017-10-12 09:15:02 +02:00
Florian Bruhin
e6ffcfc673 Remove QtWebKit reference from manpage 2017-10-12 09:14:51 +02:00
Florian Bruhin
5905b27299 Update changelog and install docs for v1.0.0 2017-10-12 09:12:39 +02:00
Florian Bruhin
5dca8cc8e5 Fix nested lists in changelog
[ci skip]
2017-10-12 08:57:41 +02:00
Florian Bruhin
80f46192b5 Update changelog for v1.0.0
See #3090
[ci skip]
2017-10-11 22:44:47 +02:00
Florian Bruhin
20f935e1f1 Prepare release checklist for v1.0.0
[ci skip]
2017-10-11 22:27:42 +02:00
Florian Bruhin
c87d369725 Improve fonts.monospace tests 2017-10-11 22:14:58 +02:00
Florian Bruhin
f035d4f362 Fix quote handling for fonts.monospace family 2017-10-11 22:14:58 +02:00
Florian Bruhin
a21a60c5ca Fix updating fonts when fonts.monospace is changed
Fixes #2973
2017-10-11 22:14:55 +02:00
Florian Bruhin
cbe9ff7435 Fix reading of fonts.monospace on init
See #2973
2017-10-11 22:06:47 +02:00
Florian Bruhin
96c0cde8b8 Fix copy-paste error in colors.messages.warning.border description 2017-10-11 16:26:52 +02:00
Florian Bruhin
ba92f32e9f Merge pull request #3073 from qutebrowser/sql-errors
Handle some sqlite errors gracefully
2017-10-11 14:48:01 +02:00
Florian Bruhin
64443a3eed Fix docstrings 2017-10-11 14:40:05 +02:00
Florian Bruhin
1b5f1aaebf Merge remote-tracking branch 'origin/pr/3055' 2017-10-11 14:37:59 +02:00
Florian Bruhin
4bca180a44 Pass HOME to PyInstaller environment
This prevents some weird Homebrew errors.
2017-10-11 14:09:45 +02:00
Florian Bruhin
f5e7388bfe Improve YAML deadline warning
See #2777
2017-10-11 13:15:15 +02:00
Florian Bruhin
4827e98b4e Fix lint 2017-10-11 13:15:15 +02:00
Florian Bruhin
5f7ce74e66 Install LibYAML on macOS on Travis
See #2777
2017-10-11 13:15:15 +02:00
Florian Bruhin
d78c184b6a Break long lines in travis_run.sh 2017-10-11 13:15:15 +02:00
Florian Bruhin
1a8de3b504 Check for YAML C extensions on Travis
See #2777
2017-10-11 13:15:15 +02:00
Florian Bruhin
35335d954b Show error when YAML load took too long
See #2777
2017-10-11 13:15:11 +02:00
Florian Bruhin
9c080538ba Add a setting to force the platform and improve Wayland handling
Closes #3078
See #2932
2017-10-11 09:23:21 +02:00
Florian Bruhin
e9a50f5f9f Another attempt at stabilizing qutescheme.feature 2017-10-11 08:46:53 +02:00
Florian Bruhin
bdc82bc633 Fix lint
See https://github.com/PyCQA/pylint/issues/1698
2017-10-11 08:41:23 +02:00
Florian Bruhin
59a1609dd8 Handle RuntimeError in AbstractTab __repr__
Apparently it can happen that we try to get a repr of an already destroyed tab.
In that case, we display <RuntimeError> as the URL now.
2017-10-11 08:02:27 +02:00
Florian Bruhin
2a3369e2fe Show nicer errors when trying to set deleted/renamed options 2017-10-11 08:00:38 +02:00
Florian Bruhin
0cd5d4300b Rename qt_args and force_software_rendering to add qt. prefix
Closes #3077
2017-10-11 07:45:38 +02:00
Florian Bruhin
abbd69f604 Implement deleting/renaming values in configdata.yml
This is needed for #3077, but also is used for the deletion in #2847 now.
See #2772.
2017-10-11 07:13:51 +02:00
Anton S
fadc8f1e0b [review] convey via_ipc from process_pos_args to get_window 2017-10-11 00:45:22 +03:00
Anton S
085304a1de [review] removed ApplicationActivate handler due to bugs 2017-10-11 00:28:20 +03:00
Anton S
ba1a7a8de8 [review] force_raise -> no_raise 2017-10-10 23:02:10 +03:00
Florian Bruhin
211de6d664 Leave qute://settings after tests are done
Let's see whether this helps with the flakyness where the next test (for pyeval)
tries to set frame_flattening...
2017-10-10 21:45:57 +02:00
Florian Bruhin
0afbcc0faa Update Saka Key url 2017-10-10 21:45:57 +02:00
Florian Bruhin
4c1273ba0a Fix indent 2017-10-10 14:59:24 +02:00
Anton S
e1f5da3eff [review] docstrings, url logging, etc. 2017-10-10 14:13:49 +03:00
Anton S
e537826ff5 fixed docstring, converted list to set 2017-10-10 01:46:49 +03:00
Anton S
40185385cf moved methods to restore initial order 2017-10-10 01:37:39 +03:00
Anton S
14da05f7b1 use open_url to handle FileOpen event 2017-10-10 01:31:31 +03:00
Anton S
00f0e519a9 added option to suppress window raising 2017-10-10 01:30:58 +03:00
Anton S
552d041422 reused some code from process args 2017-10-10 01:30:14 +03:00
Anton S
5301a42495 raise last focused window if requested 2017-10-10 01:00:34 +03:00
Anton S
6b7cecc840 separated window raising into it's own function 2017-10-10 01:00:33 +03:00
Florian Bruhin
c9c827aa3e Merge pull request #3074 from qutebrowser/pyup-scheduled-update-10-09-2017
Scheduled weekly dependency update for week 41
2017-10-09 22:31:29 +02:00
Florian Bruhin
8a6ea6a375 Add spaces around args with annotations
Looks like pylint 1.7.3/.4 notices those
2017-10-09 21:21:17 +02:00
pyup-bot
a6e363e779 Update tox from 2.8.2 to 2.9.1 2017-10-09 16:53:19 +02:00
pyup-bot
db8a84cf82 Update pytest-qt from 2.2.0 to 2.2.1 2017-10-09 16:53:18 +02:00
pyup-bot
c25bbcc0cb Update pytest from 3.2.2 to 3.2.3 2017-10-09 16:53:16 +02:00
pyup-bot
756dca8a0e Update parse-type from 0.4.1 to 0.4.2 2017-10-09 16:53:15 +02:00
pyup-bot
191ee67403 Update hypothesis from 3.30.3 to 3.32.0 2017-10-09 16:53:13 +02:00
pyup-bot
513773e81d Update pylint from 1.7.2 to 1.7.4 2017-10-09 16:53:12 +02:00
Florian Bruhin
d6d13770a3 Add missing history tests 2017-10-09 16:17:55 +02:00
Florian Bruhin
b5777299fd Fix getting a short text from the SqlError 2017-10-09 16:08:56 +02:00
Florian Bruhin
b608259751 Handle some sqlite errors gracefully
We mark some SQL errors as "environmental", and then show those as error
messages instead of raising an exception.

Fixes #3004
Workaround for #2930
2017-10-09 16:06:24 +02:00
Florian Bruhin
6498273b31 Add libraries to userscript docs 2017-10-09 07:51:13 +02:00
Florian Bruhin
83aa936276 Ignore _on_history_trigger for destroyed tabs 2017-10-09 07:13:43 +02:00
Florian Bruhin
e95260092c Add some more dwb keybindings
See #13
2017-10-09 07:00:59 +02:00
Florian Bruhin
0e64511d63 Split up _init_envvars from configinit.early_init 2017-10-09 06:52:14 +02:00
Florian Bruhin
f63b95c298 Fix the window.hide_wayland_decoration setting
Fixes #2267
2017-10-09 06:50:29 +02:00
Florian Bruhin
220d1be500 Fix docstring 2017-10-08 23:10:08 +02:00
Florian Bruhin
36ef68c698 Add :bind --default
Closes #3059
2017-10-08 21:48:48 +02:00
Florian Bruhin
83fdb68fc2 Update docs for spellcheck.languages 2017-10-08 21:30:02 +02:00
Florian Bruhin
8c1e95787d Improve error message for PercOrInt
Fixes #3068
2017-10-08 19:47:05 +02:00
Florian Bruhin
6c3f90146f Make qtutils.version_check strict by default
This also renames 'strict' to 'compiled' to be more descriptive.
It also fixes a crash when starting qutebrowser with an older compiled Qt
version which was introduced recently (calling setSpellCheckEnabled).
2017-10-08 19:08:37 +02:00
Florian Bruhin
13b7647443 Merge pull request #3057 from jnphilipp/master
Support playlist in mpv userscript.
2017-10-08 17:15:40 +02:00
Florian Bruhin
1d1faf8d25 Merge remote-tracking branch 'origin/pr/2940' 2017-10-08 16:53:10 +02:00
Florian Bruhin
6c300f41dd Don't use urllib.parse.urljoin to concatenate URLs
It doesn't support more than two arguments, and it's not really needed with the
predictable URLs we have anyways.

See #2891.
2017-10-08 16:46:15 +02:00
Florian Bruhin
1d7af2e74b Use double quotes to avoid escaping 2017-10-08 15:25:21 +02:00
Florian Bruhin
8ce69e1e57 Update docs (and lowercase qutebrowser) 2017-10-08 15:24:48 +02:00
Florian Bruhin
277daa334d Merge remote-tracking branch 'origin/pr/2891' 2017-10-08 15:23:01 +02:00
Florian Bruhin
e63d11527d Get rid of CommandRunner.run_safely_init
All messages are queued nowadays.
2017-10-08 14:42:42 +02:00
Florian Bruhin
51ea56375e Improve error handling for config commands
- Use self._handle_config_error() for key commands too
- Catch getting an invalid key properly
- Remove (wrong) "set: " prefix
2017-10-08 14:40:10 +02:00
Florian Bruhin
8d34d4d4f5 Turn on overflow checking in sip 2017-10-08 12:58:28 +02:00
jnphilipp
f1b53cdbdc Update view_in_mpv 2017-10-07 23:10:48 +02:00
Michal Siedlaczek
00666feaf6 FAQ update for spellcheck & test fix 2017-10-07 15:54:22 -04:00
Bryan Gilbert
be3727a599 Improved zoom level management and enforcement 2017-10-06 20:30:06 -04:00
Florian Bruhin
0d8edd54fb Mention macOS/Windows upgrades in install docs
[ci skip]
2017-10-06 14:25:46 +02:00
Michal Siedlaczek
4bac2f3e44 Initialize profiles with spellchecking turn on by default. 2017-10-06 07:58:26 -04:00
Florian Bruhin
54e5176f28 Revert "Only emit perc_changed signal when the percentage actually changed"
This reverts commit 1d50c2c39a.
This breaks various end2end test relying on getting log messages for scrolling.
2017-10-06 10:16:41 +02:00
Florian Bruhin
cb357b326d Merge pull request #3058 from josealberto4444/master
Small typos and bugs fixed in docs
2017-10-06 09:00:02 +02:00
Florian Bruhin
1d50c2c39a Only emit perc_changed signal when the percentage actually changed
QtWebEngine emits scrollPositionChanged a lot during smooth scrolling, and
there's no reason we need to update percentages when they didn't *actually*
change.

This reduces the updates with a single spacebar press from 6-7 to 2-3 on my
machine, which might not be enough though.

See #2233
2017-10-06 08:51:48 +02:00
Florian Bruhin
e1d358f4c1 Ignore another Qt error message 2017-10-06 08:50:57 +02:00
Florian Bruhin
acf3945efc Mark hints.auto_follow_timeout test as flaky
It fails on CI sometimes when the CI is too slow
2017-10-06 08:48:47 +02:00
Florian Bruhin
a7955505be Try stabilizing completion test 2017-10-05 20:03:35 +02:00
Florian Bruhin
2651688ef4 Only show customized options for :config-unset completion 2017-10-05 18:40:34 +02:00
Michal Siedlaczek
fd9a5fa334 Style fixes 2017-10-05 09:56:13 -04:00
Florian Bruhin
2c9003fd4b Adjust macOS QtWebKit instructions 2017-10-05 15:36:26 +02:00
josealberto4444
5f69247033 Actually fix bullet list 2017-10-05 14:13:05 +02:00
josealberto4444
9503f23abc Direct https link to the actual license 2017-10-05 14:10:13 +02:00
josealberto4444
d8e9d10c00 Unify style and fix some bugs 2017-10-05 14:10:00 +02:00
josealberto4444
30aab8ef79 Small typos 2017-10-05 13:32:10 +02:00
Florian Bruhin
618586f8b0 Merge branch 'config-write-py' 2017-10-05 11:30:50 +02:00
Florian Bruhin
953d028bd6 Mention config commands in configuring.asciidoc 2017-10-05 11:22:54 +02:00
Florian Bruhin
581b09b08f Update changelog 2017-10-05 11:22:54 +02:00
Florian Bruhin
c63d16e2ea tests: Get rid of duplicate key config stubs 2017-10-05 11:22:54 +02:00
Florian Bruhin
012f79b244 Make sure key_config_stub is available when needed 2017-10-05 11:05:16 +02:00
Florian Bruhin
712e4a975a Add a test to make sure :write-config-py files actually work 2017-10-05 10:48:14 +02:00
Florian Bruhin
3cb93b22ae Add tests for :config-write-py 2017-10-05 10:34:25 +02:00
Florian Bruhin
ade0e1bd0b Finish ConfigPyWriter and tests 2017-10-05 10:21:31 +02:00
jnphilipp
e0c76fcb4f Support playlist in mpv userscript. 2017-10-05 09:42:47 +02:00
Florian Bruhin
231b0522ca Refactor write_config_py 2017-10-05 09:01:33 +02:00
Florian Bruhin
8dc34cf78a Write commented lines with :write-config-py when writing defaults 2017-10-05 08:50:41 +02:00
Anton S
91c6847e59 [review] style fixes 2017-10-05 01:49:13 +03:00
Anton S
0f1444125f [osx] proper plist to show up in browsers list (by The-Compiler) 2017-10-05 01:16:43 +03:00
Anton S
5350b948ea [review] gather plist params in one place 2017-10-05 01:13:23 +03:00
Florian Bruhin
763d035ee3 Add environment variables to skip backendproblem checks
This is usually a bad idea, but might be useful in some special situations.
2017-10-04 22:25:14 +02:00
Florian Bruhin
2f33f93a98 Update FILES in manpage
[ci skip]
2017-10-04 22:16:36 +02:00
Florian Bruhin
d3d644d6a5 Try to stabilize :window-only test 2017-10-04 21:09:46 +02:00
Florian Bruhin
09f2b06081 build_release: Fix casing for framework name 2017-10-04 19:09:54 +02:00
Michal Siedlaczek
6d9f04355c Strip JSON response from Google API of the 5-byte prefix
Read more here:
* https://github.com/google/gitiles/issues/22
* https://github.com/google/gitiles/issues/82
2017-10-04 10:06:14 -04:00
Michal Siedlaczek
c5d695b59e Remove spellcheck.enabled option. 2017-10-04 09:54:59 -04:00
Michał Siedlaczek
e20ad95666 Merge branch 'master' into spell 2017-10-04 09:47:42 -04:00
Michal Siedlaczek
6a486058c5 Review fixes 2017-10-04 09:22:35 -04:00
Florian Bruhin
bae49c9366 Update Windows install instructions 2017-10-04 11:49:04 +02:00
Florian Bruhin
9257538dcf Regenerate docs 2017-10-04 11:48:46 +02:00
Florian Bruhin
36857d9250 Remove valid values for Bool from docs 2017-10-04 11:46:42 +02:00
Florian Bruhin
6fa001481d Add some comments to generated config.py 2017-10-04 11:43:14 +02:00
Florian Bruhin
7fc5e42cca Initial :config-write-py implementation 2017-10-04 11:14:24 +02:00
Florian Bruhin
f18b730f24 Update changelog 2017-10-04 09:36:08 +02:00
Florian Bruhin
f0c0fea281 Merge branch 'pr/3025' 2017-10-04 09:28:40 +02:00
Florian Bruhin
96ff0c61ef Try to stabilize :completion-item-del for :buffer test 2017-10-04 09:11:02 +02:00
Florian Bruhin
3b689166f8 Skip flaky :buffer test entirely 2017-10-04 09:10:48 +02:00
Florian Bruhin
da4402e98c Don't rely on order in test_clear 2017-10-04 09:02:34 +02:00
Florian Bruhin
38270de120 Avoid configdata init in test_configinit
See #2777
2017-10-04 09:01:31 +02:00
Florian Bruhin
cc871389c9 Increase pytest-faulthandler timeout a bit
See #2777
2017-10-04 08:58:35 +02:00
Florian Bruhin
6037d44d0e Remove unused imports 2017-10-04 08:56:32 +02:00
Florian Bruhin
969b8f3200 Fix test_configcommands on Python 3.5
looks like assert_called_once() was introduced in 3.6
2017-10-04 08:55:33 +02:00
Florian Bruhin
37fa7a0d3e Fix casing in test name 2017-10-04 08:47:33 +02:00
Florian Bruhin
208b4d1cbc Make configfiles.YamlConfig iteration deterministic 2017-10-04 08:47:10 +02:00
Florian Bruhin
42550cd2e6 Merge remote-tracking branch 'origin/pr/3048' 2017-10-04 06:47:48 +02:00
Florian Bruhin
9bba3ddf0d Update changelog 2017-10-04 06:47:08 +02:00
Florian Bruhin
ae4d5153b9 Add missing docstring 2017-10-04 06:47:08 +02:00
Florian Bruhin
cdf0cf56fa Merge remote-tracking branch 'origin/pr/3056' 2017-10-04 06:45:08 +02:00
Florian Bruhin
7cbb2b079f Use existing tabbed_browser_stubs fixture in tests 2017-10-04 06:35:42 +02:00
Florian Bruhin
8c660d1bf4 Add a :version command 2017-10-04 06:23:15 +02:00
Ryan Roden-Corrent
4a9e22163b Filter keyhints based on count prefix.
If a count prefix is given, only hint commands that can take a count.
2017-10-03 22:15:21 -04:00
Ryan Roden-Corrent
5d787c84ea Show keyhint even with count prefix.
The keyhintwidget was not showing up when a keychain was prefixed with a
count. For example, 'g' would show a keyhint but '5g' would not. Now
keyhints are shown even when a count is given.

Resolves #3045.
2017-10-03 22:04:53 -04:00
Michal Siedlaczek
932e7a9ab9 Review fixes 2017-10-03 20:07:06 -04:00
Anton S
68481bc989 [osx] declare html files support as well 2017-10-04 00:02:03 +03:00
Florian Bruhin
feaccb3083 Rename :scroll-perc to :scroll-to-perc
Closes #2819
2017-10-03 22:59:32 +02:00
Florian Bruhin
7f28097f55 Be explicit about constraints instead 2017-10-03 22:17:29 +02:00
Florian Bruhin
d70bdb5552 Honour --no-err-windows in more places
Fixes #3053
2017-10-03 21:28:55 +02:00
Florian Bruhin
16d369d98c bdd: Include captured log when subprocess didn't start
Fixes #3052
2017-10-03 21:13:56 +02:00
Florian Bruhin
6c2958b646 Set star_args_optional for :config-cycle 2017-10-03 20:49:16 +02:00
Florian Bruhin
22adcfba75 Stop using mocks in test_editor 2017-10-03 20:43:38 +02:00
Florian Bruhin
3907d1e032 Update changelog 2017-10-03 20:43:38 +02:00
Florian Bruhin
22088d9f7b Remove --force for :bind and config.bind(...)
Turns out --force is just in the way for most people, and at least for default
bindings it's easy to reset them.

Also, it makes :config-source fail when config.py contains keybindings.

Closes #3049
2017-10-03 20:43:38 +02:00
Florian Bruhin
727580d1f4 Add a :config-edit command
See #2794
2017-10-03 20:43:38 +02:00
Florian Bruhin
555930791f Refactor ExternalEditor to be able to edit an existing file 2017-10-03 19:24:04 +02:00
Michael Hoang
c8c6199369 Add tests for :set-cmd-text --run-on-count 2017-10-04 03:57:26 +11:00
Michael Hoang
8506e1f4f2 Add arg to run when count given for :set-cmd-text 2017-10-04 03:57:23 +11:00
Florian Bruhin
8edaad51c3 Add a :config-source command
See #2794
2017-10-03 16:28:11 +02:00
Florian Bruhin
0695cfccfc Improve some configfile tests 2017-10-03 14:33:33 +02:00
Florian Bruhin
999d70ae40 Add missing config.py tests 2017-10-03 14:13:10 +02:00
Florian Bruhin
586c6e810f Fix xfail check 2017-10-03 13:58:53 +02:00
Florian Bruhin
9f10fa105c Merge adblock.feature into misc.feature 2017-10-03 13:42:04 +02:00
Florian Bruhin
2f9d1875cd Clear BDD process settings between each test
Fixes #1310
2017-10-03 13:38:16 +02:00
Florian Bruhin
9383452ab9 Use a real YAML config for config tests 2017-10-03 13:06:50 +02:00
Florian Bruhin
ed8c3f4aa2 Add :config-clear and :config-unset
See #2794
2017-10-03 12:45:39 +02:00
Florian Bruhin
3772084cbf Adjust test_histcategory for NOT NULL constraints 2017-10-03 10:28:36 +02:00
Florian Bruhin
31f49afdb2 Fix incorrect docstring 2017-10-03 10:28:36 +02:00
Florian Bruhin
1603b15cfd Default to NOT NULL for table constraints
Ideally, we'd update all existing tables to add the new constraints, but sqlite
doesn't offer an easy way to do so: https://www.sqlite.org/lang_altertable.html

Since that migration really isn't worth the effort, we only set the constraint
for new tables...
2017-10-03 10:28:36 +02:00
Florian Bruhin
b06a38ce7e Reorder methods
(cherry picked from commit ba9bd292dbc43bf0ad382a1ef060c87ee651b5d7)
2017-10-03 10:28:19 +02:00
Florian Bruhin
ad867a3b90 Merge branch 'pr/3024' 2017-10-03 10:17:01 +02:00
Florian Bruhin
58bef6ba97 Regenerate docs 2017-10-03 10:16:41 +02:00
Florian Bruhin
368e9a5cf9 Update changelog 2017-10-03 07:39:24 +02:00
Florian Bruhin
4ed60efa80 Add missing qapp fixture 2017-10-03 07:38:10 +02:00
Florian Bruhin
f533e3b751 Move config toggling to :config-cycle
This removes :set option! and allows :config-cycle option instead.
2017-10-03 07:38:10 +02:00
Florian Bruhin
81993a70a2 Split off :config-cycle from :set
Before, we allowed :set to take multiple values, which often lead to confusing
error messages when a user forgot to quote the value.

Now, we instead have a dedicated :config-cycle command for that.

See #1840, #2794
2017-10-03 07:37:55 +02:00
Florian Bruhin
64e0313090 Fix commas in settings docs
Otherwise, asciidoc interprets it as a third parameter to the xref...

Fixes #3046
2017-10-02 20:12:32 +02:00
Michael Hoang
8ae0bd2797 Update :buffer tests for count support 2017-10-02 23:44:04 +11:00
Michael Hoang
138ce60c1d Add count support to buffer command 2017-10-02 23:44:04 +11:00
Florian Bruhin
5af8a95c82 Refactor SQL error handling
This renames SqlException to SqlError (to be more consistent with how Python
names exceptions), and adds an utility function which logs a few more useful
details about errors.

See #3004
2017-10-02 09:48:15 +02:00
Florian Bruhin
eacdbe132e Update changelog
[ci skip]
2017-10-02 09:06:11 +02:00
Florian Bruhin
85532248fa Merge remote-tracking branch 'origin/pr/2879' 2017-10-02 09:05:01 +02:00
Florian Bruhin
506b1cdbc1 Improve input.insert_mode.auto_load tests
This also adds a test for #2858 (also see #2879)
2017-10-02 09:04:37 +02:00
Florian Bruhin
9c1b604cb1 Update changelog 2017-10-02 07:51:58 +02:00
Florian Bruhin
14dacbaa92 Fix typo 2017-10-02 07:49:31 +02:00
Florian Bruhin
0df4569502 Merge remote-tracking branch 'origin/pr/2847' 2017-10-02 07:49:20 +02:00
Florian Bruhin
fbf9817dcb Rename test classes 2017-10-02 07:15:00 +02:00
Florian Bruhin
a8fc561707 Split config commands off to their own file. 2017-10-02 07:08:30 +02:00
Florian Bruhin
32d529b54e Fix typo in configuring docs
[ci skip]
2017-10-02 06:24:29 +02:00
Anton S
a576fae893 [osx] declare URLs support in Info.plist 2017-10-02 01:04:12 +03:00
Florian Bruhin
a273baf8a0 Make sure :bind/unbind works properly when bindings.commands is None
To make this work, we should never return None when trying to get bindings to
modify.

Fixes #3026
2017-10-01 21:43:00 +02:00
Florian Bruhin
0fbd914432 Fix completion for empty config values
If we have an empty string in the completion, that already gets completed as ''.
If we return "", we'd have '""' in the completion.

Fixes #3027
2017-10-01 20:14:49 +02:00
Anton S
ab6bfe61b8 [osx] first step to become default browser 2017-10-01 00:39:13 +03:00
Florian Bruhin
1b88fec7f0 Fix key chain in configuring docs
[ci skip]
2017-09-30 23:23:24 +02:00
Florian Bruhin
e0ff95d62a Remove outdated note from quickstart docs
[ci skip]
2017-09-30 22:55:36 +02:00
Florian Bruhin
59d5c0f8e8 Merge pull request #3039 from gilbertw1/fix-config-doc-alias
fix example config.py alias creation example
2017-09-30 15:21:52 +02:00
Bryan Gilbert
ba06323696 fix example config.py alias creation example 2017-09-30 09:02:17 -04:00
Florian Bruhin
1a381bf0a5 eslint: Report unused disables 2017-09-29 22:29:18 +02:00
Florian Bruhin
dca962ca03 Make userscripts work on both Python 2 and 3 2017-09-29 13:38:38 +02:00
Florian Bruhin
0b5af757ec Clarify settings which need a restart
[ci skip]
2017-09-28 21:51:07 +02:00
Florian Bruhin
322d97c3fa Only show warning message stack with --debug 2017-09-28 21:30:32 +02:00
Florian Bruhin
5c181a23ab Fix default prompt color
The former value was interpreted as a comment in the YAML...
2017-09-28 21:24:12 +02:00
Florian Bruhin
02bcec37f4 Darken default prompt color a bit more 2017-09-28 19:20:29 +02:00
Florian Bruhin
4e57b79e91 Merge branch 'webengine-by-default' 2017-09-28 18:41:41 +02:00
Florian Bruhin
9d963d55f5 Fix :debug-cache-stats with QtWebEngine
When we use --backend webengine, the QtWebKit stuff might be importable, but the
history still isn't initialized because of that.
2017-09-28 17:42:21 +02:00
Florian Bruhin
4b9bbaa04d Skip test_force_software_rendering with QtWebKit 2017-09-28 17:30:53 +02:00
Florian Bruhin
45db0eaccb Really force QtWebEngine for test_force_software_rendering init 2017-09-28 11:44:21 +02:00
Florian Bruhin
6496442503 Skip test_force_software_rendering on CI
We can't be sure we have hardware acceleration there
2017-09-28 11:42:02 +02:00
Florian Bruhin
6c25e96621 Remove unused imports 2017-09-28 11:38:52 +02:00
Florian Bruhin
3be0a78819 Fix configinit tests 2017-09-28 11:05:53 +02:00
Florian Bruhin
865fc2e0de Handle -s argument earlier
This makes sure we can e.g. set software_rendering via -s
2017-09-28 10:10:14 +02:00
Florian Bruhin
45c6ffe991 Add a test for force_software_rendering 2017-09-28 10:04:47 +02:00
Florian Bruhin
6770a474c4 Force software rendering earlier
We need to do this before a QApplication exists
2017-09-28 09:52:56 +02:00
Florian Bruhin
35beb84e85 Fix tests and lint 2017-09-28 09:38:57 +02:00
Florian Bruhin
dfa65a0bfe Remove requirements badge
Now that we use pyup weekly they'll be outdated most of the time, and it's not
really an useful metric for users anyways.
2017-09-28 09:29:00 +02:00
Florian Bruhin
f077f52997 Add asserts for the backend 2017-09-28 08:57:48 +02:00
Florian Bruhin
c77cff3fcb Also fail with DISPLAY with wayland platform plugin
QtWebEngine spews errors at us, and while it seems to work with Weston for some
reason (despite errors logged), it doesn't with sway.
2017-09-28 08:56:05 +02:00
Florian Bruhin
b906c862bb Remove ipc-server from objreg 2017-09-28 08:52:32 +02:00
Florian Bruhin
ce0622e38a Document how initialization roughly works 2017-09-28 08:41:10 +02:00
Florian Bruhin
e5958e6061 Override --backend argument from backend problem dialog 2017-09-28 08:41:10 +02:00
Florian Bruhin
defcf5394a Move SSL backend checking to backendproblem.py 2017-09-28 08:41:10 +02:00
Florian Bruhin
fa902c5d82 Improve error dialogs when QtWebKit/QtWebEngine was not found 2017-09-28 08:41:10 +02:00
Florian Bruhin
093f34183c Add improved checks for Nouveau/Wayland for QtWebEngine
Closes #2368
Closes #2932
See #2335
2017-09-28 08:41:10 +02:00
Florian Bruhin
ca4a997559 Update settings for QtWebEngine by default
See #2335
2017-09-28 08:41:10 +02:00
Jay Kamat
bb8d41cedc Add indicator padding to minimumTabSizeHint
Previously, indicator_padding was not taken into account, causing
problems when using a indicator_padding too small

Also removed icon padding to width calculation (seemed to be overestimating)
2017-09-27 21:04:06 -04:00
Florian Bruhin
e1f3829383 Cache the completion delegate stylesheet
We removed various caches in b5eac744b5 but the
completion delegate stylesheet gets rendered a lot, causing things to slow down.

The rendering takes around 1ms, but it gets done ~10k times with a simple
profiling run, so that adds up quickly.

We don't use a functools.lru_cache here as the stylesheet template never
changes.

Thanks a lot to gilbertw1 for tracking this down!

See #2812 - there's probably more possible, but this should fix the performance
regression some people saw with the new config.
2017-09-27 23:16:40 +02:00
Florian Bruhin
fac322058e Improve crashdialog result codes 2017-09-27 11:46:51 +02:00
Florian Bruhin
6573888dc6 Fix :bind completion with invalid commands
Now that Command doesn't validate things anymore, we can't rely on parsing to
work.
2017-09-27 11:10:25 +02:00
Florian Bruhin
fef1a65247 Fix ListOrValue.to_doc signature 2017-09-27 10:37:42 +02:00
Florian Bruhin
9607f3de59 Improve type documentation of settings
Use .get_name() for the docs
2017-09-27 08:25:52 +02:00
Florian Bruhin
c694bff902 Allow direct values for url.start_pages and content.user_stylesheets 2017-09-27 08:21:03 +02:00
Jay Kamat
cc84c1722d Merge remote-tracking branch 'upstream/master' into jay/remote-pintab-width 2017-09-26 18:07:10 -04:00
Jay Kamat
59c6555537 Remove the tabs.width.pinned setting 2017-09-26 18:06:23 -04:00
Florian Bruhin
2dfcf9c506 Remove unused imports 2017-09-26 21:37:20 +02:00
Florian Bruhin
b879f5e648 Slightly re-style prompts
See #2104
2017-09-26 21:28:01 +02:00
Florian Bruhin
6af879887f Drop --relaxed-config 2017-09-26 20:12:21 +02:00
Florian Bruhin
8e000dfe54 Make qute://configdiff usable with the new config too
Closes #2983
2017-09-26 19:39:47 +02:00
Florian Bruhin
1704438777 Reintroduce crash dialogs for QtWebKit 2017-09-26 19:25:53 +02:00
Florian Bruhin
6b5d34c7fb Fix updating of stylesheet when scrolling.bar is set
Fixes #2981
2017-09-26 11:28:40 +02:00
Florian Bruhin
474bf8ad06 Remove unneeded as-import 2017-09-26 10:47:07 +02:00
Florian Bruhin
e32d311d8e Update changelog 2017-09-26 08:48:53 +02:00
Florian Bruhin
277beae399 Merge branch 'pr/2984' 2017-09-26 08:48:45 +02:00
Florian Bruhin
b96ba8e41f Merge pull request #3031 from qutebrowser/pyup-scheduled-update-09-25-2017
Scheduled weekly dependency update for week 39
2017-09-26 08:43:23 +02:00
Florian Bruhin
dba631102a Try to stabilize :window-only test 2017-09-26 08:41:07 +02:00
Florian Bruhin
ff6df0c8ca Don't use utils.is_* in qutebrowser.spec
Looks like PyInstaller doesn't like that.
This partially reverts ef1c83862b.
2017-09-26 07:31:45 +02:00
Florian Bruhin
e7dba338b5 Pass %APPDATA% to pyinstaller env
This hopefully helps with PyInstaller creating a ~ directory
2017-09-26 07:30:54 +02:00
Florian Bruhin
5a60630450 Don't use utils.is_* in build_release.py
This partially reverts ef1c83862b
Otherwise, we'd have to have PyQt5 installed in the environment which runs
build_release.py.
2017-09-26 07:25:59 +02:00
Florian Bruhin
e766cf5ed1 build_release: print artifacts if not releasing 2017-09-26 07:13:54 +02:00
Florian Bruhin
6e226c6885 Add a recipes section to configuring.asciidoc
Closes #2987
Closes #2969
Closes #3009
See #2975
2017-09-26 07:08:42 +02:00
Florian Bruhin
38449e3e2b Make sure the autoconfig.yml is saved periodically
Fixes #2982
2017-09-26 06:41:55 +02:00
Florian Bruhin
38038df703 Compare objects with :set with multiple values 2017-09-25 21:24:12 +02:00
Florian Bruhin
1086e31f28 Split up configinit tests 2017-09-25 21:24:12 +02:00
Florian Bruhin
6aed6bca93 Make loading autoconfig.yml opt-in when a config.py exists
This lets the user control the precedence those files should have, and also
simplifies the code quite a bit.

Fixes #2975
2017-09-25 21:24:12 +02:00
Florian Bruhin
5a080207ff Bump up hypothesis deadline some more 2017-09-25 21:20:30 +02:00
Florian Bruhin
930bc9c998 Merge pull request #3032 from forkbong/fix-faq-link
Fix the link to faq.html in help page
2017-09-25 20:13:16 +02:00
Panagiotis Ktistakis
54eb23eab1 Fix the link to faq.html in help page 2017-09-25 20:54:28 +03:00
pyup-bot
4d4eee15d6 Update pluggy from 0.4.0 to 0.5.2 2017-09-25 16:47:20 +02:00
pyup-bot
414dc29493 Update parse-type from 0.3.4 to 0.4.1 2017-09-25 16:47:19 +02:00
pyup-bot
2a1f628e4e Update hypothesis from 3.28.3 to 3.30.3 2017-09-25 16:47:17 +02:00
pyup-bot
d23d53de1c Update wheel from 0.29.0 to 0.30.0 2017-09-25 16:47:16 +02:00
pyup-bot
9ecc0d8ef7 Update six from 1.10.0 to 1.11.0 2017-09-25 16:47:14 +02:00
pyup-bot
3605b1b510 Update setuptools from 36.2.7 to 36.5.0 2017-09-25 16:47:13 +02:00
Florian Bruhin
c7c198b949 Stabilize hint test 2017-09-25 08:22:40 +02:00
Ian Walker
ad2bb45446 Allow user to cancel proxy authentication request 2017-09-25 15:00:17 +09:00
Ian Walker
78bddaefe6 Move _on_proxy_authentication_required to WebEngineTab 2017-09-25 14:47:54 +09:00
Florian Bruhin
07862ce52e Merge branch 'pr/3029' 2017-09-25 06:57:02 +02:00
Florian Bruhin
8408d6ed9b Fix emacs syntax highlighting in configdata.yml 2017-09-25 06:56:33 +02:00
Florian Bruhin
d7273283ce Regenerate docs 2017-09-25 06:55:17 +02:00
Florian Bruhin
40f0f75ad5 Improve error message for duplicate keys in config.py 2017-09-24 19:43:30 +02:00
Florian Bruhin
fb9fca2477 Merge pull request #3017 from rcorre/overwrite-hist-backup
Append multiple history backups on import.
2017-09-24 14:24:53 +02:00
arza
cb68e4b6b2 Remove extra backslashes in configdata.yml 2017-09-23 22:58:30 +03:00
arza
1784dc777d Add table headers and widen input fields in qute://settings 2017-09-23 22:24:17 +03:00
Ryan Roden-Corrent
888a1b8c57 Append multiple history backups on import.
Previously, a successful import of the text history into sqlite would
move 'history' to 'history.bak'. If history.bak already existed, this
would overwrite it on unix and fail on windows.

With this patch, the most recently imported history is appended to
history.bak to avoid data loss.

Resolves #3005.

A few other options I considered:

1. os.replace:
    - fast, simple, no error on Windows
    - potential data loss
2. numbered backups (.bak.1, .bak.2, ...):
    - fast, no data loss, but more complex
3. append each line to the backup as it is read:
    - more efficient than current patch (no need to read history twice)
    - potentially duplicate data if backup fails
2017-09-23 13:06:11 -04:00
Ian Walker
e2e9bbacce Move _on_proxy_authentication_required to WebEngineTab 2017-09-23 17:26:41 +09:00
Florian Bruhin
b8389e4496 Revert "Fix NUL byte error handling on Python 3.4"
This reverts commit a7d5a98cc4.
Not needed anymore now that we dropped support.
2017-09-22 22:30:02 +02:00
Florian Bruhin
e8ceeceac8 Fix mock check with Python 3.5
Looks like .assert_not_called() doesn't work on function mocks with 3.5.
2017-09-22 22:28:40 +02:00
Florian Bruhin
459bbc3a6f Add configinit to PERFECT_FILES 2017-09-22 20:26:56 +02:00
Florian Bruhin
4e46c34e5a Use .assert_not_called() for mocks 2017-09-22 19:58:38 +02:00
Florian Bruhin
e27c54a5c1 Fix modeparser tests 2017-09-22 19:49:52 +02:00
Florian Bruhin
5be44756e3 Remove unused imports 2017-09-22 17:29:01 +02:00
Michal Siedlaczek
b840b8066b Spell only when pyqt>=5.8 2017-09-22 11:16:59 -04:00
Florian Bruhin
1e2015be65 Make bindings win over mappings
Fixes #2995
2017-09-22 17:13:17 +02:00
Florian Bruhin
7f4cba8bc2 Improve load_autoconfig docs
Closes #2993
2017-09-22 14:23:41 +02:00
Florian Bruhin
d5a1fff637 Move init stuff from config.py to configinit.py
Closes #2997
2017-09-22 14:11:54 +02:00
Florian Bruhin
d1a4a028cd Use more idiomatic comparison 2017-09-22 13:24:26 +02:00
Florian Bruhin
69d19e49df Fix flake8 2017-09-22 13:20:18 +02:00
Florian Bruhin
501764d1cb Fix documented default values for falsey non-strings
Fixes #3015.
2017-09-22 13:18:27 +02:00
Florian Bruhin
d9a3268405 Explain relationship between 'c' and 'config.set' better
[ci skip]
2017-09-22 11:33:42 +02:00
Florian Bruhin
43ab27634f Fix vulture 2017-09-22 11:07:54 +02:00
Florian Bruhin
7f8ae531aa Add config.configdir and config.datadir to config API.
Fixes #1419
2017-09-22 09:59:46 +02:00
Florian Bruhin
9b22480b07 Raise config.py errors happening in tests 2017-09-22 09:09:45 +02:00
Florian Bruhin
ebf378a945 Add docs about importing modules in config.py 2017-09-22 08:58:41 +02:00
Florian Bruhin
1dbd156c2f Simplify some config.py tests 2017-09-22 08:53:08 +02:00
Florian Bruhin
276b244466 Merge remote-tracking branch 'origin/pr/2970' 2017-09-22 08:37:23 +02:00
Florian Bruhin
10016ae240 Remove unused import 2017-09-22 08:23:06 +02:00
Jay Kamat
43ce10efc3 Simplify and reorganize configfile tests
Also make save/load of sys.path a little more robust
2017-09-22 02:05:55 -04:00
Jay Kamat
4e22b4666d Convert save-restore of sys to a context-manager
Also improve and simplify tests for save/load of sys.module and sys.path
2017-09-22 02:05:55 -04:00
Jay Kamat
7ddde334da Add tests for module/path isolation 2017-09-22 02:05:55 -04:00
Jay Kamat
333c0d848b Restructure save/load of state to be more extensible
Also save/load sys.modules as well
- This is a little rough, but I can't find a better way...
2017-09-22 02:05:54 -04:00
Jay Kamat
0332dce458 Get config path from config.py location, rather than standarddir 2017-09-22 02:05:54 -04:00
Jay Kamat
a2952e13a8 Add qutebrowser config directory to python path
This is done so config.py can import other python files in the config
directory. For example, config.py can 'import theme' which would load
a theme.py.

The previous path is restored at the end of this function, to avoid
tainting qutebrowser's path
2017-09-22 02:05:52 -04:00
Florian Bruhin
c652b0f96c Remove old monkeypatch 2017-09-21 23:59:16 +02:00
Florian Bruhin
f4017eb5b6 Ignore more Python warnings when importing in earlyinit
With a17c4767d6 we moved the first time
pkg_resources is imported to earlyinit.py, which means less warnings were
suppressed.

Fixes #2990
2017-09-21 23:24:22 +02:00
Florian Bruhin
cd9fe57d84 build_release: Also run asciidoc2html on Linux 2017-09-21 23:03:02 +02:00
Florian Bruhin
3f18a5ada7 Update metainfo in setup.py 2017-09-21 22:57:29 +02:00
Florian Bruhin
c74236dd96 Move some data from setupcommon to setup.py
We can't get rid of setupcommon entirely (it's needed by PyInstaller), but at
least we can get the data back to setup.py.

Fixes #2996
2017-09-21 22:54:58 +02:00
Florian Bruhin
599a5b9648 Remove windows/pip instructions from earlyinit
Windows: The instructions are outdated and not really relevant anymore with the
standalone packages;

pip: Let's recommend tox/virtualenv by just linking to the install docs.

Closes #2998
2017-09-21 22:48:15 +02:00
Michal Siedlaczek
2150154350 Skip end2end spell tests if a dictionary is/isn't installed 2017-09-21 16:36:47 -04:00
Florian Bruhin
1c76a51c1e Improve configtypes.Command docs 2017-09-21 22:31:11 +02:00
Michal Siedlaczek
396f82d474 Valid dictionaries 2017-09-21 16:30:58 -04:00
Florian Bruhin
64b783d9c0 Do not validate commands in the config and with :bind
There are just way too many gotchas related to valid modes, aliases, and
circular dependencies when validating aliases/bindings in the config.

Let's just remove this and let invalid commands fail late, when they're actually
used.
2017-09-21 22:30:48 +02:00
Florian Bruhin
f97f427100 Add an assertion for Completer._partition 2017-09-21 21:50:33 +02:00
Florian Bruhin
32b2b3dfd9 Add test for invalid value type in YAML file 2017-09-21 21:15:37 +02:00
Florian Bruhin
b1ddb9a6df Remove confusing test
That's not the behavior we actually have in the config anymore when using
conf._yaml.load().
2017-09-21 20:27:45 +02:00
Florian Bruhin
691cd2d09b More test_configfiles cleanups 2017-09-21 20:19:02 +02:00
Florian Bruhin
3e0d49a4b3 Add TestYaml class to test_configfiles 2017-09-21 19:57:54 +02:00
Florian Bruhin
f821fb793a Initialize configdata in test_configfiles 2017-09-21 19:37:22 +02:00
Michal Siedlaczek
9e620ce6e9 Fix spell with new config 2017-09-21 12:09:55 -04:00
Florian Bruhin
2f7cbfa1ee Make sure the changelog is in releases
[ci skip]
2017-09-21 17:42:57 +02:00
Florian Bruhin
7cad8f41f2 Remove unknown YAML data from config
I considered introducing another list of deleted options (or a "deleted: True"
in configdata.yml), similar to what we had with the old config.

However, let's take the easier route and just delete everything we don't know
from configdata.yml. If someone edits it by hand, it's their fault :P

See #2772, #2847
2017-09-21 16:29:40 +02:00
Michal Siedlaczek
132b1f705e Revert requirements changes 2017-09-21 09:56:38 -04:00
Michal Siedlaczek
329cfa5756 End2end tests for spell checking 2017-09-21 09:56:33 -04:00
Michal Siedlaczek
cf229cb9c8 Dictionary path bug fix & added warning whenever a selected dictionary isn't installed 2017-09-21 09:56:27 -04:00
Michal Siedlaczek
e61e6b124e Check if spelling supported by QWebEngineProfile (version 5.8 or higher) 2017-09-21 09:56:27 -04:00
Michal Siedlaczek
95592770a7 Fixing test dependencies and other test issues 2017-09-21 09:53:51 -04:00
Michal Siedlaczek
fac0e44a7e Test all available languages and getting installed langs when the dir doesn't exist 2017-09-21 09:52:31 -04:00
Michal Siedlaczek
82433e04ad Set default value for spelling settings and limit number of installed languages for testing 2017-09-21 09:52:09 -04:00
Michal Siedlaczek
d923ab9ae5 Moved and renamed the language list file 2017-09-21 09:51:52 -04:00
Michal Siedlaczek
c2197102a3 Enable spell checking and installing dictionaries for QtWebEngine 2017-09-21 09:51:52 -04:00
Florian Bruhin
cb57525f69 Fix whitespace 2017-09-21 13:43:30 +02:00
Florian Bruhin
a559477028 Merge remote-tracking branch 'origin/pr/2953' 2017-09-21 13:43:01 +02:00
Florian Bruhin
e0e7d4ca67 Stabilize test_quitting_process_expected 2017-09-21 13:42:24 +02:00
Florian Bruhin
53b1ffe953 Merge remote-tracking branch 'origin/pr/2965' 2017-09-21 09:12:56 +02:00
Florian Bruhin
9a6de48efa Break long line 2017-09-21 09:12:25 +02:00
Florian Bruhin
fb33985f07 Merge remote-tracking branch 'origin/pr/2992' 2017-09-21 09:12:03 +02:00
Florian Bruhin
192c063743 Mark another window.open test as flaky
See https://travis-ci.org/qutebrowser/qutebrowser/jobs/277846887
2017-09-21 08:58:56 +02:00
Florian Bruhin
106edc953a Merge branch 'is-os' 2017-09-21 08:57:32 +02:00
Jay Kamat
d5c2f2855a Clean up pinned_tab width implementation
Misc fixes from PR
2017-09-20 20:48:48 -04:00
Florian Bruhin
9913550688 Fix windows condition 2017-09-20 18:28:18 +02:00
Jay Kamat
e49aa35c75 Remove pinned_width variables
Now it calculates the number of pinned tabs directly, instead of
keeping track of a variable. Potentially slower though.
2017-09-20 11:31:05 -04:00
Jay Kamat
da57d21f0c Remove pinned-width from config 2017-09-20 11:31:05 -04:00
Jay Kamat
b46f116075 Switch pinned tabs to use their title width
Previously, their width was determined by a config setting
Closes #2845
2017-09-20 11:31:03 -04:00
Florian Bruhin
9d360f80cf Use __attrs_post_init__ to validate ArgInfo
This makes qutebrowser compatible with attrs < 17.1.0, such as attrs 16.3.0
coming with Debian Stretch.
2017-09-20 17:27:28 +02:00
Felix Van der Jeugt
6892705e18 cover setting-saving-loading-getting yaml config 2017-09-20 15:52:42 +02:00
Penaz91
6132a3d7ca Made _handle_auto_insert_mode public 2017-09-20 15:52:07 +02:00
Penaz91
7f03b0d0d5 Deleted a commented-out line 2017-09-20 13:37:40 +02:00
Penaz91
ccba76f757 Fix for Issue #2879 2017-09-20 13:31:44 +02:00
Penaz91
f5c15b6ce8 Merge branch 'qutebrowser-master' 2017-09-20 13:23:40 +02:00
Penaz91
6a997851eb Merge branch 'master' of https://github.com/qutebrowser/qutebrowser into qutebrowser-master 2017-09-20 13:23:20 +02:00
Ryan Roden-Corrent
5cd00f699e Resolve KeyError when deleting URL with space.
Resolves #2963.
2017-09-20 07:15:59 -04:00
Ryan Roden-Corrent
f9440b8026 Use CommandParser for configmodel.bind.
The parsing bind() did manually is now available through CommandParser.
Resolves #2952.

This also adds a unit test for the case when there is no current
binding, as I broke that while working on this and there was no test to
catch it :)
2017-09-20 07:05:38 -04:00
Florian Bruhin
1d964ccdaf Only run system datadir test on Linux 2017-09-20 12:20:46 +02:00
Florian Bruhin
2a4f10f0f5 Add qapp for tabbed_browser_stubs 2017-09-20 11:30:18 +02:00
Florian Bruhin
46cfd5353d Use a pytest marker to fake an OS 2017-09-20 11:30:18 +02:00
Florian Bruhin
ef1c83862b Use utils.is_* for platform checks everywhere 2017-09-20 11:10:24 +02:00
Florian Bruhin
e4594bd688 Use attributes for utils.is_* 2017-09-20 11:10:23 +02:00
Florian Bruhin
9ddc59e8e5 Also add utils.is_posix() 2017-09-20 11:10:23 +02:00
Florian Bruhin
e50ab3f72c Merge remote-tracking branch 'origin/pr/2972' 2017-09-20 10:08:08 +02:00
Felix Van der Jeugt
285b534384 make changed dirty and save on duplicate write 2017-09-20 10:04:34 +02:00
Florian Bruhin
31bd4d7ffe Make sure ProxyId is hashable
Fixes proxy auth with QtWebEngine
2017-09-20 09:30:58 +02:00
Florian Bruhin
10c84dfb90 Use unpacking to access config mutables 2017-09-20 08:52:11 +02:00
Florian Bruhin
55cbb39127 Merge remote-tracking branch 'origin/pr/2999' 2017-09-20 08:48:22 +02:00
Florian Bruhin
50b19462f4 Bring back accidentally deleted hunk 2017-09-20 08:17:04 +02:00
Florian Bruhin
ba1cf06be6 Reintroduce handling for typing.Union.__union_params__
Looks like Python 3.5.2 doesn't have typing.Union.__args__.
2017-09-20 08:17:04 +02:00
Florian Bruhin
a519d54e7d Remove hypothesis strict setting
It was deprecated as normal python warnings are used now
2017-09-20 08:17:04 +02:00
Florian Bruhin
54ceb52eaf Switch to using Item.get_report() for vulture 2017-09-20 08:17:04 +02:00
Florian Bruhin
1d2d31d0f9 Remove duplicate key mapping 2017-09-20 08:17:04 +02:00
Florian Bruhin
22be2bf7ab Fix circular import in ImportFake in test_version
We can't use importlib.import_module() when we patched that away...
2017-09-20 08:17:04 +02:00
Florian Bruhin
f74d93b4e9 Merge pull request #3000 from swalladge/fix_readme_link
fix link to configuring page in readme
2017-09-20 08:06:07 +02:00
Samuel Walladge
5b8b6cfa99 fix link to configuring page in readme 2017-09-20 15:29:09 +09:30
Ian Walker
a3456c41e4 Mark url argument as unused 2017-09-20 12:51:38 +09:00
Ryan Farley
dd4294de03 fix #2979: use dictionary for mutable tracking
Using a dictionary instead of a list keeps only one working copy,
allowing consistency in between calls of update_mutables()
2017-09-19 16:26:02 -05:00
Florian Bruhin
1de25c14e4 Add attrs to setup.py 2017-09-19 22:36:37 +02:00
Florian Bruhin
58a43d0851 Update changelog 2017-09-19 22:23:32 +02:00
Florian Bruhin
3a5241b642 Start using attrs
Closes #1073
2017-09-19 22:21:45 +02:00
Ryan Farley
a530b0cc95 fixed iteration 2017-09-19 14:19:28 -05:00
Ryan Farley
cc540bb166 Merge branch 'master' into mutable-dict 2017-09-19 14:07:46 -05:00
Ryan Farley
83473b9c69 fix test for new tuples 2017-09-19 14:00:44 -05:00
Felix Van der Jeugt
8e14d1b7e6 remove unused import 2017-09-19 17:47:38 +02:00
Felix Van der Jeugt
8db630d358 don't copy values but set dirty 2017-09-19 17:26:03 +02:00
Felix Van der Jeugt
7b192d426e add unit test and fix issues with it 2017-09-19 15:30:28 +02:00
Florian Bruhin
7226750363 Bump up Hypothesis deadline globally 2017-09-19 15:08:56 +02:00
Felix Van der Jeugt
0e743f0e09 save only a changed autoconfig file 2017-09-19 14:33:34 +02:00
Florian Bruhin
1a1a6ebf79 Improve bind documentation
[ci skip]
2017-09-19 13:56:29 +02:00
Florian Bruhin
bb073e1709 Bump up another hypothesis deadline 2017-09-19 13:38:44 +02:00
Florian Bruhin
248afde21e configapi: Also allow mode as posarg 2017-09-19 13:18:44 +02:00
Florian Bruhin
e8ae672c93 Check for read errors in test_configfiles 2017-09-19 13:18:16 +02:00
Florian Bruhin
7d1549aaeb Make mode optionally in ConfigAPI.bind and .unbind 2017-09-19 13:14:41 +02:00
Florian Bruhin
a23492fe27 Bump up hypothesis deadline for Content-Disposition test 2017-09-19 11:16:03 +02:00
Florian Bruhin
51afe14965 Set backend to QtWebKit in cookie tests 2017-09-19 11:07:11 +02:00
Florian Bruhin
cfbe0f8cbc Update dependencies in README
[ci skip]
2017-09-19 10:46:46 +02:00
Florian Bruhin
59236802c1 Update dependencies
Closes #2985
2017-09-19 10:41:57 +02:00
Florian Bruhin
55a4eb18f2 Get rid of httpbin
Fixes #2949
2017-09-19 10:35:54 +02:00
Florian Bruhin
40b26d7492 Always require QtOpenGL
It makes it a bit easier to explain things, and it makes the transition to
QtWebEngine smoother.
2017-09-19 08:16:26 +02:00
Florian Bruhin
97a7cee878 Update documentation for installing via tox 2017-09-19 07:57:49 +02:00
Florian Bruhin
e9b8288e4b Add a test for Config._set_value without backend 2017-09-19 07:08:56 +02:00
Florian Bruhin
13a8867e13 Add tests for config.get_backend() 2017-09-19 07:05:36 +02:00
Florian Bruhin
7bece81519 Make sure tests always have object.backend set 2017-09-19 06:46:08 +02:00
Florian Bruhin
43ff79be0b Merge branch 'drop-legacy' 2017-09-18 23:07:58 +02:00
Florian Bruhin
8ae87bbde2 Remove typing module from version.py
It comes with python now
2017-09-18 23:06:49 +02:00
Florian Bruhin
b1b6c462c1 Add a backend setting
See #2589
2017-09-18 23:02:08 +02:00
Florian Bruhin
61e183d9bb Fix indent 2017-09-18 23:01:18 +02:00
Florian Bruhin
cd701e95fa Reintroduce __hash__ for CertificateErrorWrapper 2017-09-18 23:01:18 +02:00
Florian Bruhin
5c0ebc1f94 Fix lint 2017-09-18 23:01:18 +02:00
Florian Bruhin
f10d334c90 Remove Python 3.5 block for Gentoo 2017-09-18 23:01:17 +02:00
Florian Bruhin
3772dc5930 Drop legacy QtWebKit support
See #2742
2017-09-18 23:01:17 +02:00
Florian Bruhin
3e70bf5af9 Make sure we never compare against an uninit'ed backend 2017-09-18 23:01:17 +02:00
Florian Bruhin
5298d14084 Move backend initialization to config.py 2017-09-18 23:01:17 +02:00
Florian Bruhin
01da144a03 Revert ipc.py socket opts handling 2017-09-18 23:01:17 +02:00
Florian Bruhin
a17c4767d6 Check libraries before Qt version
Importing qtutils for version_check needs pkg_resources, so we need to check
that's available earlier.

Also, import pkg_resources also shows warnings on older setuptools versions
because of invalid escapes, so we need to import it with warnings suppressed.
2017-09-18 23:01:17 +02:00
Florian Bruhin
db807a1bbc Reintroduce downloadview workaround
This still seems to be an issue on AppVeyor
2017-09-18 23:01:17 +02:00
Florian Bruhin
cf07bfc5c5 Make sure the :set-cmd-text command is registered 2017-09-18 23:01:17 +02:00
Florian Bruhin
505321c336 Drop support for Python 3.4
See #2742
2017-09-18 23:01:17 +02:00
Florian Bruhin
852baaa8c3 Drop support for Qt < 5.7.1
See #2742
2017-09-18 23:01:17 +02:00
Florian Bruhin
2b4304908a Drop Debian Jessie / Ubuntu Xenial from Travis
Closes #2780
2017-09-18 23:00:49 +02:00
Florian Bruhin
ee4d92364e Fix off-by-one issue for odd/even tabs 2017-09-18 14:29:14 +02:00
Ian Walker
9867200c38 Change username/password prompt for proxyAuthenticationRequired
Update webview.py to more closely follow the webkit/networkmanager.py
on_proxy_authentication_required().
2017-09-18 15:55:44 +09:00
Florian Bruhin
8e2b2d113b Improve explanations for dicts in the config 2017-09-18 06:25:39 +02:00
Ryan Farley
c6ea0f8372 Use dictionary for configuration mutable storage
Includes a test for persistence of intermediate mutations in a
configuration file (i.e. more than one update) and a switch of the
_mutable attribute in configurations to a dictionary of (old, new)
values rather than (name, old, new). get_obj() now checks for an
existing mutable value and returns a reference to that value, only
making an initial copy; this preserves changes between update_mutables()
2017-09-17 16:07:52 -05:00
Florian Bruhin
66e4c3286a Fix lint 2017-09-17 22:53:32 +02:00
Florian Bruhin
f83696a670 Update changelog 2017-09-17 22:53:32 +02:00
Florian Bruhin
fe05947b54 Add a new qt_args setting
See #2589
2017-09-17 22:53:27 +02:00
Florian Bruhin
34042522f1 Set default hints font in pt and not px 2017-09-17 22:13:13 +02:00
Florian Bruhin
7b42e38dae Fix more file move issues 2017-09-17 22:10:06 +02:00
Florian Bruhin
1959a76393 Update contributing docs 2017-09-17 22:06:56 +02:00
Florian Bruhin
2398a58526 Fix more file move issues 2017-09-17 21:54:42 +02:00
Florian Bruhin
b711d15617 Try to fix file moving issues 2017-09-17 21:49:49 +02:00
Florian Bruhin
73873c5bbd Update changelog 2017-09-17 21:45:18 +02:00
Florian Bruhin
6191a81eff Move qutebrowser.desktop to misc/ 2017-09-17 21:40:35 +02:00
Florian Bruhin
609ed6d261 Make codecov.yml hidden 2017-09-17 21:40:35 +02:00
Florian Bruhin
4c616a5733 Move all documentation files to doc/ 2017-09-17 21:27:38 +02:00
Florian Bruhin
3e0ca5d94d Stop using objreg for state-config 2017-09-17 21:04:34 +02:00
Florian Bruhin
70b8585e95 Move qtutils.unset_organization to standarddir 2017-09-17 20:44:08 +02:00
Florian Bruhin
f40103cbba Don't require qapp for configtypes tests anymore
We need to make sure they work without a QApplication, and the only reason they
needed one before was standarddir.
2017-09-17 20:38:34 +02:00
Ryan Farley
b35a808712 test multiple mutations for config
This detects the problem in #2979
2017-09-17 13:24:05 -05:00
Florian Bruhin
6f1b8bd1d9 Make sure the config is available before the QApplication
See #2589
2017-09-17 20:06:35 +02:00
Florian Bruhin
21a10fcb17 Break up long line 2017-09-17 16:33:37 +02:00
Florian Bruhin
e4d05e3fec Log error information when config init fails 2017-09-17 14:13:36 +02:00
Florian Bruhin
884f73f349 Mention how c works in configuring docs 2017-09-17 12:35:29 +02:00
Florian Bruhin
62b30af12a Fix unit tests for end2end SQL change 2017-09-17 11:49:42 +02:00
Florian Bruhin
36ca819cb3 Merge branch 'standarddir' 2017-09-17 11:19:26 +02:00
Florian Bruhin
975df02704 Improve configuring docs
Thanks Meline! :)
2017-09-17 11:17:59 +02:00
Florian Bruhin
f85f4630ff Turn off SQL history writing during end2end tests
This hopefully makes them a bit faster, and also should help with weird hangs we
had in tests.
2017-09-17 10:58:30 +02:00
Florian Bruhin
f6d878f33f Mark window.open test as flaky 2017-09-17 10:36:28 +02:00
Florian Bruhin
f29bafcdb2 Fix expected dir on macOS 2017-09-17 10:35:05 +02:00
Florian Bruhin
7ed64efa08 Fix standarddir.cache() on Windows 2017-09-17 10:35:05 +02:00
Florian Bruhin
d4709f7c44 Fix docs for bindings.default 2017-09-17 09:50:10 +02:00
Florian Bruhin
b31db0d0d5 Add another str() for paths
Using py.path for os.path is only supported since 3.6
2017-09-17 09:49:06 +02:00
Florian Bruhin
5aa653a54f Fix IPC socket location test
We use fake_runtime_dir which simply patches XDG_RUNTIME_DIR for this test.
Since we patch QApplication.applicationName() during the tests, but standarddir
doesn't use that anymore, we get a different name.
2017-09-17 09:49:06 +02:00
Florian Bruhin
df9726a152 Fix standarddir without AppDataLocation 2017-09-17 09:49:06 +02:00
Lakshay Kalbhor
813a7b2c3a Removed if statements 2017-09-17 10:56:53 +05:30
Lakshay Kalbhor
476ca6d42f Added 'startswith()' to each OS 2017-09-17 10:27:21 +05:30
Florian Bruhin
9354297276 Add test for standarddir without QApplication
See #2791.
2017-09-16 23:48:06 +02:00
Florian Bruhin
9706dcbda5 Fix lint 2017-09-16 23:48:02 +02:00
Florian Bruhin
a1fa40f067 Remove the ability to migrate old QtWebEngine data
Versions before v0.9.0 (which didn't even support hinting with QtWebEngine!)
used to write QtWebEngine data to:

~/.local/share/qutebrowser/qutebrowser/QtWebEngine/Default
~/.cache/qutebrowser/qutebrowser/QtWebEngine/Default

In v0.9.0 this was changed to:

~/.local/share/qutebrowser/webengine
~/.cache/qutebrowser/webengine

Now we don't try to migrate data from the old location anymore.
2017-09-16 23:48:02 +02:00
Florian Bruhin
a85e19a5e1 Add initial support for early standarddir init
See #2589, #2791
2017-09-16 23:47:22 +02:00
Florian Bruhin
046a16f924 Bind <Ctrl-Shift-N> and <Ctrl-Shift-W> by default
See #2954
2017-09-16 22:22:36 +02:00
Florian Bruhin
7c11d3ecd9 Document new default values in configuring docs 2017-09-16 22:18:44 +02:00
Florian Bruhin
624c3a4c27 Merge branch 'new-config' 2017-09-16 16:12:21 +02:00
Florian Bruhin
1aa918bb86 Add configdata.yml to qutebrowser.spec for PyInstaller 2017-09-16 16:12:00 +02:00
Lakshay Kalbhor
c5ceb6b880 Added functions to check OS/Platform 2017-09-16 19:23:05 +05:30
Florian Bruhin
8420f03f18 Fix some issues with configuring.asciidoc 2017-09-16 15:22:53 +02:00
Florian Bruhin
0ae1f5909d Strip the old text for configdiff
This means we don't report an unneeded whitespace hunk anymore.
2017-09-16 14:41:37 +02:00
Florian Bruhin
2afd7549bc Encode Unicode in old config as escapes
This seems to fix #2971.
2017-09-16 14:39:37 +02:00
Florian Bruhin
800464d311 Fix dict documentation in configuring.asciidoc 2017-09-16 14:20:48 +02:00
Florian Bruhin
714c18db0e Fix \b escapes in old config file 2017-09-16 14:20:08 +02:00
Florian Bruhin
0aa85f5967 Skip SSL download test if SSL is not supported
This makes the testsuite pass entirely with a PyPI PyQt and OpenSSL 1.1
2017-09-16 10:43:59 +02:00
Florian Bruhin
3179e8c7b9 Always autoescape jinja environments unless overridden
We were only rendering .html files before, so the old _guess_autoescape function
had the effect of always autoescaping .render() (from a file) but never
autoescaping .from_string(). However, most places using .from_string() actually
render (Qt-)HTML via jinja, so they should escape stuff!

Now, we always autoescape, except when the caller uses the
jinja.environment.no_autoescape() context manager, which places rendering
stylesheets now do.

This impacted:

- Confirm quit texts (no HTML here)
- config.py loading errors
  (where this was found because of an error containing - a <keybinding>)
- Certificate error prompts
  (should be fine from what I can tell, as the only user-controllable output is
  the hostname, which cannot contain HTML)
2017-09-16 10:43:59 +02:00
Florian Bruhin
337d57b940 Be more clever about missing qute://help pages 2017-09-16 10:43:59 +02:00
Ian Walker
eaa1bdcddb Show error page when user cancels proxy authentication dialog 2017-09-16 17:13:16 +09:00
Ian Walker
9face7567c Removed QAuthenticator import 2017-09-16 17:01:18 +09:00
Florian Bruhin
c8f3743008 Remove auto_save.config setting
This is not needed anymore now that we have config.load_autoconfig=False and
wasn't even read anywhere.
2017-09-15 22:22:09 +02:00
Florian Bruhin
1bcc66b5b9 Add documentation for new config
This also changes qute://help to show the documentation generation error if a
help page wasn't found. This way, people who pull from git but not re-generate
the documentation hopefully get the idea.
2017-09-15 22:22:09 +02:00
Florian Bruhin
4f6e085be8 Quote a completed value if it contains " 2017-09-15 22:17:38 +02:00
Florian Bruhin
a7d5a98cc4 Fix NUL byte error handling on Python 3.4
Looks like Python 3.4 raises TypeError and not ValueError...
2017-09-15 22:17:38 +02:00
Florian Bruhin
d901bee88e Fix test_oserror on older Pythons 2017-09-15 22:17:38 +02:00
Florian Bruhin
543bc3bcaa Fix default :open keybindings
:open -i (--implicit) is now -r (--related).
2017-09-15 22:17:38 +02:00
Florian Bruhin
42039eee99 Fully remove ConfigAPI.val 2017-09-15 19:01:03 +02:00
Florian Bruhin
3be7299cb4 Fix completions for FlagList 2017-09-15 18:41:08 +02:00
Florian Bruhin
54c417391d Add a qute://configdiff page 2017-09-15 18:26:33 +02:00
Florian Bruhin
2e8419db27 Fix lint 2017-09-15 17:24:39 +02:00
Florian Bruhin
c9625cb311 Add more tests for YAML error handling 2017-09-15 17:21:11 +02:00
Florian Bruhin
3f8817cc2d Use blocking message boxes for config errors 2017-09-15 17:21:11 +02:00
Florian Bruhin
745ef63451 Start implementing autoconfig.yml error handling 2017-09-15 17:21:11 +02:00
Florian Bruhin
a92ffd9770 Improve NoOptionError traceback 2017-09-15 17:21:11 +02:00
Florian Bruhin
413c7ec1ac Add config type docstrings to settings.asciidoc 2017-09-15 17:21:11 +02:00
Florian Bruhin
d7d8d191c0 Remove FIXMEs
backend validation: I decided not to do this, as it is quite annoying when
switching between backends.
2017-09-15 17:20:58 +02:00
Florian Bruhin
3d3391b55e Clean up *_tmpdir fixtures 2017-09-15 14:32:03 +02:00
Florian Bruhin
fa4ea912c9 Get rid of init_standarddir fixture
Instead, always patch in tmpdir's so we don't write to qute_test folders.
2017-09-15 14:30:46 +02:00
Florian Bruhin
e87a782411 Move command-history init to cmdhistory.py 2017-09-15 14:27:15 +02:00
Florian Bruhin
54214873f4 Resurrect :debug-cache-stats test 2017-09-15 14:16:42 +02:00
Florian Bruhin
54dfc083f9 Remove default_config fixture 2017-09-15 14:13:27 +02:00
Florian Bruhin
9f955f251a Reshape comments 2017-09-15 14:11:45 +02:00
Florian Bruhin
ee5dd7fad2 Remove interpolation FIXME and DEFAULT_FONT_SIZE
This is just not going to happen, and with the new config we have no good way of
supporting a DEFAULT_FONT_SIZE.
2017-09-15 14:11:10 +02:00
Florian Bruhin
e0621c6eda Fix initializing without a config.py 2017-09-15 14:08:37 +02:00
Florian Bruhin
7c39600508 Change default bindings for Up/Down in command mode
Those now look at the history again.
Looking at the behavior in different applications:

- vim: History
- spacemacs: Completion if open, else history
- luakit: Completion if open, else history
- dwb: Always completion (has no history?)
- vimb: Nothing if completion open, else history
- vimperator: Always history

So this is consistent with at least some of them - the much more important
factor is that <Tab> is probably intuitively easy to discover if up/down doesn't
do what's expected, but <ctrl-p>/<ctrl-n> are not.
2017-09-15 14:08:37 +02:00
Florian Bruhin
f406e8d9ca Remove config.val support for config.py 2017-09-15 14:08:37 +02:00
Florian Bruhin
25baf3b97e Add more tests for config.py error handling 2017-09-15 13:30:09 +02:00
Florian Bruhin
bb648b62f3 Make sure we honour config_api.load_autoconfig even with errors
We don't raise ConfigFileErrors inside read_config_py so we can get back the
config_api object. Instead we raise it in config.init().
2017-09-15 12:07:54 +02:00
Florian Bruhin
5efce10c2c Add initial tests for config.py error handling 2017-09-15 12:07:54 +02:00
Florian Bruhin
4da9b8c495 check_coverage: Truncate long floats 2017-09-15 12:07:54 +02:00
Florian Bruhin
c5c566aadc tests: Bump up timeout for CallbackChecker 2017-09-15 12:07:54 +02:00
Florian Bruhin
bbffda669a Fix lint 2017-09-15 12:07:54 +02:00
Florian Bruhin
c031a7ab3d Fix another Python 3.4 circular import 2017-09-15 12:07:54 +02:00
Florian Bruhin
b8fb88f4c2 Improve config error handling
- Errors are now combined if possible
- Rich text output in message boxes
- ConfigContainer errors are collected properly
2017-09-15 12:07:54 +02:00
Ian Walker
506ee571b1 Add handler for proxyAuthenticationRequired() 2017-09-15 08:36:59 +09:00
Florian Bruhin
490de32b49 Initial attempt at error handling for config.py 2017-09-14 21:51:29 +02:00
Florian Bruhin
5a11c96e56 Don't fail tests because of OpenSSL 1.1 warnings
"Downloading with SSL errors" from downloads.feature still fails, but like this,
at least all other tests pass without the need to modify LD_LIBRARY_PATH.
2017-09-14 18:23:40 +02:00
Florian Bruhin
b3734b151b Handle mutations in config.py correctly 2017-09-14 17:38:33 +02:00
Florian Bruhin
cb806aefa3 Initial config.py support
See #2795
2017-09-14 17:38:33 +02:00
Florian Bruhin
ed6933a839 tests: Ignore "Invalid node channel message" log from Chromium 2017-09-14 16:15:07 +02:00
Florian Bruhin
0a3a1b756d Mark confirm_quit test to only run on Windows
See #2964
2017-09-14 16:14:01 +02:00
Florian Bruhin
6618c3a6e8 Don't use shlex for configtypes.ShellCommand
We accidentally did show the command as a list in to_str(). However, after
correcting that to use shlex.escape, we got ugly qutebrowser command lines
when tabbing to the default value, because of how shlex handles double-escaping:

>>> print(shlex.quote("gvim -f '{}'"))
'gvim -f '"'"'{}'"'"''

While in this case, outputting "gvim -f '{}'" would be much more appropriate, it
doesn't look like we can teach shlex.quote to do that.

Instead, we now only accept a list as input for ShellCommand, at the price that
the user needs to do
  :set editor.command '["gvim", "-f", "{}"]'
instead of
  :set editor.command 'gvim -f {}'

Fixes #2962.
2017-09-14 14:44:24 +02:00
Florian Bruhin
12260e068a Don't move cache directory on Windows 2017-09-14 13:35:42 +02:00
Florian Bruhin
5cd14c941b Fix race condition is :jseval test 2017-09-14 09:33:58 +02:00
Florian Bruhin
0de7b2eb83 Skip standarddir migrations when a basedir is given 2017-09-14 00:37:54 +02:00
Florian Bruhin
3dc67df180 Fix minor standarddir migration issues 2017-09-14 00:37:54 +02:00
Florian Bruhin
d1e69a75dd tests: Ignore some more Mac Mini messages 2017-09-14 00:37:54 +02:00
Florian Bruhin
cee51df4fb Refactor JS log handling and use a dict for javascript.log
Fixes #2828
2017-09-14 00:37:01 +02:00
Florian Bruhin
1fc9817cd4 Remove support for ambiguous keybindings 2017-09-14 00:37:01 +02:00
Florian Bruhin
bf9d401198 Reorder statusbar settings in configdata.yml 2017-09-13 21:32:36 +02:00
Florian Bruhin
13f49738d7 Fix typo in content.user_stylesheets 2017-09-13 21:32:36 +02:00
Florian Bruhin
8537e92d39 Add backend: QtWebKit for hints.find_implementation 2017-09-13 21:32:36 +02:00
Florian Bruhin
9d95dec5ea Handle standarddir.config() correctly on macOS
With auto=False we should get ~/.qutebrowser
2017-09-13 21:32:36 +02:00
Florian Bruhin
08b5fc8e3b Stabilize qute://plainlog test
Looks like we actually get a loading event on Qt 5.9 just fine, and there was a
race condition here otherwise.
2017-09-13 21:32:36 +02:00
Florian Bruhin
718dd21573 Handle auto-config location properly with --basedir 2017-09-13 21:32:36 +02:00
Florian Bruhin
70a9a7e5c8 Fix macOS testsuite issues 2017-09-13 21:32:36 +02:00
Florian Bruhin
231193f7a6 Fix standarddir test coverage 2017-09-13 21:32:36 +02:00
Florian Bruhin
2f394d3c9f Mock out all moving functions for standarddir.init() 2017-09-13 21:32:36 +02:00
Florian Bruhin
50aab7a802 Skip tests needing AppDataLocation on older Qt versions 2017-09-13 21:32:22 +02:00
Florian Bruhin
f7d17c4c55 Allow existing empty dir when migrating files
Remove old empty directory if it exists - otherwise, we move old/data to
new/data/data.
2017-09-13 21:32:22 +02:00
Florian Bruhin
0498e042a0 Ignore another macOS log line 2017-09-13 21:32:22 +02:00
Florian Bruhin
e84c1fa82f Call _init_config in test_fake_mac_auto_config 2017-09-13 21:32:22 +02:00
Florian Bruhin
2a9441dfbf Make moving data in standarddir more generic 2017-09-13 21:32:22 +02:00
Florian Bruhin
8c4bc76de6 Stabilize hint test which failed on macOS 2017-09-13 17:26:56 +02:00
Florian Bruhin
ad2598b475 Add initial support for standarddir.config(auto=True)
This doesn't actually migrate things yet.
See #2791, #383.
2017-09-13 17:26:56 +02:00
Florian Bruhin
a2f16dbecd Merge standarddir.system_data() into standarddir.data(system=True)
See #2791
2017-09-13 17:26:56 +02:00
Florian Bruhin
2d500d4efa Also don't create ~/Downloads in standarddir.downloads()
This means we need to create it in downloads.py instead.

Fixes #2418
2017-09-13 17:26:56 +02:00
Florian Bruhin
91f5e72f02 Remove download dir from path info
This always returns the default Qt path (e.g. ~/Downloads) and also creates it
each time.

See #2418
2017-09-13 17:26:56 +02:00
Florian Bruhin
a1f91f799f Add completion.util to PERFECT_FILES 2017-09-13 17:26:56 +02:00
Florian Bruhin
1fe1cd45f5 Remove dead code
This code is not called/needed anymore with the changes done in the new-config
branch.
2017-09-13 17:26:56 +02:00
Florian Bruhin
b185e57406 Remove change_qapp_name in test_standarddir
This is already done in conftest.py anyways
2017-09-13 17:26:56 +02:00
Florian Bruhin
56bbd73622 Introduce standarddir caching
This makes things a bit more complicated, but is needed to make standarddir (and
thus the config) work without a QApplication.
2017-09-13 17:26:56 +02:00
Florian Bruhin
56b673ca05 tests: Don't use <Ctrl+Backspace> to clear qute://settings fields
This won't work on macOS
2017-09-13 10:29:54 +02:00
Florian Bruhin
5d50ec612d Disable qsettings subdir test on macOS
QSettings uses a plist file there.
2017-09-13 10:21:23 +02:00
Florian Bruhin
40882c4ce2 Fix python version for -cov envs 2017-09-13 00:53:33 +02:00
Florian Bruhin
73ea316501 Use upper-case Monospace in test_progress_affecting_statusbar_height
While the test worked again with eb4691adfc, it
broke again immediately because of 40ee89bddc.

With that fix in, the lower-case monospace in the set value was immediately
replaced by the full list of fonts again. With an upper-case Monospace, this
won't happen.

Fixes #2825, for real this time.
2017-09-12 22:51:52 +02:00
Florian Bruhin
b04a233e8d Adjust :unbind signature to match :bind 2017-09-12 22:51:52 +02:00
Florian Bruhin
f70c5968a9 Improve documentation for command modes 2017-09-12 22:12:37 +02:00
Florian Bruhin
07079664a6 Don't use alias in default binding
See #2957
2017-09-12 22:12:37 +02:00
Florian Bruhin
eb4691adfc Fix test_progress_affecting_statusbar_height on Windows
Fixes #2825
2017-09-12 22:12:37 +02:00
Florian Bruhin
40ee89bddc Initialize monospace fonts in tests properly
See #2825
2017-09-12 22:12:37 +02:00
Florian Bruhin
a60e932454 Remove :wq from docs 2017-09-12 22:12:37 +02:00
Florian Bruhin
bcb486379a Fix python version for -cov envs 2017-09-11 22:43:45 +02:00
Florian Bruhin
fe8ffcc5c3 Quote default xos4 Terminus font properly 2017-09-11 21:50:35 +02:00
Florian Bruhin
9bcd120dcc Only mark completion issue as flaky 2017-09-11 19:33:27 +02:00
Florian Bruhin
a4e215cee4 AppVeyor: Use PyQt 5.9 2017-09-11 19:09:49 +02:00
Florian Bruhin
f6a0500bd3 Merge branch 'master' into new-config
This pulls the travis changes to drop the old Qt 5.2 environment.
2017-09-11 18:39:41 +02:00
Florian Bruhin
9b8c21cace travis: Stop marking macOS as allowed to fail 2017-09-11 18:33:08 +02:00
Florian Bruhin
a65d70820a Add macOS xfail for session completion test
See #2956
2017-09-11 18:33:08 +02:00
Florian Bruhin
50d43b0678 Fix some macOS testsuite issues 2017-09-11 18:33:08 +02:00
Florian Bruhin
2538fec0c5 Ignore Mach IPC message 2017-09-11 18:33:08 +02:00
Florian Bruhin
c62e748b7b travis: Use Python 3 pip 2017-09-11 18:33:08 +02:00
Florian Bruhin
4794d1970b travis: Update macOS 2017-09-11 18:33:07 +02:00
Florian Bruhin
f320da07b4 Increase timeout for test_version 2017-09-11 18:33:07 +02:00
Florian Bruhin
836c8de87d travis: Use Python 3.6 everywhere 2017-09-11 18:32:23 +02:00
Florian Bruhin
37464c8e3a travis: Re-add installing eslint to travis_install 2017-09-11 18:32:23 +02:00
Florian Bruhin
9e10f891ff Print output earlier in test_version 2017-09-11 18:32:23 +02:00
Florian Bruhin
9a8088586f tests: Ignore dbus-uuidgen error messages 2017-09-11 18:32:23 +02:00
Florian Bruhin
816369f0ef travis: Clean up Travis scripts 2017-09-11 18:32:23 +02:00
Florian Bruhin
e6864b6599 travis: Run eslint without tox on Travis 2017-09-11 18:32:23 +02:00
Florian Bruhin
1491f20201 Remove geolocation tests
They just cause more trouble than they're worth.
2017-09-11 18:32:23 +02:00
Florian Bruhin
a11baeb84d travis: Fix some more issues 2017-09-11 18:32:23 +02:00
Florian Bruhin
b4f30f6df2 Move coverage to QtWebEngine environment with PyPI-PyQt 2017-09-11 18:30:23 +02:00
Florian Bruhin
49a389542e travis: Update travis_install.sh 2017-09-11 18:30:23 +02:00
Florian Bruhin
eae276b539 travis: Initial .travis.yml update for containers 2017-09-11 18:30:21 +02:00
Florian Bruhin
1d66aacb36 Remove old :wq handler 2017-09-09 11:05:15 +02:00
Florian Bruhin
a283a1bb65 Merge branch 'master' into new-config 2017-09-09 10:52:02 +02:00
Florian Bruhin
2117824cf9 Merge pull request #2914 from rcorre/configmerge
Merge master into new-config
2017-09-09 10:52:17 +02:00
Ryan Roden-Corrent
a8b0a42791 Remove extra blank line from utilcmds 2017-09-08 08:00:29 -04:00
Florian Bruhin
8fce08a927 Merge pull request #2950 from instinctive/patch-1
Use python3-qt5-webengine for Fedora
2017-09-08 11:16:00 +02:00
instinctive
adb552ee6e Use python3-qt5-webengine for Fedora
This was the incantation that worked for me on Fedora 26.
2017-09-07 14:29:45 -07:00
Ryan Roden-Corrent
deb6cccff9 Fix merge resolution in messageview.
Remove a line that was acidentally re-added while merging master into
new-config.
2017-09-07 12:08:26 -04:00
Ryan Roden-Corrent
a6d14ad7dc Fix two new-config/master merge resolutions.
Remove icon from jinja.render call (removed in master).
Add 'When the unwritable dir is unwritable' to download feature file.
2017-09-07 08:58:55 -04:00
Ryan Roden-Corrent
607c64742c Fix configmodel nitpicks 2017-09-07 08:56:11 -04:00
Ryan Roden-Corrent
f0509d1c26 Fix web_history_max_items default value.
Should default to -1, not 1000 as the new history completion is better
able to handle large numbers of entries. I believe this was acidentally
reset to 1000 while fixing a merge conflict.

Also re-run src2asciidoc.
2017-09-07 08:45:05 -04:00
Ryan Roden-Corrent
6e0f65c063 Remove duplicate line from pytest.ini. 2017-09-07 07:34:26 -04:00
Ryan Roden-Corrent
aec736439c Restore history cache stats.
Acidentally removed in merge.
2017-09-07 07:32:51 -04:00
Ryan Roden-Corrent
63e0574411 Remove stray FIXME:conf 2017-09-07 07:32:46 -04:00
Florian Bruhin
7f30fe377c Update CONTRIBUTING for new completion 2017-09-07 13:01:21 +02:00
Ryan Roden-Corrent
a5ecb75fcd Really avoid flakiness in test_models.
Ensure the OrderedDict is actually ordered consistently.
2017-09-05 07:52:42 -04:00
Ryan Roden-Corrent
3726502017 Fix bad merge from master to newconfig. 2017-09-05 07:44:36 -04:00
Ryan Roden-Corrent
fc02216754 Avoid flakiness in test_models.
Ensure config values are ordered consistently by using an OrderedDict.
2017-09-04 16:30:54 -04:00
Ryan Roden-Corrent
0d78c72018 Remove config dependency from get_cmd_completions.
In order to really resolve the python3.4 circular import, this should
take the completion info as an argument and not depend on the config
module.
2017-09-04 15:00:35 -04:00
Ryan Roden-Corrent
3bfa01f0d0 Pass CompletionInfo to completion functions.
In python3.4, there is a circular dependency between the config module
and configmodel.bind. This is resolved by dependency injection. The
config/keyconfig instances are embedded in a struct passed to every
completion function, so the functions no longer depend on the modules.

This will also enable completion functions to access other previously
inaccessible info, such as the window id.
See #2814.
2017-09-04 14:01:48 -04:00
Florian Bruhin
1938520878 eslint: Turn off function-paren-newline 2017-09-04 15:48:33 +02:00
Florian Bruhin
ee147bb327 Merge pull request #2942 from kepi/fix/pfill_visible_input
password_fill: Stop filling username to invisible input fields
2017-09-04 15:34:27 +02:00
Florian Bruhin
2598fd8c5d Add a note about Gentoo and bindist to INSTALL
Closes #2944
2017-09-04 15:03:04 +02:00
Kepi
69ea2cf327 password_fill: Stop filling username to invisible input fields
There is no reason to fill usernames into invisible input fields. We are
probably not leaking anything but it can break some apps (like TTRSS).
2017-09-01 15:48:02 +02:00
Ryan Roden-Corrent
6a292f9d56 Merge quteurls.feature into qutescheme.feature. 2017-08-28 07:18:14 -04:00
Florian Bruhin
79d3c49f26 Merge pull request #2909 from jgkamat/jay/fix-2900
Fix saving a session with --only-active-window
2017-08-28 07:58:25 +02:00
Florian Bruhin
25780eb2bc Merge pull request #2905 from rcorre/urlencode
Consistently format urls in history.
2017-08-28 07:56:45 +02:00
Florian Bruhin
6b795e0093 Merge pull request #2923 from gilbertw1/feature-add-format-json
implemented format_json userscript
2017-08-28 07:41:46 +02:00
Ryan Roden-Corrent
61a03a7808 Add quteurls.feature
Move Scenario: Open qute://version from misc.feature to quteurls.feature
See #2779.
2017-08-27 22:37:04 -04:00
Ryan Roden-Corrent
37ba256900 Ensure web-history-max-items has int64 as maxval.
See #2779.
2017-08-27 22:29:01 -04:00
Ryan Roden-Corrent
d2d55531e6 Remove double-registration of proxy factory.
Due to a bad merge, proxy.init() was called twice.
2017-08-27 22:27:34 -04:00
Bryan Gilbert
536c28a952 implemented format_json userscript 2017-08-27 21:37:58 -04:00
Florian Bruhin
8e92848356 Switch pyup to Mondays 2017-08-24 05:50:33 +02:00
Florian Bruhin
187facd5c7 Merge pull request #2915 from qutebrowser/pyup-scheduled-update-08-21-2017
Scheduled weekly dependency update for week 34
2017-08-24 05:51:37 +02:00
Ryan Roden-Corrent
b89caf0458 Use REPLACE when rebuilding completion table.
When upgrading from an old table that used different url formatting, two
entries might map to the same key, so we'll need to replace the previous
entry to avoid a primary key conflict.
2017-08-23 21:26:27 -04:00
Florian Bruhin
074cc1b723 Another one 2017-08-23 09:37:51 +02:00
Florian Bruhin
df909ca75b Fix sorting for vulture 2017-08-23 08:33:50 +02:00
Florian Bruhin
f1fc078dc1 Remove vulture exclude
Looks like it was removed in
d35e73deda,
and passing [] seems to be equal to the default nowadays anyways.
2017-08-22 08:08:28 +02:00
pyup-bot
8a0b7b9441 Update vulture from 0.24 to 0.25 2017-08-21 16:24:38 +02:00
pyup-bot
7f2e8d8147 Update vulture from 0.24 to 0.25 2017-08-21 16:24:36 +02:00
pyup-bot
6c83016657 Update pytest-rerunfailures from 2.2 to 3.0 2017-08-21 16:24:34 +02:00
pyup-bot
67e3de06c7 Update hypothesis from 3.18.0 to 3.19.1 2017-08-21 16:24:32 +02:00
pyup-bot
86a9487fb2 Update glob2 from 0.5 to 0.6 2017-08-21 16:24:29 +02:00
pyup-bot
dc61e8ecdf Update requests from 2.18.3 to 2.18.4 2017-08-21 16:24:27 +02:00
pyup-bot
8151a73d64 Update requests from 2.18.3 to 2.18.4 2017-08-21 16:24:25 +02:00
pyup-bot
0313982ac8 Update requests from 2.18.3 to 2.18.4 2017-08-21 16:24:23 +02:00
Ryan Roden-Corrent
d35b47c9d8 Regenerate history completion on version change.
Incrementing _USER_VERSION in the source will cause the
HistoryCompletion table to regenerate when users update.

This is currently necessary to support some recent formatting fixes, but
could be incremented again in the future for other changes.
2017-08-21 08:45:40 -04:00
Ryan Roden-Corrent
111846a909 Merge remote-tracking branch 'upstream/master' into configmerge 2017-08-20 21:18:47 -04:00
Ryan Roden-Corrent
722137ab29 Fix 2 end2end tests for config/completion merge. 2017-08-20 21:15:25 -04:00
Ryan Roden-Corrent
b5a6583559 Fix pylint/flake8/vulture errors. 2017-08-20 21:12:38 -04:00
Ryan Roden-Corrent
90c49b3fe7 Move bind completion to configmodels.
When in miscmodels, the config module was unable to find the function.
It appears to be some sort of circular import issue:

```
  File "/home/rcorre/projects/contrib/qutebrowser/qutebrowser/app.py", line 44, in <module>
    from qutebrowser.completion.models import miscmodels
  File "/home/rcorre/projects/contrib/qutebrowser/qutebrowser/completion/models/miscmodels.py", line 24, in <module>
    from qutebrowser.completion.models import completionmodel, listcategory, util
  File "/home/rcorre/projects/contrib/qutebrowser/qutebrowser/completion/models/util.py", line 24, in <module>
    from qutebrowser.config import config
  File "/home/rcorre/projects/contrib/qutebrowser/qutebrowser/config/config.py", line 223, in <module>
    class ConfigCommands:
  File "/home/rcorre/projects/contrib/qutebrowser/qutebrowser/config/config.py", line 314, in ConfigCommands
    @cmdutils.argument('command', completion=miscmodels.bind)
AttributeError: module 'qutebrowser.completion.models.miscmodels' has no attribute 'bind'
```

As configmodel imports util (and thereby config as well) it is unclear
to me why moving bind() to configmodel actually fixes this, but it does.
2017-08-20 21:12:38 -04:00
Ryan Roden-Corrent
0286e9ddf2 Fix completion tests after config merge. 2017-08-20 21:12:38 -04:00
Ryan Roden-Corrent
5f45b9b40e Fix pylint and coverage for history. 2017-08-20 20:59:48 -04:00
Ryan Roden-Corrent
8c6133e29d Regenerate history completion table if needed.
If the HistoryCompletion table is removed, regenerate it from the
History table. This allows users to manually edit History, then remove
HistoryCompletion to prompt regeneration.

See #2903.
2017-08-18 07:39:36 -04:00
Jay Kamat
7073c33dce Test for saving a session with --only-active-window 2017-08-17 22:27:40 -04:00
Ryan Roden-Corrent
c607537319 Consistently format urls in history.
Encode urls that are inserted into the history, but do not encode urls
for completion (other than removing passwords).
Also ensure that urls read from the history text file are formatted
consistenly with those added while browsing.

Fixes #2903.
2017-08-14 21:37:43 -04:00
Florian Bruhin
173688c748 Merge pull request #2904 from qutebrowser/pyup-scheduled-update-08-14-2017
Scheduled weekly dependency update for week 33
2017-08-14 22:11:12 +02:00
pyup-bot
7b1f3e36de Update vulture from 0.22 to 0.24 2017-08-14 16:19:24 +02:00
pyup-bot
bda5ac9bbf Update vulture from 0.22 to 0.24 2017-08-14 16:19:22 +02:00
pyup-bot
1581a68082 Update pytest from 3.2.0 to 3.2.1 2017-08-14 16:19:21 +02:00
pyup-bot
d0d27e7fb1 Update hypothesis from 3.16.1 to 3.18.0 2017-08-14 16:19:20 +02:00
pyup-bot
4f49e58d52 Update cheroot from 5.8.2 to 5.8.3 2017-08-14 16:19:18 +02:00
pyup-bot
29cc8ed272 Update wrapt from 1.10.10 to 1.10.11 2017-08-14 16:19:17 +02:00
pyup-bot
c00d35ea73 Update wrapt from 1.10.10 to 1.10.11 2017-08-14 16:19:16 +02:00
pyup-bot
f5ee01ab6a Update idna from 2.5 to 2.6 2017-08-14 16:19:14 +02:00
pyup-bot
5ebbe80cfe Update idna from 2.5 to 2.6 2017-08-14 16:19:13 +02:00
pyup-bot
843f14042b Update idna from 2.5 to 2.6 2017-08-14 16:19:11 +02:00
cryzed
085d1e9c10 :save-session --only-active-window implies --with-private for private windows 2017-08-14 00:30:45 +02:00
Florian Bruhin
1941071f87 Merge pull request #2901 from lachs0r/master
INSTALL: update openSUSE install instructions
2017-08-13 20:06:36 +02:00
Martin Herkt
dd8b5fc638 INSTALL: update openSUSE install instructions 2017-08-13 19:56:17 +02:00
Florian Bruhin
2957c4e55f Merge pull request #2899 from cryzed/jseval-expand-tilde
Expand ~ to user's home on Linux
2017-08-13 08:53:14 +02:00
cryzed
6ef53c814c Expand ~ to user's home on Linux 2017-08-13 02:34:50 +02:00
Florian Bruhin
ba04822388 Use develop branch of PyInstaller
https://github.com/pyinstaller/pyinstaller/pull/2519 was merged.
Fixes #2880
2017-08-10 17:24:41 +02:00
Ryan Roden-Corrent
5ea420b49b Fix startup crashes after config merge.
Get qutebrowser to the point where it can at least start

- Declare _messages earlier in MessageView.__init__ so it is set before
  the config trigger tries to access it.
- Remove unused configmodel completion functions
- Move bind completion to configmodel to avoid a circular import with
  the config module
- Fix some config accesses (forgot to use .val)
- Fix old Completion.CompletionKind references
2017-08-09 07:28:22 -04:00
Florian Bruhin
3a2d64ba46 version.distribution(): Handle Funtoo 2017-08-08 20:19:33 +02:00
Florian Bruhin
5f4ecd7efc Merge pull request #2892 from qutebrowser/pyup-scheduled-update-08-07-2017
Scheduled weekly dependency update for week 32
2017-08-08 07:59:27 +02:00
Florian Bruhin
a20f017c7a Sort sessions in SessionMnager.list_sessions() 2017-08-08 07:56:10 +02:00
Florian Bruhin
b7a296c81f Merge branch 'tabsort' of https://github.com/rcorre/qutebrowser 2017-08-08 07:53:22 +02:00
Florian Bruhin
81b260998d Ignore a new Geoclue error during tests 2017-08-08 06:25:50 +02:00
pyup-bot
3179599c31 Update vulture from 0.21 to 0.22 2017-08-07 16:16:30 +02:00
pyup-bot
9da802eadf Update vulture from 0.21 to 0.22 2017-08-07 16:16:28 +02:00
pyup-bot
e47e22ba28 Update pytest from 3.1.3 to 3.2.0 2017-08-07 16:16:27 +02:00
pyup-bot
d77ecc8218 Update hypothesis from 3.14.0 to 3.16.1 2017-08-07 16:16:25 +02:00
pyup-bot
af5872bc83 Update cheroot from 5.7.0 to 5.8.2 2017-08-07 16:16:24 +02:00
pyup-bot
fbb2a175ff Update docutils from 0.13.1 to 0.14 2017-08-07 16:16:22 +02:00
pyup-bot
6dbae7fe64 Update setuptools from 36.2.5 to 36.2.7 2017-08-07 16:16:21 +02:00
pyup-bot
111390db0f Update pyflakes from 1.5.0 to 1.6.0 2017-08-07 16:16:19 +02:00
pyup-bot
d288325f64 Update requests from 2.18.2 to 2.18.3 2017-08-07 16:16:18 +02:00
pyup-bot
c0f6588339 Update requests from 2.18.2 to 2.18.3 2017-08-07 16:16:16 +02:00
pyup-bot
e844962645 Update requests from 2.18.2 to 2.18.3 2017-08-07 16:16:15 +02:00
Ryan Roden-Corrent
71b71dbc58 Merge remote-tracking branch 'upstream/master' into HEAD 2017-08-06 18:13:49 -04:00
Ryan Roden-Corrent
6e025c1bb0 Don't perform alphabetical sort in listcategory.
Instead, expect the data to be given in the desired order. Completion
functions should sort their data _if_ they want it sorted in the
completion. This has a few implications:

- {book,quick}marks appear in the same order they do in the text file.
  This means users can rearrange their mark files for custom sorting.
  Fixes #2354
- Sessions are sorted as they appear in the session manager
- Tabs are sorted numerically, not alphabetically (Fixes #2883)

Note that prefix-based filter sorting is still performed, so items
starting with the filter pattern come first.
2017-08-06 10:00:18 -04:00
Florian Bruhin
49b858e359 Add more variants of fake apple URL to ignored ones 2017-08-01 16:00:53 +02:00
Penaz91
6b99ad95d3 Proposed patch for #2858 2017-07-31 21:10:09 +02:00
Penaz
0611dc0cb4 Merge pull request #2 from qutebrowser/master
More Updates
2017-07-31 20:45:12 +02:00
Florian Bruhin
edc0512102 Merge pull request #2878 from qutebrowser/pyup-scheduled-update-07-31-2017
Scheduled weekly dependency update for week 31
2017-07-31 17:48:08 +02:00
Florian Bruhin
a329ce41b5 Update vulture whitelist 2017-07-31 16:41:43 +02:00
Florian Bruhin
bcba14a029 Adjust run_vulture.py for new vulture version 2017-07-31 16:35:12 +02:00
pyup-bot
dd25205623 Update vulture from 0.19 to 0.21 2017-07-31 16:07:25 +02:00
pyup-bot
931d9cc372 Update vulture from 0.19 to 0.21 2017-07-31 16:07:24 +02:00
pyup-bot
240feaf547 Update pytest-benchmark from 3.1.0 to 3.1.1 2017-07-31 16:07:23 +02:00
pyup-bot
e4db036382 Update setuptools from 36.2.1 to 36.2.5 2017-07-31 16:07:21 +02:00
pyup-bot
2e4704aaa7 Update flake8-deprecated from 1.2 to 1.2.1 2017-07-31 16:07:20 +02:00
pyup-bot
92a520fa8c Update requests from 2.18.1 to 2.18.2 2017-07-31 16:07:18 +02:00
pyup-bot
633026e8b3 Update requests from 2.18.1 to 2.18.2 2017-07-31 16:07:17 +02:00
pyup-bot
67f3396ced Update requests from 2.18.1 to 2.18.2 2017-07-31 16:07:15 +02:00
pyup-bot
28c62a7f03 Update certifi from 2017.4.17 to 2017.7.27.1 2017-07-31 16:07:14 +02:00
pyup-bot
26b47bcb6e Update certifi from 2017.4.17 to 2017.7.27.1 2017-07-31 16:07:13 +02:00
pyup-bot
57bf36156b Update certifi from 2017.4.17 to 2017.7.27.1 2017-07-31 16:07:11 +02:00
Florian Bruhin
695769d1b4 Merge pull request #2875 from rcorre/obsolete-signals
Remove obsolete signals.
2017-07-29 20:30:25 +02:00
Florian Bruhin
ba92ea9fb4 Merge pull request #2873 from rcorre/completion-del-marks
Support delete from :{quick,book}mark-load.
2017-07-29 19:27:25 +02:00
Ryan Roden-Corrent
8e34b54cd7 Remove obsolete signals.
The added/removed signals for the urlmark managers are no longer used as
the completion models are generated on-the-fly. The changed signal is
still needed so the save-manager knows when to trigger a write to disk.

Also removes session_manager.update_completion, which is no longer
needed for the same reason as above.

keyconf.changed cannot be removed, as it is still wired up to
basekeyparser.

Resolves #2874.
2017-07-29 13:09:10 -04:00
Ryan Roden-Corrent
1ab7bb83cc Support delete from :{quick,book}mark-load.
Pressing ctrl-d in the completion menu for
:quickmark-load/:bookmark-load  will now delete the selected
quickmark/bookmark.

Resolves #2840.
2017-07-29 12:49:20 -04:00
Florian Bruhin
cee82a3c7b Merge pull request #2871 from rcorre/fix-fetch-delete
Fix fetch/delete sql category bug.
2017-07-28 16:17:11 +02:00
Ryan Roden-Corrent
c6cb6ccd07 Fix fetch/delete sql category bug.
Fixes #2868, where pressing <shift-tab> then <ctrl-d> in history
completion (with > 256 items) would cause later items to disappear (and
cause a crash if you try to delete again).

Cause:
Scrolling to the bottom would fetch an additional 256 items (in addition
to the 256 that are fetched at first). Deleting causes the query to
re-run, but it only fetches the initial 256 items, so the current index
is now invalid.

Fix:
After deleting from the history category, call fetchMore until it has
enough rows populated that the current index is valid.
2017-07-28 09:07:30 -04:00
Florian Bruhin
8f63bb1edc Merge pull request #2853 from rcorre/fix-completionview
Expand history completion results if on last index.
2017-07-27 12:31:01 +02:00
Florian Bruhin
2b07b3db2b Update 'not code' label in CONTRIBUTING 2017-07-27 12:18:59 +02:00
Florian Bruhin
629f6a6876 Remove unused import 2017-07-27 09:56:34 +02:00
Florian Bruhin
e4f776448e Fix typo 2017-07-27 09:25:33 +02:00
Florian Bruhin
a942613d7f Use ctypes instead of PyOpenGL for QtWebEngine Nvidia workaround
Fixes #2821
2017-07-27 09:22:12 +02:00
Ryan Roden-Corrent
32fa1ff1e9 Expand history completion results if on last index.
When tabbing to the last index of history completion, call expandAll
which will call fetchMore to retrieve more query results, if available.

Calling fetchMore directly will not update the view, and for some
reason self.expand(idx.parent()) and
self.expand(self.model().index(idx.row(), 0)) did not work, so I'm using
expandAll.

Fixes #2841.
2017-07-26 07:46:12 -04:00
Florian Bruhin
210bc0fd6b Merge pull request #2861 from rcorre/bind-completion-fix
Fix bind completion for bindings with arguments.
2017-07-26 07:40:08 +02:00
Ryan Roden-Corrent
1929883485 Fix bind completion for bindings with arguments.
When a key is bound to a command line that includes one or more
arguments to a command, bind completion should show the whole command
for the "Current" category, and use only the command name to look up the
description.

Fixes #2859, where a crash was caused by looking up the description by
the full command text rather than just the name.
2017-07-25 12:55:44 -04:00
Florian Bruhin
79e7eb6495 pytest: Show Median instead of Mean for benchmarks 2017-07-25 17:37:18 +02:00
Florian Bruhin
5ecda25fdb Fix renderer process test for older Qt versions 2017-07-25 17:35:42 +02:00
Florian Bruhin
792a01ba6d Try to stabilize renderer process test 2017-07-25 16:56:38 +02:00
Florian Bruhin
3de0b15073 Delay showing the "renderer process killed" error page a bit
Sometimes, we get another error with "Renderer process was killed" and the data:
URL for the error page. This is probably because the renderer process wasn't
restarted yet. This hopefully helps.
2017-07-25 16:00:52 +02:00
Florian Bruhin
79c088d3a4 pytest.ini: Add benchmark-columns 2017-07-24 16:52:36 +02:00
Florian Bruhin
cb2dbc1e0a Merge pull request #2857 from qutebrowser/pyup-scheduled-update-07-24-2017
Scheduled weekly dependency update for week 30
2017-07-24 16:52:43 +02:00
pyup-bot
05dba38190 Update vulture from 0.16 to 0.19 2017-07-24 16:04:24 +02:00
pyup-bot
c4d7cc79b5 Update vulture from 0.16 to 0.19 2017-07-24 16:04:22 +02:00
pyup-bot
38664f9a0a Update pytest-mock from 1.6.0 to 1.6.2 2017-07-24 16:04:21 +02:00
pyup-bot
734acd628e Update pytest-benchmark from 3.0.0 to 3.1.0 2017-07-24 16:04:20 +02:00
pyup-bot
b70f56e87f Update hypothesis from 3.13.0 to 3.14.0 2017-07-24 16:04:18 +02:00
pyup-bot
f8312e9502 Update decorator from 4.1.1 to 4.1.2 2017-07-24 16:04:17 +02:00
pyup-bot
96ed6668e5 Update setuptools from 36.2.0 to 36.2.1 2017-07-24 16:04:15 +02:00
pyup-bot
c49e5f84d9 Update urllib3 from 1.21.1 to 1.22 2017-07-24 16:04:14 +02:00
pyup-bot
920fae02c1 Update urllib3 from 1.21.1 to 1.22 2017-07-24 16:04:13 +02:00
pyup-bot
c1b8830831 Update urllib3 from 1.21.1 to 1.22 2017-07-24 16:04:11 +02:00
Florian Bruhin
137eec8745 Merge pull request #2856 from rcorre/completion-fixes
Abort resizeEvent if model is None.
2017-07-24 15:05:14 +02:00
Ryan Roden-Corrent
f09423efe5 Abort resizeEvent if model is None.
Some reports came in that a resizeEvent was causing a crash due to the
model being none in the CompletionView.

Fixes #2854.
2017-07-24 08:16:14 -04:00
Florian Bruhin
b7fe13434b Merge pull request #2855 from Penaz91/master
Troubleshooting for GCC 6 QtWebEngine Render Crash
2017-07-24 11:09:38 +02:00
Penaz
99559b24e3 Update FAQ.asciidoc 2017-07-24 10:58:45 +02:00
Penaz
cd27363126 Merge pull request #1 from qutebrowser/master
Update Fork
2017-07-24 10:39:08 +02:00
Florian Bruhin
07b2fde2de Mark test_version as flaky
Sometimes it fails on Travis with empty output for no apparent reason
2017-07-24 08:05:51 +02:00
Florian Bruhin
df3ba278e9 Merge pull request #2852 from rcorre/fix-max-items
Fix web-history-max-items-crash.
2017-07-24 07:29:15 +02:00
Florian Bruhin
837ee5c626 Merge pull request #2846 from rcorre/completion-fixes
Completion fixes
2017-07-24 07:27:11 +02:00
Ryan Roden-Corrent
2ad4cdd729 Fix web-history-max-items-crash.
Fixes #2849, where pressing 'o' with web-history-max-items set and no
history items would cause a crash as the query result is empty.
2017-07-23 21:17:22 -04:00
Ryan Roden-Corrent
ff9efe22ae Fix unused imports and removeRow override.
Override removeRows instead of removeRow.

> removeRow is not virtual in C++, so if this gets called by Qt
> internally for some reason, it wouldn't use the overloaded version -
> so I think it'd be better to implement removeRows and then use
> removeRow without overloading that

- The-Compiler
2017-07-23 17:30:09 -04:00
Florian Bruhin
630e9ebd66 Remove old notes file 2017-07-23 23:15:41 +02:00
Florian Bruhin
e402e37f12 Work around segfault when using pdb 2017-07-23 22:45:13 +02:00
Florian Bruhin
56b4989f44 Fix tests for QProcess changes 2017-07-23 22:10:50 +02:00
Florian Bruhin
7d10e47046 Update changelog 2017-07-23 21:38:10 +02:00
Florian Bruhin
a08fd0fcb1 Fix error message with :spawn -d 2017-07-23 21:38:10 +02:00
Florian Bruhin
353f86488a Disallow :spawn -u -d 2017-07-23 21:38:10 +02:00
Ryan Roden-Corrent
00be9e3c7f Remove obsolete TODO.
New aliases will now show up without a signal, as completions are
generated on-demand.
2017-07-22 18:09:10 -04:00
Ryan Roden-Corrent
b61691684e Clear selection when setting completion pattern.
It doesn't make sense to have an active selection while you are
filtering by entering text. You should be in one of two states:

1. Tabbing through completions (valid selection)
2. Entering a filter pattern (invalid selection)

Fixes #2843, where a crash would occur after the following:

1. tab to an item other than the first
2. <backspace>
3. re-type last character
4. <ctrl-d>

This would try to delete an out of range index.
2017-07-22 18:06:16 -04:00
Ryan Roden-Corrent
bc21904fef Fix completion-item-del on undeletable item.
Even though no item was deleted, it was manipulating the completion
model because beginRemoveRows was called before the exception was
raised.

This fixes that problem by moving the removal logic (and delete_func
check) into the parent model, so it can check whether deletion is
possible before calling beginRemoveRows.

Fixes #2839.
2017-07-22 17:16:35 -04:00
Florian Bruhin
a00548ec4d Merge pull request #2827 from jgkamat/jay/fix-small-crash
Enforce a minimum size for non-pinned tabs
2017-07-22 22:07:31 +02:00
Jay Kamat
27dfc72012 Restructure minimum tab size behavior 2017-07-22 10:55:08 -07:00
Florian Bruhin
e943f0063e Merge pull request #2834 from kchr/bugfix/use-breadability-module-when-available
Add support for breadability module in readability userscript
2017-07-22 18:28:49 +02:00
Florian Bruhin
f9dc31e464 Add subreddit to README 2017-07-22 10:22:57 +02:00
Florian Bruhin
6873991e2b Merge pull request #2837 from qutebrowser/zeromax
Fix new completion with web-history-max-items set to 0
2017-07-21 22:19:57 +02:00
Florian Bruhin
118a7942a5 Add maximum bound for web-history-max-items
sqlite can't handle values bigger than uint64_t for LIMIT.
2017-07-21 18:30:12 +02:00
Florian Bruhin
544094ba72 Use simpler way of preventing History completion 2017-07-21 17:55:47 +02:00
Florian Bruhin
6660297871 Fix new completion with web-history-max-items set to 0
We get no last_atime limit at all otherwise:

qutebrowser.misc.sql.SqlException: Failed to prepare query "SELECT url, title,
strftime('%Y-%m-%d', last_atime, 'unixepoch', 'localtime') FROM
CompletionHistory WHERE (url LIKE :pat escape '\' or title LIKE :pat escape '\')
AND last_atime >= ORDER BY last_atime DESC": "near "ORDER": syntax error Unable
to execute statement"
2017-07-21 17:11:38 +02:00
Florian Bruhin
de0b50eaf7 Update docs 2017-07-21 15:39:36 +02:00
Florian Bruhin
5bea9c7794 Some more doc improvements 2017-07-21 15:16:54 +02:00
Florian Bruhin
fba25338be Merge pull request #2295 from rcorre/really_complete
Completion refactor V3
2017-07-21 15:05:43 +02:00
Ryan Roden-Corrent
33a9c8cce6 Add listcategory to perfect_files. 2017-07-21 07:59:47 -04:00
Florian Bruhin
f1d4f693bb Whoops - hopefully final README fix 2017-07-21 13:40:04 +02:00
Florian Bruhin
03a0bfdddd Some more README improvements 2017-07-21 13:36:17 +02:00
Florian Bruhin
7e36310e8a Shorten and update README 2017-07-21 13:28:23 +02:00
Ryan Roden-Corrent
1175543ce1 Fix qutescheme timestamp error.
A date object doesn't have a timestamp property. Go back to using
mktime.
2017-07-20 22:07:37 -04:00
Noor Christensen
a4e644c285 Add support for breadability module in readability userscript 2017-07-20 16:21:47 +02:00
Ryan Roden-Corrent
0eb347186c Add 'localtime' to sql history query.
We need to tell sqlite to convert the timestamps to localtime during
formatting, otherwise it formats them as though you are in UTC.

Also fix up a few uses of mktime.
2017-07-20 09:06:29 -04:00
Florian Bruhin
57167a5cde Merge pull request #2831 from kchr/docs/readability-userscript-dependencies
Clarify dependecies for readability userscript
2017-07-20 14:50:18 +02:00
Noor Christensen
5939bc990a Clarify dependecies for readability userscript 2017-07-20 14:36:27 +02:00
Jay Kamat
8dbb61e9e3 Enforce a minimum size for non-pinned tabs
Closes #2826
2017-07-19 21:37:48 -07:00
Florian Bruhin
fafa063bcd Remove unused import 2017-07-19 12:55:51 +02:00
Florian Bruhin
a3834d043b pytest: Set testpaths 2017-07-19 12:22:30 +02:00
Florian Bruhin
a26fc89f49 Simplify setting the size for background tabs
We can simply look at the size of the existing open tab.
2017-07-19 11:59:44 +02:00
Florian Bruhin
0f85898137 Add a config version to the YAML file 2017-07-19 08:22:00 +02:00
Florian Bruhin
3756d9d76b Merge pull request #2820 from qutebrowser/pyup-scheduled-update-07-17-2017
Scheduled weekly dependency update for week 29
2017-07-17 18:18:14 +02:00
pyup-bot
4d356e5320 Update vulture from 0.15 to 0.16 2017-07-17 16:02:22 +02:00
pyup-bot
19d8411c15 Update vulture from 0.15 to 0.16 2017-07-17 16:02:21 +02:00
pyup-bot
d9f0e21ea4 Update pytest-qt from 2.1.0 to 2.1.2 2017-07-17 16:02:20 +02:00
pyup-bot
a976e9011d Update mako from 1.0.6 to 1.0.7 2017-07-17 16:02:18 +02:00
pyup-bot
72de0fcfcb Update hypothesis from 3.12.0 to 3.13.0 2017-07-17 16:02:17 +02:00
pyup-bot
db2f60b0ef Update decorator from 4.0.11 to 4.1.1 2017-07-17 16:02:16 +02:00
pyup-bot
bdfea0fa6f Update setuptools from 36.0.1 to 36.2.0 2017-07-17 16:02:14 +02:00
Florian Bruhin
4a7fe25f66 Only clear search with :search if one is displayed
For some reason, calling search.clear() while no search is displayed causes the
backends to un-focus inputs, and with QtWebKit, even hinting can't focus them
again after that.
2017-07-17 15:00:18 +02:00
Ryan Roden-Corrent
f45acaa9c8 Fix coverage check for sqlcategory rename. 2017-07-17 08:37:24 -04:00
Ryan Roden-Corrent
c32d452786 Add LIMIT to history query.
For performance, re-introduce web-history-max-items.
As the history query has now become a very specific multi-part query and
history completion was the only consumer of SqlCategory, SqlCategory is
now replaced by a HistoryCategory class.
2017-07-16 18:13:51 -04:00
Florian Bruhin
ee1707c4d4 Update back/forward indicator on tab switches 2017-07-16 20:20:33 +02:00
Florian Bruhin
cbf9da0b7e Set window.navigator.languages correctly 2017-07-13 21:24:17 +02:00
Florian Bruhin
5c367e7ab2 Fix the "try again" button on error pages
Fixes #2810
2017-07-13 17:26:58 +02:00
Ryan Roden-Corrent
8745f80d90 Fix qute://history SQL bug.
The javascript history page was requesting the new start_time in ms, but
the python code was expecting seconds. This is fixed by removing all the
millisecond translations in the python code and only translating to
milliseconds in the javascript code that formats dates.
2017-07-13 08:54:21 -04:00
Florian Bruhin
9898c1ba4b Update docs 2017-07-13 11:02:26 +02:00
Florian Bruhin
71ee64a974 Merge branch 'jay/prompt-on-click' of https://github.com/jgkamat/qutebrowser 2017-07-13 11:01:04 +02:00
Jay Kamat
7dfca60893 Refactor tab_close_prompt_if_pinned
Now it lives in tabbedbrowser.py as method instead of a static function
2017-07-12 20:18:57 -07:00
Ryan Roden-Corrent
1aed2470e5 SQL code review.
- Fix flake8
- history.clear should also clear completion table
- call _resize_columns in set_model, not set_pattern
- add more unit-testing for the history completion table
2017-07-12 22:14:27 -04:00
Ryan Roden-Corrent
ea459a1eca SQL code review fixes.
- Ignore invalid variable name in flake8 (pylint already checks this and
  we don't want to have to double-ignore)
- Fix and test completion bug with `:set asdf `
- Remove unused import
- Use `assert not func.called` instead of `func.assert_not_called` for
  backwards compatibility
2017-07-12 08:19:31 -04:00
Florian Bruhin
53620ecce4 Fix printing on macOS
Fixes #2798
2017-07-12 07:43:03 +02:00
Florian Bruhin
ba8083c539 Fix issues with new stylesheet cache 2017-07-11 21:59:17 +02:00
Florian Bruhin
9307cf86fa Add a cache for rendered stylesheets
Otherwise, when showing hints a few times, we spend around 8-10s just in jinja
generating stylesheets.
2017-07-11 21:06:53 +02:00
Ryan Roden-Corrent
182d067ff8 SQL code review fixes.
- Fix comment and empty line check in _parse_entry
- connect layoutAboutToBeChanged signal
- assert sort_order is None if sort_by is None
- modify sql init failure message to ask about Qt sqlite support.
2017-07-11 08:07:48 -04:00
Florian Bruhin
3dfa36fad1 Update changelog 2017-07-11 13:00:23 +02:00
Florian Bruhin
c0426d3482 Merge branch 'pr/2808' 2017-07-11 09:27:08 +02:00
Florian Bruhin
6f930be08e Update docs 2017-07-11 09:26:36 +02:00
Florian Bruhin
1e58c87380 Improve test for messageview timeout 2017-07-11 09:25:53 +02:00
Florian Bruhin
882dc75536 Set default count for AbstractHistory.back/.forward
Otherwise, using back/forward mouse buttons will crash.
2017-07-11 08:38:06 +02:00
Florian Bruhin
a91e6c3405 Fix test_adblock on Windows
We can't simply have an absolute filename as URL path there, so we only deal
with paths relative to tmpdir in the URLs now.
2017-07-10 22:22:44 +02:00
Florian Bruhin
f93b92cca8 adblock: Fix getting filename from URL
On Windows, we would end up with /C:/foo as "path".
2017-07-10 21:36:34 +02:00
Florian Bruhin
237362663a Fix test_configfiles.test_init on Windows 2017-07-10 20:37:36 +02:00
Florian Bruhin
ac8fb03b80 Fix lint 2017-07-10 20:37:30 +02:00
Yashar Shahi
7da6908850 Check for interval being positive.
Check for interval being positive instead of checking for it to be
non-zero. So if somehow some unexpected thing happend and made
message-timeout negative, the bug doesn't cascade.
2017-07-10 21:14:55 +04:30
Yashar Shahi
1cb23f1193 Change timer interval after appending to _messages 2017-07-10 21:11:38 +04:30
Florian Bruhin
196f4a67b2 Update docs 2017-07-10 18:34:48 +02:00
Florian Bruhin
1f4012cc1e Merge branch 'master' of https://github.com/iordanisg/qutebrowser 2017-07-10 18:33:46 +02:00
Yashar Shahi
a631c971d9 Add tests for show messages longer
Add tests for "Show messages longer if there are multiple of them."
2017-07-10 20:52:42 +04:30
Florian Bruhin
135fb042da Make settings from qute://settings persistent 2017-07-10 18:04:39 +02:00
Yashar Shahi
9574549798 Merge https://github.com/qutebrowser/qutebrowser 2017-07-10 19:58:03 +04:30
Florian Bruhin
deaa5f363a Merge branch 'pr/2807' 2017-07-10 17:16:42 +02:00
Florian Bruhin
045831f3c7 Fix coverage check 2017-07-10 16:57:26 +02:00
Yashar Shahi
cb0bd2c52d Do not call _set_timer_interval() at constructor
No need to call _set_timer_interval() at constructor since it's called
every time timer is going to be started.
2017-07-10 19:21:35 +04:30
Yashar Shahi
c015e9cc5d Revert "An empty file to trigger travis."
This reverts commit 03c70f0421.
2017-07-10 19:20:32 +04:30
Yashar Shahi
03c70f0421 An empty file to trigger travis. 2017-07-10 18:58:45 +04:30
Florian Bruhin
cf2f81aae1 Remove myself from CODEOWNERS
I watch the repo anyways
2017-07-10 15:59:05 +02:00
Iordanis Grigoriou
9c83ea4717 Refactor _back_forward 2017-07-10 15:58:11 +02:00
pyup-bot
34eddc92ff Update vulture from 0.14 to 0.15 2017-07-10 15:55:18 +02:00
pyup-bot
44270b37b9 Update vulture from 0.14 to 0.15 2017-07-10 15:55:17 +02:00
pyup-bot
57caf80e5d Update pytest from 3.1.2 to 3.1.3 2017-07-10 15:55:15 +02:00
pyup-bot
9da52c5d86 Update hypothesis from 3.11.6 to 3.12.0 2017-07-10 15:55:14 +02:00
pyup-bot
9e6b84e31e Update flake8-tidy-imports from 1.0.6 to 1.1.0 2017-07-10 15:55:12 +02:00
Iordanis Grigoriou
6ab49fdf1d Move back/forward logic to AbstractHistory, fix method names 2017-07-10 15:43:35 +02:00
Yashar Shahi
3c1b05c81e Show messages longer if there are multiple of them 2017-07-10 18:05:35 +04:30
Florian Bruhin
e81dcccace Add a test for a None currentWidget with backforward widget 2017-07-10 09:29:45 +02:00
Florian Bruhin
5fb6cb713b Hide back/forward widget when there's no text 2017-07-10 07:59:56 +02:00
Iordanis Grigoriou
bf074d14de Adjust back/forward method arguments in AbstractHistory class 2017-07-10 01:00:48 +02:00
Iordanis Grigoriou
c6ed4fe4f9 Skip intermediate pages with :back/:forward and a count 2017-07-10 00:28:47 +02:00
Florian Bruhin
0e8175b8eb Update docstrings/docs 2017-07-09 23:27:34 +02:00
Florian Bruhin
bce28fe526 Merge branch 'backforward' of https://github.com/blueyed/qutebrowser into blueyed-backforward 2017-07-09 23:25:36 +02:00
Jay Kamat
28a2482cf7 Merge branch 'master' into jay/prompt-on-click 2017-07-09 14:17:03 -07:00
Florian Bruhin
b3b2f69673 Fix manifest 2017-07-09 23:09:50 +02:00
Daniel Hahler
b3a9e09d6c Add statusline widget for back/forward indicator
Fixes https://github.com/qutebrowser/qutebrowser/issues/2737.
2017-07-09 22:38:44 +02:00
Florian Bruhin
d895ad183d Update authors 2017-07-09 22:12:32 +02:00
Florian Bruhin
7ffe6a2c78 Fix Python/PyQt casing 2017-07-09 22:12:17 +02:00
Florian Bruhin
211a586173 Merge branch 'pr/2805' 2017-07-09 22:11:54 +02:00
Florian Bruhin
bb567a61b6 Fix ipc test coverage 2017-07-09 22:09:31 +02:00
Fritz Reichwald
fd4bc29beb Add some comment 2017-07-09 14:10:08 +02:00
Fritz Reichwald
ead71db41a Add explanation for using open_url_in_instance script 2017-07-09 13:45:16 +02:00
Fritz Reichwald
38c00e53cd Add open_url_in_instance.sh script 2017-07-09 13:34:10 +02:00
Florian Bruhin
6c0ceeac7f Update docs 2017-07-09 12:58:21 +02:00
Florian Bruhin
84c2289aa5 Merge branch 'master' of https://github.com/iordanisg/qutebrowser 2017-07-09 12:56:52 +02:00
Florian Bruhin
cd063c74d9 Why is my commit -a broken 2017-07-09 12:54:19 +02:00
Florian Bruhin
6a2163d36f ipc: Remove support for connecting to legacy servers 2017-07-09 12:49:47 +02:00
Florian Bruhin
cfb169b5f0 Remove unused import 2017-07-09 12:40:16 +02:00
Florian Bruhin
9e7f2e470f Move OpenGL workaround import
OpenGL.GL gets imported in earlyinit already anyways, so we can move everything
there.
2017-07-09 11:57:06 +02:00
Florian Bruhin
915cd5f016 Fix long lines 2017-07-09 11:51:22 +02:00
Ryan Roden-Corrent
cf4ac1a5b7 SQL code review changes.
- use mocker.Mock instead of mock.Mock to avoid an extra import
- attach model to validator sooner so it can validate changes in the
  model during the test
2017-07-08 16:34:38 -04:00
Florian Bruhin
fcf5158258 Recommend QT_XCB_FORCE_SOFTWARE_OPENGL
This won't disable OpenGL for stuff started from qutebrowser.

See #2368.
2017-07-08 17:36:14 +02:00
Florian Bruhin
b81474d2fd Improve earlyinit check for PyOpenGL
Importing OpenGL alone doesn't actually load libgl, it only checks that the
package is here. If libgl is missing, we'd later get an exception.
2017-07-08 17:33:50 +02:00
Iordanis Grigoriou
c9fd182dba Adjust suggested_fn_from_title, add tests 2017-07-08 16:28:58 +02:00
Ryan Roden-Corrent
f9f8900fe9 More sql code review fixes.
- remove outdated comment
- fix sql init error message
- clean up history text import code
- fix test_history file path in coverage check
- use real web history, not stub, for completion model tests
- use qtmodeltester in sql/list_category tests
- test url encoding in history tests
- fix test_clear by using a callable mock
- remove test_debug_dump_history_oserror as the check is now the same as
  for the file not existing
- rename nonempty to data in test_completionmodel
- add more delete_cur_item tests
- test empty option/value completion
2017-07-08 09:57:32 -04:00
Florian Bruhin
ad615941a2 Replace OS X with macOS 2017-07-08 11:12:43 +02:00
Florian Bruhin
0de0bbfa71 Fix :restart with private browsing mode 2017-07-08 10:46:08 +02:00
Ryan Roden-Corrent
515e82262d Merge remote-tracking branch 'upstream/master' into really_complete 2017-07-07 20:42:21 -04:00
Florian Bruhin
a572b0f34d Update docs 2017-07-07 18:40:57 +02:00
Florian Bruhin
f80fd2a27c Merge branch 'pr/2782' 2017-07-07 18:38:29 +02:00
Florian Bruhin
f7dbd3c283 Add initial CODEOWNERS file 2017-07-07 17:58:38 +02:00
Florian Bruhin
215503ba59 Remove now useless suppression 2017-07-07 15:21:18 +02:00
Florian Bruhin
af6d833c50 Fix build_release.py 2017-07-07 15:18:05 +02:00
Florian Bruhin
5098aa388b build_release: Fail GitHub uploads early 2017-07-07 14:28:36 +02:00
Christian Helbling
6d9e5dc931 avoid too long lines 2017-07-07 11:30:18 +02:00
Florian Bruhin
d4da82805f Remove hostblock_blame 2017-07-07 09:44:34 +02:00
Florian Bruhin
6a8d2ac826 Disable search workaround for Qt 5.9.2 2017-07-06 23:18:29 +02:00
Iordanis Grigoriou
82d194cf2e Improve function docstring, add more tests 2017-07-06 21:37:11 +02:00
Iordanis Grigoriou
3bfafb5e50 Refactor suggested_fn_from_title, add unit tests 2017-07-06 17:41:54 +02:00
Christian Helbling
d179450c29 :fullscreen, enter video fullscreen, :fullscreen, exit video fullscreen should not go into video fullscreen 2017-07-06 15:35:52 +02:00
Ryan Roden-Corrent
1dd5f06a4f Fix debug-dump-history behavior.
Ensure the file is closed before printing the success message. This will
hopefully fix the AppVeyor tests.
2017-07-06 08:02:16 -04:00
Ryan Roden-Corrent
cee0aa3adc Show error dialog is sql isn't available.
If creating the sql database fails, show an error dialog assuming sqlite
is not installed.

This removes the isDriverAvailable check as it was true even with sqlite
uninstalled.

sql.version now inits itself if sql is not already initialized and
prints 'UNAVAILABLE (<error message>)' if init fails. This is to avoid
cascading errors, where one error would create a crash dialog, which
calls sql.version, which would create another error.
2017-07-06 07:36:59 -04:00
Florian Bruhin
338d62204e Make TestModuleVersions in test_version more maintainable 2017-07-06 12:36:11 +02:00
Florian Bruhin
66168a5b49 Add test ids to test_version_output 2017-07-06 12:25:11 +02:00
Florian Bruhin
911e59b0f4 Improve version output without SSL support 2017-07-06 12:23:08 +02:00
Florian Bruhin
94951d92a1 Simplify arg handling in test_version_output 2017-07-06 12:15:42 +02:00
Iordanis Grigoriou
57e4d4978b Use page title only for whitelisted extensions 2017-07-06 11:59:02 +02:00
Florian Bruhin
3c9de92d58 Add Gentoo instructions to backend warning 2017-07-06 00:41:06 +02:00
Florian Bruhin
6b4e0ad2bc Update changelog 2017-07-05 22:14:49 +02:00
Florian Bruhin
a4833fcc46 Merge branch 'pr/2747' 2017-07-05 22:14:07 +02:00
Florian Bruhin
0304040cbb Update docs 2017-07-05 22:14:01 +02:00
Florian Bruhin
a8120a23c4 Update comment for TabBarStyle 2017-07-05 22:13:24 +02:00
Florian Bruhin
f15dbecc73 Update changelog for unreleased versions 2017-07-05 21:49:34 +02:00
Ryan Roden-Corrent
dc4472470e Merge remote-tracking branch 'upstream/master' into really_complete 2017-07-05 08:45:57 -04:00
Ryan Roden-Corrent
81f5b7115f Add spec=[] to two mock functions in tests. 2017-07-05 08:44:56 -04:00
Christian Helbling
361251bf53 mark public attribute as public, fix debug output 2017-07-04 23:30:06 +02:00
Christian Helbling
20db65e430 preserve window state when exiting video fullscreen 2017-07-04 22:56:44 +02:00
Florian Bruhin
eaecfe5882 build_release: Adjust Windows installer names 2017-07-04 22:27:17 +02:00
Florian Bruhin
725d4a44f0 build_release: Don't fail if hdiutil detach fails 2017-07-04 22:16:21 +02:00
Florian Bruhin
c424a745d8 build_release: Add comment about missing 3rdparty upgrade 2017-07-04 21:36:20 +02:00
Florian Bruhin
3cbe419cee Update Python version for Windows in release checklist 2017-07-04 21:36:20 +02:00
Florian Bruhin
8f03a36862 build_release: Use correct path when copying dirs 2017-07-04 21:31:53 +02:00
Florian Bruhin
7ecdd6c1c5 build_release: Print some more information about copied files 2017-07-04 21:04:08 +02:00
Florian Bruhin
d96403fe93 build_release: Clean up before doing stuff
So we can inspect the results later.
2017-07-04 21:03:55 +02:00
Florian Bruhin
2df9508e44 Add PyQt5 OpenGL module to PyInstaller hiddenimports 2017-07-04 21:03:34 +02:00
Florian Bruhin
defe140d98 build_release: Run tox with -vv 2017-07-04 19:56:54 +02:00
Florian Bruhin
28410b8533 Release v0.11.0 2017-07-04 18:02:34 +02:00
Florian Bruhin
378914b327 Ignore another new geoclue error during tests 2017-07-04 18:01:24 +02:00
Christian Helbling
7ea7a2f3fd restore maximized state on :fullscreen and when exiting video fullscreen 2017-07-04 17:50:07 +02:00
Florian Bruhin
023bf82638 Update for PyQt 5.9.1 2017-07-04 17:31:09 +02:00
Florian Bruhin
45b1285402 Merge pull request #2765 from jgkamat/jay/tab-crashes
Refactor set_tab_pinned to take a tab widget.
2017-07-04 17:24:10 +02:00
Florian Bruhin
0cdd3ff82f Update some more references to old config options 2017-07-04 16:46:02 +02:00
Florian Bruhin
770c879410 Bring back searchengine BDD tests 2017-07-04 15:39:07 +02:00
Florian Bruhin
cff61fa0bc Fix pylint
This also reverts commit 8df0b063be.
2017-07-04 15:34:10 +02:00
Florian Bruhin
88b878098d Implement pretty-printing of configtypes for the doc
This is also needed to make the docs environment work on Travis - as otherwise,
doc generation wasn't deterministic because of changing dict key order.
2017-07-04 15:09:23 +02:00
Florian Bruhin
f98b8a240e Fix flake8 2017-07-04 15:09:23 +02:00
Florian Bruhin
f92ccd4893 Show diff on Travis in check_doc_changes 2017-07-04 15:09:23 +02:00
Florian Bruhin
397ca47efb Fix vulture 2017-07-04 15:09:23 +02:00
Florian Bruhin
f71e678d80 Ignore a new Geoclue error during tests 2017-07-04 15:09:23 +02:00
Florian Bruhin
acf85eb96b Stabilize qute://settings test 2017-07-04 15:09:23 +02:00
Florian Bruhin
79c11d6008 Skip test_configdata.test_init_benchmark on Travis in Docker
See #2777
2017-07-04 15:09:23 +02:00
Florian Bruhin
65585b313d test_configtypes: Rename test_to_py to _valid for consistency 2017-07-04 15:09:23 +02:00
Florian Bruhin
9ac2dbcc80 Disallow surrogate escapes in dicts and lists in the config
In Dict.to_str() and List.to_str() we use json.dump to get a value. However,
JSON includes surrogate escapes in the dumped values, which breaks round trips.

>>> yaml.load(json.dumps({'\U00010000': True}))
{'\ud800\udc00': True}

>>> yaml.load(json.dumps({'\U00010000': True}, ensure_ascii=False))
yaml.reader.ReaderError: unacceptable character #x10000: special characters are not allowed

See:
https://stackoverflow.com/a/38552626/2085149
https://news.ycombinator.com/item?id=12798032
2017-07-04 15:09:23 +02:00
Florian Bruhin
fa0f4e1101 Improve test_configtypes.TestDict
We didn't have to_py tests there before.
2017-07-04 15:09:23 +02:00
Florian Bruhin
f00e91e85e Don't set valid_values in test_configtypes.TestList
Most of the time we want to check values without them being outright rejected by
ValidValues.
2017-07-04 15:09:23 +02:00
Florian Bruhin
05f4f2e742 Fix TestDict.test_hypothesis_text for unordered dicts 2017-07-04 15:09:23 +02:00
Florian Bruhin
ea2b9f5596 Remove old comment
The recursion is caught in test_config
2017-07-04 15:09:15 +02:00
Florian Bruhin
0528a800f2 Fix config things relying on dict order 2017-07-04 15:08:04 +02:00
Florian Bruhin
8933b4c5da Avoid calling configdata.init() in tests
It takes unnecessary time (20ms without C extensions) to initialize it over and
over again - and for some reason, it takes 20s (!) on Travis.
2017-07-04 15:08:04 +02:00
Florian Bruhin
56ec5719a2 Update docs 2017-07-04 15:08:04 +02:00
Florian Bruhin
91cd6c6288 Fix Python 3.4 circular imports 2017-07-04 15:08:04 +02:00
Florian Bruhin
9db4a8cb43 Clean up test_cache 2017-07-04 15:08:04 +02:00
Florian Bruhin
9dfe4429d7 Import qutebrowser.app in conftest 2017-07-04 15:08:04 +02:00
Florian Bruhin
b42265212b Update test_keyhints for new config
This also makes the keyhint display things sorted
2017-07-04 15:08:04 +02:00
Florian Bruhin
4bebfd8d5f Update test_modeparsers for new config 2017-07-04 15:08:04 +02:00
Florian Bruhin
d5cd0b19b0 Update test_basekeyparser for new config 2017-07-04 15:08:04 +02:00
Florian Bruhin
22b0f2fd24 Various simple test updates for new config
test_cache
test_cookies
test_webkitelem
test_cmdutils
test_runners
test_completionwidget
test_messageview
test_editor
test_miscwidgets
test_sessions
test_urlutils
test_utils
test_prompt
statusbar/test_*
test_cmdhistory
test_tabwidget
test_tab
test_downloads
test_networkmanager
2017-07-04 15:08:04 +02:00
Florian Bruhin
1663280f53 Update test_shared for new config
Also, make accept_language none_ok=True like it was in the old configdata.py
2017-07-04 15:08:04 +02:00
Florian Bruhin
7dd5e4b2e6 Skip broken completion tests
This skips test_completer and test_models - we'll reintroduce them when merging
the new completion.
2017-07-04 15:08:04 +02:00
Florian Bruhin
ff05560047 Update test_adblock for new config
This required some changes on how URLs are handled during those tests. Before,
we simply could return a path and (since we had a patched QNAM), nobody
complained.

Now this actually needs to be a valid URL, so we use
https://www.example.com/path everywhere instead.
2017-07-04 15:08:04 +02:00
Florian Bruhin
78d7ac311f Use fonts.monospace properly 2017-07-04 15:08:04 +02:00
Florian Bruhin
4562a3574b Allow a list for content.user_stylesheets 2017-07-04 15:08:04 +02:00
Florian Bruhin
afb3b496e8 Add missing backend: QtWebKit for content.pdfjs 2017-07-04 15:08:04 +02:00
Florian Bruhin
a36f5bafc1 Rename content.javascript.can_*_windows to _tabs 2017-07-04 15:08:04 +02:00
Florian Bruhin
be94098597 Improve more docs 2017-07-04 15:08:04 +02:00
Florian Bruhin
5ada3606d8 Allow to not send the DNT header 2017-07-04 15:08:04 +02:00
Florian Bruhin
040be60697 Improve more docs 2017-07-04 15:08:04 +02:00
Florian Bruhin
202b8445f6 Move content.accept_language under headers 2017-07-04 15:08:04 +02:00
Florian Bruhin
f546cbe934 Clarify some docs 2017-07-04 15:08:04 +02:00
Florian Bruhin
d7036fe8a8 Clarify history_session_interval and rename it to _gap_interval
"session" is already overloaded enough.
2017-07-04 15:08:04 +02:00
Florian Bruhin
8712fc6fd3 Move new_instance_open_target out of url.
It doesn't really fit there really...
See 3cf028db23cbfe256e499d8881c3c2856f224d94
2017-07-04 15:08:04 +02:00
Florian Bruhin
d641652a92 More test_config improvements 2017-07-04 15:08:04 +02:00
Florian Bruhin
c214acd899 Remove config from objreg 2017-07-04 15:08:04 +02:00
Florian Bruhin
f8a88ae042 Clean up objreg properly in config tests 2017-07-04 15:08:04 +02:00
Florian Bruhin
54adf3898a Add test_configfiles.py 2017-07-04 15:08:04 +02:00
Florian Bruhin
e72b0fc89d Update check_coverage.py for new config 2017-07-04 15:08:04 +02:00
Florian Bruhin
1a492e9f4a Re-add backend checks to new config 2017-07-04 15:08:04 +02:00
Florian Bruhin
556f49d367 Add PACFetcher.fetch
Let's not try to download proxies during tests...
2017-07-04 15:08:04 +02:00
Florian Bruhin
215fd2f055 More test_config fixes/tests 2017-07-04 15:08:04 +02:00
Florian Bruhin
009ed3584d Reorder tests 2017-07-04 15:08:04 +02:00
Florian Bruhin
2b9b54cf6b Tests and improvements for ConfigContainer 2017-07-04 15:08:03 +02:00
Florian Bruhin
4495e721d8 Tests and fixes for config.Config 2017-07-04 15:08:03 +02:00
Florian Bruhin
e259293f83 Always copy config objects
If we mutate the value we get from the config, we want to make sure the value in
the config always stays the same (especially when it's the default!).
2017-07-04 15:08:03 +02:00
Florian Bruhin
2c3981e57e Get rid of Config.read_configdata()
No need for this indirection
2017-07-04 15:08:03 +02:00
Florian Bruhin
252c5396f3 Apply proxy changes from master
This are the same changes as done in 629038632c,
but only the part related to the config. This is so we don't forget this when
merging them.
2017-07-04 15:08:03 +02:00
Florian Bruhin
07d0ea6a54 Unit tests and improvements for :bind/:unbind 2017-07-04 15:08:03 +02:00
Florian Bruhin
353c10aee7 Add a separate qutescheme BDD file 2017-07-04 15:08:03 +02:00
Florian Bruhin
3edebce833 Add tests for :set 2017-07-04 15:08:03 +02:00
Florian Bruhin
31b999ea59 Tests and improvements for KeyConfig 2017-07-04 15:08:03 +02:00
Florian Bruhin
725ffef5f3 Use a real config object in unit tests 2017-07-04 15:08:03 +02:00
Florian Bruhin
5aac991446 Remove unnecessary sip.isdeleted line
Now that the StyleSheetObserver is a child of the object it observes, it should
get cleaned up properly when the object is deleted.

This means this is hopefully not needed anymore, even on Qt 5.2.
2017-07-04 15:08:03 +02:00
Florian Bruhin
978013e750 Fix CommandParser and don't use a generator 2017-07-04 15:08:03 +02:00
Florian Bruhin
a8c7e8ba05 Add first config tests 2017-07-04 15:08:03 +02:00
Florian Bruhin
28670f8e48 Move config.style into config.config and refactor it 2017-07-04 15:08:03 +02:00
Florian Bruhin
81d6406e14 Update test_stylesheet 2017-07-04 15:08:03 +02:00
Florian Bruhin
a5c8a52dd5 Update config_stub for tests 2017-07-04 15:08:03 +02:00
Florian Bruhin
0dc95aceed Clean up old test_config.py 2017-07-04 15:08:03 +02:00
Florian Bruhin
a2f62238f1 Change default binding to leave passthrough mode to Ctrl-V
Also, display the binding in the statusbar
2017-07-04 15:08:03 +02:00
Florian Bruhin
df1685905e Add content.headers and content.cache groups 2017-07-04 15:08:03 +02:00
Florian Bruhin
50602cbf26 Add an url. group to settings 2017-07-04 15:08:03 +02:00
Florian Bruhin
5c08c6c930 Add conditional backend infos to docs 2017-07-04 15:08:03 +02:00
Florian Bruhin
034d727a2c Clean up configdata 2017-07-04 15:08:03 +02:00
Florian Bruhin
25ab3b30c2 Initial doc update with new settings 2017-07-04 15:08:03 +02:00
Florian Bruhin
94ac2ca56c Merge :wq into :quit and add an alias 2017-07-04 15:08:03 +02:00
Florian Bruhin
065f82f485 Fix endless recursion while validating aliases 2017-07-04 15:08:03 +02:00
Florian Bruhin
ac78039171 Use aliases for :w and :q 2017-07-04 15:08:03 +02:00
Florian Bruhin
ac64ea287a Rename tabs.new_position/_explicit to .related/.unrelated 2017-07-04 15:08:03 +02:00
Florian Bruhin
441b3a4df4 Allow missing fixed_keys for configtypes.Dict
We just fill them up with a None value for the value type, so we can e.g. only
specify a subset of modes for bindings and the rest is {}.
2017-07-04 15:08:03 +02:00
Florian Bruhin
9d8b76e497 Simplify _none_value for List/Dict configtypes
We don't need to check for fixed_keys/required_keys in get_obj (only get_py),
and we don't need to care about mutability in get_py.
2017-07-04 15:08:03 +02:00
Florian Bruhin
da0a2b8578 Handle {} and [] with none_ok for configtypes.Dict/List 2017-07-04 15:08:03 +02:00
Florian Bruhin
2ba637891a Add required_keys for configtypes.Dict 2017-07-04 15:08:03 +02:00
Florian Bruhin
bc526cf0ce Remove some FIXMEs 2017-07-04 15:08:03 +02:00
Florian Bruhin
7ee222af88 Return [] for none-values for configtypes.List 2017-07-04 15:08:03 +02:00
Florian Bruhin
c141c33b32 Clean up start_pages setting
The value is now of type FuzzyUrl, and the setting is renamed to start_pages.
2017-07-04 15:08:03 +02:00
Florian Bruhin
9cbacf3264 Use {} for none-dicts and fix keybindings 2017-07-04 15:08:03 +02:00
Florian Bruhin
0115285a84 Initial update for better bindings management 2017-07-04 15:08:03 +02:00
Florian Bruhin
127db2fe42 Be a bit more relaxed about values for Perc
We now allow float/int for objects, and strings without a trailing % sign.
2017-07-04 15:08:03 +02:00
Florian Bruhin
cbf6e4287f Rename fonts.tabbar to fonts.tabs 2017-07-04 15:08:03 +02:00
Florian Bruhin
e7ba56cb2c Read YAML config after config.val is ready
This means we can (at least somewhat) validate aliases in configtypes.Command.
2017-07-04 15:08:03 +02:00
Florian Bruhin
0ed0a6db57 Clean up code 2017-07-04 15:08:03 +02:00
Florian Bruhin
67cb6a9802 Implement initial reading from YAML 2017-07-04 15:08:03 +02:00
Florian Bruhin
70f6d0e305 Add qutebrowser.config.configfiles 2017-07-04 15:08:03 +02:00
Florian Bruhin
78434a330c Remove old stub FIXMEs 2017-07-04 15:08:03 +02:00
Florian Bruhin
fda4fd4888 Rename NewConfigManager.set to set_obj 2017-07-04 15:08:03 +02:00
Florian Bruhin
ad0a961a5f Add an lru_cache for configdata.is_valid_prefix()
This gets called a lot, and caused some :bind calls to take ~3s.

Stats after starting with a bit of :bind:
CacheInfo(hits=25917, misses=139, maxsize=256, currsize=139)
2017-07-04 15:08:03 +02:00
Florian Bruhin
45e7e35233 Detect mutated values in new config
This will allow config.py to get a value and then mutate it, and we can also
make things easier for :bind and :unbind.
2017-07-04 15:08:03 +02:00
Florian Bruhin
9bd438618a Add a test for DuplicateKeyError 2017-07-04 15:08:03 +02:00
Florian Bruhin
2a40401398 Fix config tests for new Command type 2017-07-04 15:08:03 +02:00
Florian Bruhin
2577b2c5e3 Validate configtypes.Command correctly 2017-07-04 15:08:03 +02:00
Florian Bruhin
ad919fc972 Add a test for :bind with a wrong mode 2017-07-04 15:08:03 +02:00
Florian Bruhin
23d30d4fc0 Fix remaining :bind/:unbind issues 2017-07-04 15:08:03 +02:00
Florian Bruhin
f434f955c2 Improve exception handling for :bind/:unbind 2017-07-04 15:08:02 +02:00
Florian Bruhin
ba1bc29a97 Initial :bind/:unbind implementation 2017-07-04 15:08:02 +02:00
Florian Bruhin
290d27a064 Add a cmdexc.Error 2017-07-04 15:08:02 +02:00
Florian Bruhin
a6c629899e Split CommandRunner into runner/parser 2017-07-04 15:08:02 +02:00
Florian Bruhin
d4cbd4ace4 Fix getting the scrollbar option 2017-07-04 15:08:02 +02:00
Florian Bruhin
d9f1c4595e Make "the option ... should be set to ..." unambiguous
Otherwise, it'd collide with the cookie check.
2017-07-04 15:08:02 +02:00
Florian Bruhin
ed5bea6e3f Call int() for zoom level messages 2017-07-04 15:08:02 +02:00
Florian Bruhin
3c2d568a2e Add an ID for qute://settings inputs 2017-07-04 15:08:02 +02:00
Florian Bruhin
d7f1ebedbf Fix toggling options 2017-07-04 15:08:02 +02:00
Florian Bruhin
44e4816cbb Use get_opt in NewConfigManager.set 2017-07-04 15:08:02 +02:00
Florian Bruhin
5081e4f201 Fix NewConfigManager.get_str 2017-07-04 15:08:02 +02:00
Florian Bruhin
5e4675b34a Fix ignore_case handling 2017-07-04 15:08:02 +02:00
Florian Bruhin
340a62869d Fix javascript.prompt default 2017-07-04 15:08:02 +02:00
Florian Bruhin
ceca99a99c Fix :help with new config 2017-07-04 15:08:02 +02:00
Florian Bruhin
e752f87876 Add Shift-Delete mapping for :completion-item-del
This seems to be what Chromium and Firefox use for the same purpose.
2017-07-04 15:08:02 +02:00
Florian Bruhin
75798bebb0 Normalize bindings correctly when checking key_mappings 2017-07-04 15:08:02 +02:00
Florian Bruhin
383968d948 Add a Key config type
Make sure any key we get from the config is normalized).
2017-07-04 15:08:02 +02:00
Florian Bruhin
0d062b28bf Comment out failing test 2017-07-04 15:08:02 +02:00
Florian Bruhin
e894ad4ab0 Improve :set --temp docs 2017-07-04 15:08:02 +02:00
Florian Bruhin
6aafaca329 Fix invalid default_page replacement 2017-07-04 15:08:02 +02:00
Florian Bruhin
ae6cc543ed Fix shared.feature_permission 2017-07-04 15:08:02 +02:00
Florian Bruhin
bd9b45bb96 tests: Fix more issues with new config 2017-07-04 15:08:02 +02:00
Florian Bruhin
089e1ee91b Rewrite various references to old settings 2017-07-04 15:08:02 +02:00
Florian Bruhin
88fb5bbd82 tests: Fix various issues with new config 2017-07-04 15:08:02 +02:00
Florian Bruhin
ab1b80967f Disable tests which won't work yet
They are re-enabled in later commits.
2017-07-04 15:08:02 +02:00
Florian Bruhin
198040b2e2 Fix setting descriptions 2017-07-04 15:08:02 +02:00
Florian Bruhin
f27978e268 Rename input.insert_mode.auto_focused to _load 2017-07-04 15:08:02 +02:00
Florian Bruhin
3470e9bf5d Fix invocation with -s 2017-07-04 15:08:02 +02:00
Florian Bruhin
471755d370 Fix old config access in hints 2017-07-04 15:08:02 +02:00
Florian Bruhin
3aa7f771c1 Fix dirbrowser.html for stricter jinja env 2017-07-04 15:08:02 +02:00
Florian Bruhin
d0904a9f67 Adjust test settings 2017-07-04 15:08:02 +02:00
Florian Bruhin
c2a2845ee7 Remove the tabs.movable setting 2017-07-04 15:08:02 +02:00
Florian Bruhin
85bee4a7d2 Rename completion background settings to .odd/.even 2017-07-04 15:08:02 +02:00
Florian Bruhin
bc8176ff21 Remove most legacy config code 2017-07-04 15:08:02 +02:00
Florian Bruhin
785de9fb99 Add dump_userconfig 2017-07-04 15:08:02 +02:00
Florian Bruhin
b5eac744b5 Remove old caching code
Not deleting debug_cache_stats as we'll soon re-add stuff there.
2017-07-04 15:08:02 +02:00
Florian Bruhin
46d0fee11b Bring back :set 2017-07-04 15:08:02 +02:00
Florian Bruhin
30f1970850 Fix key-config usage 2017-07-04 15:08:02 +02:00
Florian Bruhin
aa75262fe4 Fix keyhintwidget 2017-07-04 15:08:02 +02:00
Florian Bruhin
22f096088b Fix alias handling 2017-07-04 15:08:02 +02:00
Florian Bruhin
f5d2c48bbb Fix new keyconfig issues 2017-07-04 15:08:02 +02:00
Florian Bruhin
056edcfed3 More keyconfig work 2017-07-04 15:08:02 +02:00
Florian Bruhin
67afc06d79 Initial work on new keyconfig 2017-07-04 15:08:02 +02:00
Florian Bruhin
e4278a69ac Re-activate aliases 2017-07-04 15:08:02 +02:00
Florian Bruhin
82102279bc Get rid of configdata.SECTION_DESC 2017-07-04 15:08:02 +02:00
Florian Bruhin
624c6777ff Reorder configdata.yml 2017-07-04 15:08:02 +02:00
Florian Bruhin
94b200835a Hack in setting a value to NewConfigManager 2017-07-04 15:08:02 +02:00
Florian Bruhin
dc74a55b84 Fix remaining configtypes issues 2017-07-04 15:08:02 +02:00
Florian Bruhin
72d4421ac8 Make ShellCommand a List subclass
Also, let's not require a list in Command (which is used for aliases).
2017-07-04 15:08:02 +02:00
Florian Bruhin
3392ccc58b test_configtypes fixes 2017-07-04 15:08:02 +02:00
Florian Bruhin
ecba175b16 Test and fix configtypes to_str. 2017-07-04 15:08:02 +02:00
Florian Bruhin
4c2f65819b Try to fix qute://settings 2017-07-04 15:08:02 +02:00
Florian Bruhin
5414744439 Clean up NewConfigManager 2017-07-04 15:08:02 +02:00
Florian Bruhin
d69c6d0c66 Reorganize how configtypes store their data
Now the "object" kind of value (like in YAML) is stored internally, and that's
the canonical value. The methods changed their meaning slightly, see the
docstring in configtypes.py for details.
2017-07-04 15:08:02 +02:00
Florian Bruhin
1cbb4ece4b Force configtype.Dict keys to be strings 2017-07-04 15:08:02 +02:00
Florian Bruhin
41655e7852 Fix handling of none_ok in List/Dict
We now always return None (and '' as string) when the user configured an empty
list or dict.
2017-07-04 15:08:01 +02:00
Florian Bruhin
8ea3d92697 Initial implementation of to_str for configtypes 2017-07-04 15:08:01 +02:00
Florian Bruhin
0c1f480fc1 Remove TODO for qute://settings on webengine 2017-07-04 15:08:01 +02:00
Florian Bruhin
ffc29ee043 Make qute://settings work with QtWebEngine and new config
Fixes #2332
2017-07-04 15:08:01 +02:00
Florian Bruhin
fede64ba7a Add test for configdata.is_valid_prefix 2017-07-04 15:08:01 +02:00
Florian Bruhin
18eb133811 configdata: Make sure default values are valid 2017-07-04 15:08:01 +02:00
Florian Bruhin
0857a45b0a configtypes: parse regex flags properly 2017-07-04 15:08:01 +02:00
Florian Bruhin
a7c3bb0d55 Initial qute://settings upgrade 2017-07-04 15:08:01 +02:00
Florian Bruhin
3a6bcb3dd0 Remove icon from base.html 2017-07-04 15:08:01 +02:00
Florian Bruhin
36a5614c61 Add "FIXME" 2017-07-04 15:08:01 +02:00
Florian Bruhin
a1ed81f790 Patch out setting completion
Let's bring it back with the completion refactoring
2017-07-04 15:08:01 +02:00
Florian Bruhin
6733e92b50 Handle files correctly in utils.yaml_dump 2017-07-04 15:08:01 +02:00
Florian Bruhin
001312ca82 Disallow Booleans for configtypes.Int.from_py 2017-07-04 14:42:56 +02:00
Florian Bruhin
4e729bb9ec Back to using json in test_configtypes
It returns one-line data and is YAML compatible
2017-07-04 14:42:56 +02:00
Florian Bruhin
dfee857466 Make utils.yaml_dump return str 2017-07-04 14:42:56 +02:00
Florian Bruhin
05dc94ccc4 Improve configtypes tests 2017-07-04 14:42:56 +02:00
Florian Bruhin
7416164aca Rename old validate tests 2017-07-04 14:42:56 +02:00
Florian Bruhin
71f2e8c577 None validation fixups for test_configtypes 2017-07-04 14:42:56 +02:00
Florian Bruhin
ffd1a91467 Fix Directory conftype 2017-07-04 14:42:56 +02:00
Florian Bruhin
61ba92ae18 configtypes: Separate str/py basic validation
This also ensures the behavior for none_ok is consistent.
2017-07-04 14:42:56 +02:00
Florian Bruhin
cdbd64a30d Move test_configtypes_hypothesis to test_configtypes 2017-07-04 14:42:56 +02:00
Florian Bruhin
51a29468be configtypes: Use YAML for loading List/Dict from a string
This allows for a more lightweight syntax (like "{a: b}").
2017-07-04 14:42:56 +02:00
Florian Bruhin
41565fcfd4 configtypes: Use from_py for List/Dict values from a string 2017-07-04 14:42:56 +02:00
Florian Bruhin
7ddce62cd6 Refactor most of remaining config.get() calls 2017-07-04 14:42:56 +02:00
Florian Bruhin
51474724e5 Refactor objreg.get('config') calls 2017-07-04 14:42:56 +02:00
Florian Bruhin
cc0e66fe7b More config fixes 2017-07-04 14:42:56 +02:00
Florian Bruhin
6a451b37d7 re-raise NoOptionError 2017-07-04 14:42:56 +02:00
Florian Bruhin
52f15c84a6 Get rid of config sections 2017-07-04 14:42:56 +02:00
Florian Bruhin
7e7fbf106b Fix lint and old config options 2017-07-04 14:42:56 +02:00
Florian Bruhin
63bdee8b55 Initial configtype tests update 2017-07-04 14:42:56 +02:00
Florian Bruhin
ce7597b3f6 Fix various configtypes issues found while writing tests 2017-07-04 14:42:56 +02:00
Florian Bruhin
d751539a25 Add __eq__ and __repr__ for PACFetcher
This makes it possible to use it in comparisons during tests easily.
2017-07-04 14:42:56 +02:00
Florian Bruhin
cc90cc6843 Initial pylint checker update 2017-07-04 14:42:56 +02:00
Florian Bruhin
3cee9cdcd7 Fix JS logging 2017-07-04 14:42:56 +02:00
Florian Bruhin
45ce7efc71 Adjust feature permissions 2017-07-04 14:42:56 +02:00
Jakub Klinkovský
7eacea1057 Preserve fullscreen when exiting video fullscreen
Fixes #2778
2017-07-04 14:12:21 +02:00
Ryan Roden-Corrent
1e1335aa5e Make various SQL code review changes.
- Fix outdated comments
- Use mock specs when possible
- More precise error message check in test_import_txt_invalid.
- Fix copyright message
- Tweak missing pyqt error message
- Dead code: remove group_by and where from sqlcategory.
  With the new separate completion table, these are no longer used.
- Move test_history out of webkit/. History is no longer purely webkit
  related, it could be webengine.
2017-07-03 09:45:08 -04:00
Ryan Roden-Corrent
25c79bec67 Check correct SQL driver in earlyinit. 2017-07-03 08:15:06 -04:00
Ryan Roden-Corrent
a34df34208 Fix various test/flake8/pylint errors. 2017-07-03 08:12:47 -04:00
Ryan Roden-Corrent
f2dbff92f4 Check for PyQt.QtSql and sqlite in earlyinit.
Show a graphical error box with install instructions if PyQt.QtSql is
not found, rather than failing with CLI errors. Also show an error box
if the sqlite driver is not available.
2017-07-03 07:57:55 -04:00
Florian Bruhin
629038632c Add proxy support for QtWebEngine and Qt 5.7.1
This used to give us crashes in libproxy:
https://github.com/libproxy/libproxy/issues/45
https://bugreports.qt.io/browse/QTBUG-56852

However, trying again with Qt 5.7.1 on Debian and from PyPI, this doesn't happen
anymore, so it was probably something with how Archlinux handled things.

See #2082, #2775.
Reverts fd29528e4f
2017-07-03 10:29:28 +02:00
Florian Bruhin
3b53ec1cb6 Skip tests with permission changes if they didn't work
This e.g. wouldn't work inside of a Docker container otherwise.
2017-07-03 10:07:40 +02:00
Florian Bruhin
e828f5b812 Fix most config changed handlers 2017-07-02 22:17:33 +02:00
Florian Bruhin
c25022f549 Fix LimitLineParser 2017-07-02 22:17:33 +02:00
Florian Bruhin
1022b7ea32 Make jinja templating more strict
This ensures we actually know when an AttributeError happens.

It also changes most external code to use the correct environment, rather than
simply creating a jinja2.Template, which wouldn't use the more tightened
environment.
2017-07-02 22:17:33 +02:00
Florian Bruhin
4b4acc5f5a Minor config fixes 2017-07-02 22:17:33 +02:00
Florian Bruhin
c8c9536beb Fix completion stuff 2017-07-02 22:17:33 +02:00
Florian Bruhin
8c1b5f0581 Fix up background_tabs, favicon_show and some custom config magic 2017-07-02 22:17:33 +02:00
Florian Bruhin
1f508d9d8f Fix config getters 2017-07-02 22:17:33 +02:00
Florian Bruhin
b9aa5d0e4e Fix valid_values initing from configdata 2017-07-02 22:17:33 +02:00
Florian Bruhin
fcc0b3e8c0 Fix tab indicator width 2017-07-02 22:17:33 +02:00
Florian Bruhin
269e9d69e0 Improve typechecking message 2017-07-02 22:17:33 +02:00
Florian Bruhin
500ad8b00f Use strings for Perc configtypes 2017-07-02 22:17:33 +02:00
Florian Bruhin
e6275ab561 Fix startpage 2017-07-02 22:17:33 +02:00
Florian Bruhin
298553d48d Fix QssColor 2017-07-02 22:17:33 +02:00
Florian Bruhin
61fe40f4a1 Initial stylesheet refactoring for new config 2017-07-02 22:17:33 +02:00
Florian Bruhin
e2b0fdf8aa Fix VerticalPosition and NewTabPosition
Make them string so they have to_py() defined.
2017-07-02 22:17:33 +02:00
Florian Bruhin
a3d4822b9f Fix up adblock settings 2017-07-02 22:17:33 +02:00
Florian Bruhin
26bf588fad Fix _validate_valid_values 2017-07-02 22:17:33 +02:00
Florian Bruhin
231b7303f5 Use null for empty config values. 2017-07-02 22:17:33 +02:00
Florian Bruhin
af134eb861 Refactor websettings for new config 2017-07-02 22:17:33 +02:00
Florian Bruhin
129ee33ffb Refactor former network section 2017-07-02 22:17:33 +02:00
Florian Bruhin
f1d81d86aa Fix configtypes _basic_validation 2017-07-02 22:17:33 +02:00
Florian Bruhin
aa6f229e6b Add utils.yaml_{load,dump} 2017-07-02 22:17:33 +02:00
Florian Bruhin
1a6511c7a8 Refactor most stuff using config.val.ui 2017-07-02 22:17:33 +02:00
Florian Bruhin
1ed8df8903 Fix various typos/bugs 2017-07-02 22:17:33 +02:00
Florian Bruhin
3e3685b68b Initial configexc refactoring 2017-07-02 22:17:33 +02:00
Florian Bruhin
5ab2c89a37 Adjust config.change_filter 2017-07-02 22:17:33 +02:00
Florian Bruhin
b5110b07f0 Fix newconfig init 2017-07-02 22:17:33 +02:00
Florian Bruhin
3009e5eebe Fix configtypes mistakes 2017-07-02 22:17:33 +02:00
Florian Bruhin
8de0445661 Move UserAgent to configdata 2017-07-02 22:17:33 +02:00
Florian Bruhin
616aad84d8 More configtypes refactoring 2017-07-02 22:17:33 +02:00
Florian Bruhin
5ec47da127 Get rid of configtypes.AutoSearch and IgnoreCase 2017-07-02 22:17:33 +02:00
Florian Bruhin
921d02e4d3 First portion of configtypes refactoring 2017-07-02 22:17:33 +02:00
Florian Bruhin
7e52eb7b0e Initial work on new configdata 2017-07-02 22:17:33 +02:00
Florian Bruhin
c2e75bf2fd Initial conversion to new config syntax 2017-07-02 22:17:33 +02:00
Florian Bruhin
938946c48b configdata: Add check for shadowing keys 2017-07-02 22:17:33 +02:00
Florian Bruhin
8b9b750f8f configdata: Rename some options for consistency 2017-07-02 22:17:33 +02:00
Florian Bruhin
c856f6d97b Initial work on new pylint checker 2017-07-02 22:17:33 +02:00
Florian Bruhin
52f6ea2525 Initial parsing 2017-07-02 22:17:33 +02:00
Florian Bruhin
f965805099 First setting renames 2017-07-02 22:17:33 +02:00
Florian Bruhin
836395cdb1 Add configdata.yml 2017-07-02 22:17:33 +02:00
Florian Bruhin
00c8d8da34 Initial stubbing out of a new config 2017-07-02 22:17:33 +02:00
Florian Bruhin
2f26490536 Remove FIXME 2017-07-02 14:03:38 +02:00
Florian Bruhin
69337ed264 Update tox default envlist 2017-07-02 13:07:13 +02:00
Jay Kamat
2fbadc46d2 Remove error when count is invalid to :tab-pin 2017-06-30 09:57:39 -07:00
Florian Bruhin
9cedaa60bc Check for PyQt5.QtQml in earlyinit 2017-06-30 14:56:02 +02:00
Florian Bruhin
e4a054d34e Stop marking QtWebEngine as experimental 2017-06-30 10:42:33 +02:00
Jay Kamat
596dee69d6 Clean up pin_tab
Also add a test case for :pin-tab with an invalid count
2017-06-29 20:04:02 -07:00
Ryan Roden-Corrent
22880926b1 Fix WebHistoryStub for delete argument change 2017-06-29 21:46:09 -04:00
Ryan Roden-Corrent
c1f5e77fc6 Implement "Current" completion for bind.
When binding a key, the first row will be the current binding if the key
is already bound. This should make it easier for users to tell when they
are binding a key that is already bound, and what it is bound to.
2017-06-29 21:44:44 -04:00
Ryan Roden-Corrent
1e489325c4 Assert if index is invalid in delete_cur_item.
CompletionView already checks the index, so an error here shouldn't
happen.
2017-06-29 20:58:15 -04:00
Ryan Roden-Corrent
fd07c571e5 Store pattern in completion view, not model.
The pattern property is used for highlighting. It is purely
display-related, so it should be in the view rather than the model.
2017-06-29 20:56:39 -04:00
Ryan Roden-Corrent
262b028ee9 Match error message in lineparser test. 2017-06-29 20:49:05 -04:00
Ryan Roden-Corrent
c007f592b3 Use more intuitive argument order in sql.delete. 2017-06-29 20:43:42 -04:00
Florian Bruhin
0d5a33ef2a Update changelog 2017-06-29 23:21:10 +02:00
Florian Bruhin
d132b6ed71 Fix :scroll-page with --bottom-navigate on QtWebEngine
There were two issues here:

- The comparison was backwards, causing scroller.at_bottom() to always return
  true.
- When zoomed in, jsret['px']['y'] can be a float, which means we can be
  slightly off when checking the difference - math.ceil() fixes that.
2017-06-29 22:39:48 +02:00
Ryan Roden-Corrent
9c0c174534 Use builtin SortFilter regex functionality.
With the new completion API, we no longer need a custom filterAcceptsRow
function. This was necessary to handle the tree structure of the model,
but now we use a separate QSortFilterProxyModel for each category, so
the data it filters is flat. We can simplify the code by using the
builtin setFilterRegExp.

This changes the behavior a little, as now all list categories filter on
all columns. This should be beneficial if anything. For example, help
topics are now filtered on description in addition to name.

This also seems to slightly speed up filtering, according to the url
model benchmark.

Before:

----------------------------------------------- benchmark: 1 tests ----------------------------------------------
Name (time in s)                     Min     Max    Mean  StdDev  Median     IQR  Outliers(*)  Rounds  Iterations
-----------------------------------------------------------------------------------------------------------------
test_url_completion_benchmark     1.2806  1.3817  1.3195  0.0390  1.3068  0.0487          1;0       5           1
-----------------------------------------------------------------------------------------------------------------

After:

----------------------------------------------- benchmark: 1 tests ----------------------------------------------
Name (time in s)                     Min     Max    Mean  StdDev  Median     IQR  Outliers(*)  Rounds  Iterations
-----------------------------------------------------------------------------------------------------------------
test_url_completion_benchmark     1.1183  1.1508  1.1281  0.0132  1.1241  0.0142          1;0       5           1
-----------------------------------------------------------------------------------------------------------------
2017-06-29 12:44:02 -04:00
Jay Kamat
302961a86a Refactor set_tab_pinned to take a tab widget.
See #2759
2017-06-28 22:22:33 -07:00
Florian Bruhin
f136f78802 Fix :undo documentation
See #2759
2017-06-28 22:41:08 +02:00
Florian Bruhin
a98a6ac0c8 travis: Write a sane sources.list
Also updates nodejs
2017-06-28 21:42:50 +02:00
Jay Kamat
4d1dbe11e8 Prompt when closing a pinned tab via the mouse
Closes #2761
2017-06-27 19:03:13 -07:00
Ryan Roden-Corrent
6ac940fa32 Fix pylint/coverage errors.
Ensure 100% coverage for sqlcategory and history, and fix some linter
errors
2017-06-27 12:33:51 -04:00
Ryan Roden-Corrent
f06880c6e2 Fix history completion delete function.
In order to update SqlQueryModel's rowCount after re-running the query,
we must call setQuery again.
2017-06-27 08:42:10 -04:00
Iordanis Grigoriou
0a09758be1 Add file path to download 2017-06-27 12:21:25 +02:00
Iordanis Grigoriou
5e2be8a44a Fix PEP-8 issue 2017-06-27 08:25:59 +02:00
Iordanis Grigoriou
8a5b48d374 Add suggested_fn argument to get_request 2017-06-26 23:21:32 +02:00
Florian Bruhin
5ec94f96fd Allow a trailing % for :zoom 2017-06-26 21:51:35 +02:00
Florian Bruhin
92d5f6c41d Ignore _remove_tab for crashed deleted tabs 2017-06-26 20:50:17 +02:00
Florian Bruhin
24caaea54d Handle OSError in SessionManager.delete 2017-06-26 19:52:07 +02:00
Florian Bruhin
130be2aedc Handle OSError when trying to delete autosave session 2017-06-26 19:47:54 +02:00
Ryan Roden-Corrent
62a849c2db Fix bugs introduced in test_models 2017-06-26 12:41:48 -04:00
Florian Bruhin
736dd77a6e Regenerate authors 2017-06-26 18:05:25 +02:00
Florian Bruhin
8a7610206e Merge branch 'master' of https://github.com/jupart/qutebrowser 2017-06-26 18:04:57 +02:00
pyup-bot
78c93e1225 Update pytest-rerunfailures from 2.1.0 to 2.2 2017-06-26 15:47:14 +02:00
pyup-bot
e8dac08a35 Update cheroot from 5.5.2 to 5.7.0 2017-06-26 15:47:13 +02:00
pyup-bot
6d1775fcd6 Update pylint from 1.7.1 to 1.7.2 2017-06-26 15:47:11 +02:00
Ryan Roden-Corrent
46161c3af0 Refactor delete_cur_item.
Taking the completion widget as an argument was overly complex.
The process now looks like:

1. CompletionView gets deletion request
2. CompletionView passes selected index to CompletionModel
3. CompletionModel passes the row data to the owning category
4. The category runs its custom completion function.

This also fixes a bug. With the switch to the hybrid (list/sql)
completion model, the view was no longer updating when items were
deleted. This fixes that by ensuring the correct signals are emitted.

The SQL model must be refreshed by running the query. We could try using
a SqlTableModel so we can call removeRows instead.

The test for deleting a url fails because qmodeltester claims the length
of the query model is still 3.
2017-06-26 08:57:36 -04:00
Iordanis Grigoriou
a24d7f6686 Use page title for filename with :download 2017-06-26 12:25:03 +02:00
Ryan Roden-Corrent
866f4653c7 Fix spelling existant -> existent. 2017-06-25 22:14:38 -04:00
Justin Partain
cb67a911fa Remove recommendation to use '-c' command line argument, which doesn't exist 2017-06-21 10:56:25 -04:00
Marius
df6b8b7ff5 Update tabwidget.py 2017-06-21 09:03:15 +02:00
Ryan Roden-Corrent
6080830a8b Fix outdated docstring and pylint error. 2017-06-20 22:25:09 -04:00
Ryan Roden-Corrent
b722cc1dec Pass invalid index to [can]FetchMore.
For QSqlQueryModel, the argument should always be an invalid index:
http://doc.qt.io/qt-5/qsqlquerymodel.html#canFetchMore

For a QStandardItemModel, it doesn't matter. Either way, passing the
top-level parent index was wrong.
2017-06-20 22:11:53 -04:00
Ryan Roden-Corrent
63cb88a0f4 Use _cat_from_index in completionmodel.data.
Keep all the category lookup inside _cat_from_idx for easier refactoring
if the organization ever changes.
2017-06-20 22:08:23 -04:00
Ryan Roden-Corrent
0f585eda4f Bring history.py back to 100% coverage.
The code of debug_dump_history was tweaked to handle a possible
OSException that can be thrown by open, which I noticed while trying to
test it.
2017-06-20 21:41:43 -04:00
Marius
f3a2b84033 remove space 2017-06-20 23:58:23 +02:00
Marius
dfedddf0bd Wrap scroll button workaround in try/except
for older pyqt5 versions (5.2.1)
2017-06-20 23:55:11 +02:00
Marius
6e166d139a Fix alignment of scroll buttons in tab bar 2017-06-20 21:18:13 +02:00
Florian Bruhin
cb5cd1a910 Remove old test_commands.py 2017-06-20 15:20:32 +02:00
Florian Bruhin
994e8c692f Merge different FakeTabbedBrowser objects 2017-06-20 15:19:53 +02:00
Florian Bruhin
096b0a7a37 Remove unused import 2017-06-20 15:03:42 +02:00
Florian Bruhin
750ef834dc Make PyOpenGL a required dependency
Looks like the "black screen" issue isn't the only thing going wrong, some
people even report segfaults since the vendor check was added.
2017-06-20 13:05:53 +02:00
Florian Bruhin
73940a64bb Update docs 2017-06-20 12:46:55 +02:00
Florian Bruhin
cf3c7266aa Make show_error keyword-only 2017-06-20 12:45:36 +02:00
Florian Bruhin
06d4a24bd1 Merge branch 'master' of https://github.com/iordanisg/qutebrowser 2017-06-20 12:45:21 +02:00
Florian Bruhin
3a7a3909d7 Merge remote-tracking branch 'origin/pyup-scheduled-update-06-19-2017' 2017-06-20 12:44:05 +02:00
Florian Bruhin
038dcff4ba Ignore common URL issues while importing history
See #2646.

This ignores the "corrupted" Apple-lookalike URLs, comments and data: URLs.
2017-06-20 12:19:14 +02:00
Florian Bruhin
f838eb1bdc Use named formatting for queries in sql.py 2017-06-20 12:11:41 +02:00
Florian Bruhin
da875755d1 Add spaces after commas in SQL queries 2017-06-20 12:06:17 +02:00
Florian Bruhin
c1776bbf9d Add error message when query failed to prepare 2017-06-20 12:05:40 +02:00
Florian Bruhin
29ce1b3811 Add column order in SqlTable._insert_query
_insert_query gets called with a query and dict of values such as:

  {'val': 1, 'lucky': False, 'name': 'one'}

Via bindValues(), we only assign a placeholder in the query string to a value,
so we get a query with bindings like:

  INSERT INTO Foo values(:lucky,:val,:name)
  {':name': 'one', ':val': 1, ':lucky': False}

So what we're executing is something like:

  INSERT INTO Foo values(false,1,"one")

However, if the column order in the database doesn't happen to be the order
we're passing the values in, we get the wrong values in the wrong columns.

Instead, we now do:

  INSERT INTO Foo (lucky, val, name) values(false,1,"one")

Which inserts the values in the order we intended.

With Python 3.6, this just happened to work before because we always passed the
keyword arguments in the table column order, and in 3.6 dicts
(and thus **kwargs) happen to be ordered:
https://mail.python.org/pipermail/python-dev/2016-September/146327.html
2017-06-20 12:03:43 +02:00
Florian Bruhin
27c6aa00bd travis: Add group: edge 2017-06-19 18:15:35 +02:00
Iordanis Grigoriou
f0ff02fcb2 Avoid throwing exception when no last focused tab exists 2017-06-19 15:48:17 +02:00
pyup-bot
aa460a7abd Update hypothesis from 3.11.3 to 3.11.6 2017-06-19 15:46:21 +02:00
pyup-bot
0306c3e898 Update cheroot from 5.5.0 to 5.5.2 2017-06-19 15:46:19 +02:00
pyup-bot
61737f95a9 Update requests from 2.17.3 to 2.18.1 2017-06-19 15:46:18 +02:00
pyup-bot
5913f92b19 Update requests from 2.17.3 to 2.18.1 2017-06-19 15:46:16 +02:00
pyup-bot
86fffb5462 Update requests from 2.17.3 to 2.18.1 2017-06-19 15:46:15 +02:00
Florian Bruhin
3053ed01e4 backers: Add Bostan 2017-06-19 15:30:09 +02:00
Florian Bruhin
2adb57f263 travis: Remove the archlinux-ng docker env
Archlinux merged qt5-webkit-ng into qt5-webkit
2017-06-19 14:17:56 +02:00
Florian Bruhin
7062f9e060 Update qt5-webkit-ng docs for Archlinux 2017-06-19 13:44:41 +02:00
Florian Bruhin
4296a61b9a tests: Clean up check_history 2017-06-19 07:44:11 -04:00
Florian Bruhin
9f94f28181 Use :memory: for an in-memory database
Using an empty string for the same purpose only started working in some
recent-ish Qt/sqlite/? version, so using --version failed on Ubuntu Trusty.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
051d2665f3 Fix signal type error in CompletionView.
On Travis CI we are sometimes seeing:

```
CompletionView.selection_changed[str].emit():
argument 1 has unexpected type 'int'
```

Cast the data to a string before emitting it just to be safe.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
891a6bcf14 Fix flake8 errors 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
c7a18a8b8d Fix tests for recent sql changes 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
4e87773d89 Use a dict instead of named params for insert.
This allows replace to be a named parameter and allows consolidating
some duplicate code between various insert methods.

This also fixes some tests that broke because batch insert was broken.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
e436f48164 Small sql fixes.
- Remove unused SqlTable.Entry
- Fix wording of two log messages
- Remove unused import
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
f4f52ee204 Remove history.Entry.
No longer needed with sql backend. Query results build their own
namedtuple from the returned columns, and inserting new entries is just
done with named parameters.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
1fe1813431 Fix pylint errors. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
cf23f42b99 Use splitlines in test_history_bdd again.
Just using read() returns a single string, and iterating over that
iterates over each character.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
679e001a48 Separate sqlcategory title from table name.
Also fix a number of sql/completion tests that were failing.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
61a1709141 Fix completion selection bug.
Fix the issue where pressing `o<esc>o` would show a url completion
dialog where attempting to <Tab> select items would do nothing but show
a Qt warning.

The fix is to ensure we set _last_completion_func to None whenever we
clear completion (there was a case I missed).

It also ensures we always delete the old model and adds a safety to
prevent deleting an in-use model is set_model is called with the current
model.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
fa39b82b3c Backup old history file after import.
Instead of removing it, move it to history.bak.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
a6a9ad72f9 Fix test_history_interface.
This was still using a history dict instead of SQL history.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
22b7b21d5a Use named placeholders for sql queries. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
862f8d3188 Always return col 0 for index parent.
This was changed during code review but was causing Qt errors while
TAB-completing in the selection view:

08:42:34 WARNING  qt         Unknown module:none:0 Can't select indexes from different model or with different parents
2017-06-19 07:44:11 -04:00
Florian Bruhin
18cd8ba0b6 Add indices for HistoryAtimeIndex and CompletionHistoryAtimeIndex
before
------

sqlite> SELECT * FROM History where not redirect and not url like "qute://%" and atime > ? and atime <= ? ORDER BY atime desc;
Run Time: real 0.072 user 0.063334 sys 0.010000

sqlite> explain query plan SELECT * FROM History where not redirect and not url like "qute://%" and atime > ? and atime <= ? ORDER BY atime desc;
0|0|0|SCAN TABLE History
0|0|0|USE TEMP B-TREE FOR ORDER BY

sqlite> explain query plan select url, title, strftime('%Y-%m-%d', last_atime, 'unixepoch') from CompletionHistory where (url like "%qute%" or title like "%qute%") order by last_atime desc;
0|0|0|SCAN TABLE CompletionHistory
0|0|0|USE TEMP B-TREE FOR ORDER BY

after
-----

sqlite> SELECT * FROM History where not redirect and not url like "qute://%" and atime > ? and atime <= ? ORDER BY atime desc;
Run Time: real 0.000 user 0.000000 sys 0.000000

sqlite> explain query plan SELECT * FROM History where not redirect and not url like "qute://%" and atime > ? and atime <= ? ORDER BY atime desc;
0|0|0|SEARCH TABLE History USING INDEX AtimeIndex (atime>? AND atime<?)

sqlite> explain query plan select url, title, strftime('%Y-%m-%d', last_atime, 'unixepoch') from CompletionHistory where (url like "%qute%" or title like "%qute%") order by last_atime desc;
0|0|0|SCAN TABLE CompletionHistory USING INDEX CompletionAtimeIndex
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
3a4ef09f58 More sql code review fixes 2017-06-19 07:44:11 -04:00
Florian Bruhin
9b0395db08 Add an lru cache for WebHistoryInterface.historyContains
When loading heise.de, for some crazy reason QtWebKit calls historyContains
about 16'000 times.

With this cache (which we simply clear when *any* page has been loaded, as then
the links which have been visited can change), that's down to 250 or so...
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
6fc61d12fc Assorted small fixes for sql code review. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
feed9c8936 Better exception handling in history.
- Show an error message when import fails, not a generic crash dialog
- Raise CommandError when debug-dump-history fails
- Check that the path exists for debug-dump-history
2017-06-19 07:44:11 -04:00
Florian Bruhin
6ce52f39ae Add debug timings for SQL 2017-06-19 07:44:11 -04:00
Florian Bruhin
57d96a4512 Add a CompletionHistory instead of HistoryVisits table 2017-06-19 07:44:11 -04:00
Florian Bruhin
c64b7d00e6 Add separate table for history visits 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
7f27603772 Fix columns_to_filter for sql category. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
389e1b0178 Fix bad objreg reference in app.py. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
f8325cbbc1 Remove print statement 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
309b6ba32c Move _import_history to history.py.
Also adjusts the history import test to operate at a higher level and
ensure the old text file is removed (or isn't, in the case of an error).
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
ea0b3eee05 Use full, not partial index for history.
historyContains includes redirect urls, so we actually don't want a
partial index here.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
478a719f77 Use a prepared query for historyContains.
This is called often, hopefully a prepared query will speed it up.
This also modifies Query.run to return self for easier chaining, so you
can use `query.run.value()` instead of `query.run` ; query.value()`.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
5b827cf86a Fix typo in sql exception handling 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
6a0fc5afd2 Create a SQL index on History.url.
This will hopefully speed up historyContains but does not seem to speed
up the completion query, unfortunately.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
565ba23f8c Don't instantiate completion models nedlessly.
For real this time. A mistake on the last commit like this meant models
were still spuriously instantiated.
Now that the completion model is reused, the layoutChanged signal needs
to be forwarded through, otherwise the view will not update.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
42243d3d97 Add more performance logging to completion. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
a01c76db54 Remove 'group by' from url completion query.
This seemed to have a significant performance impact. Removing it means
that instead of just seeing the most recent atime for a given url, you
will see multiple entries.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
c297f047d2 Don't regenerate completion model needlessly.
If the completion model would stay the same, just keep it and update the
filter pattern rather than instantiating a new model each time the
pattern changes.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
2cd02be7b1 Remove CompletionModel.columns_to_filter.
Instead set this on inidividual categories, as that is where it actually
gets used. This makes it easier for SqlCompletionCategory to reuse a
prepared query (as it gets the filter field names in its constructor).
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
8fb6f45bec Don't set pattern in SqlCategory constructor.
This will be called by the Completer after construction anyways, this
was a duplicate call that could be expensive.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
cf89ffa971 Fix pylint/flake8 errors 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
2c501f7fb7 Fix url completion benchmark.
Still had old code from pre-SQL era.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
39b561a182 Fix BaseLineParser::test_double_open.
Don't tie the test to a particular error message. Ths failed because a
typo was fixed (AppendLineParser -> LineParser).
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
b1b521e0c2 Fix two history tests added recently.
These were added on master and needed to be adjusted slightly for the
new history check (which doesn't rely on reading a history file
anymore).
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
e67da51662 Use prepared SQL queries. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
20000088de Add debug-dump-history and fix sql history tests.
Trying to read from the sql database from another process was flaky.
This adds a debug-dump-history command which is used by the history BDD
tests to validate the history contents.

It outputs history in the old pre-SQL text format, so it might be
useful for those who want to manipulate their history as text.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
87643040a4 Fix test_history for python < 3.6.
Mock.assert_called is only in python 3.6. For earlier versions we must
use `assert m.called`.

Weird errors only appearing in CI, trying to debug...
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
e201a42383 Fix eslint errors 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
9b25b7ee5d Fix misspelling of 'occurs' 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
119c33ac32 Remove base.py from check_coverage.
This module no longer exists.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
882da71397 Remove unused imports 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
eb61269068 Fix qute://history javascript for SQL.
Returning "next" was no longer possible as the SQL query does not fetch
more items than necessary. This is solved by using a start time, a
limit, and an offset. The offset is needed to prevent fetching duplicate
items if multiple entries have the same timestamp.

Two of the history tests that relied on qute://history were changed to
rely on qute://history/data instead to make them less failure-prone.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
0aa0478327 Use EXISTS for SqlTable.contains. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
71191f10a2 Only complete most recent atime for url.
The history completion query is extended to pick only the most recent item for
a given url.

The tests in test_models now check for ordering of elements.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
9d4888a772 Optimize qute://history for SQL backend.
The old implementation was looping through the whole history list, which for
SQL was selecting every row in the database. The history benchmark was taking
~2s. If this is rewritten as a specialized SQL query, the benchmark takes
~10ms, an order of magnitude faster than the original non-SQL implementation.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
784d9bb043 Remove code rendered dead by sql implementation.
Vulture exposed the following dead code:

- AppendLineParse was only used for reading the history text file, which is now
  a sql database (and the import code for the old text file is simpler and does
  not need a complex line parser)

- async_read_done is no longer used as importing the history text file is
  synchronous (and should only happen once)

- config._init_key_config is unused as it was moved to keyconf.init
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
a8ed9f1c2f Fix qute://version sql init bug.
Calling sql.init() in version.version() would replace the existing sql
connection and cause a crash when accessed by opening qute://version.

Now version relies on sql already being initted, and app.py inits sql early if
the --version arg is given.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
231bbe7c2b Fix race condition on history tests.
Two history end2end tests are failing because sqlite is not flushing to disk in
time to be read by the test process. My understanding is that sqlite should
take an exclusive lock while writing, so it is difficult to understand why this
is happening. This can be fixed by adding a delay, but that seems flaky.

I'm fixing it by checking qute://history instead of reading the database file.

See:
https://github.com/qutebrowser/qutebrowser/pull/2295#issuecomment-292786138
and the following discussion.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
44080b8ad4 Fix flake8 errors in test_history 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
e661fb7446 Fix test_history.
History doesn't depend on standarddir anymore, the history file path get passed
by app.py.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
f110cf4d53 Fix long hang after importing history.
Turns out historyContains was getting called for the webkit backend multiple
times when the browser starts. This was calling `url in history`, which was
enumerating the entire history as `__contains__` was not defined.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
024386d189 Fail on history file parsing errors.
Instead of skipping bad history lines during the import to sql, fail hard. We
don't want to delete the user's old history file if we couldn't parse all of
the lines.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
6412c88277 Clean up history module.
Eliminate out-of-date docstring and remove an unused signal.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
3e63b62d6e Fix pylint/flake8 for sql work. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
8ff45331df Clean up sql implementation.
Now that sql is only used for history (not quickmarks/bookmarks) a number of
functions are no longer needed. In addition, primary key support was removed as
we actually need to support multiple entries for the same url with different
access times. The completion model will have to handle this by selecting
something like (url, title, max(atime)).

This also fixes up a number of tests that were broken with the last few
sql-related commits.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
80647b062a Convert old history file to sqlite.
If qutebrowser detects a history text file when it starts
(~/.local/share/qutebrowser/history by default on Linux), it will import this
file into the new sqlite database, then delete it.

The read is done as a coroutine as it can take some time.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
de5be0dc5a Store history in an on-disk sqlite database.
Instead of reading sqlite history from a file and storing it in an in-memory
database, just directly use an on-disk database. This resolves #755, where
history entries don't pop in to the completion menu immediately as they are
still being read asynchronously for a few seconds after the browser starts.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
b47c3b6a60 Test deleting a history entry from completion.
Deleting a history entry should do nothing, but we want a test to ensure this
and get 100% branch coverage for urlmodel.

This also un-skips the bookmark/quickmark tests.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
2eea115b3a Rename sqlcategory and add to perfect_files.
There was a typo in the file name.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
7d04f155c8 Add missing docstring. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
4296eed429 Fix test_history cleanup failure.
The test may be skipped if the PyQt5.QtWebKitWidget import fails, but the
cleanup was still running and trying to delete a nonexistant web-history.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
93e0bfa410 Fix tests after sql completion rebase. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
5dce6fa494 Fix pylint/flake8 errors 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
f95dff4d9e Decouple categories from completionmodel.
Instead of add_list and add_sqltable, the completion model now supports
add_category, and callees either pass in a SqlCategory or ListCategory. This
makes unit testing much easier.

This also folds CompletionFilterModel into the ListCategory class.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
ce3c555712 Use list completion for bookmarks/quickmarks.
The RFC on moving from plaintext to SQL storage (#2340) showed that many would
be upset if bookmarks and quickmarks were no longer stored in plaintext.

This commit uses list-based completion for quickmarks and bookmarks. Now the
history storage can be moved from plaintext to an on-disk SQL database while
leaving bookmarks and quickmarks as-is.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
1d54688b0b Revert "Use SQL completer for quickmarks/bookmarks."
This reverts commit bcf1520132df84552f69419f3b1cbf3ede20ccad.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
80619c88b3 Revert "Use SQL for quickmark/bookmark storage."
This reverts commit fa1ebb03b70dfff4ac64038e67d9bab04b984de5.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
e3a33ca427 Implement a hybrid list/sql completion model.
Now all completion models are of a single type called CompletionModel.
This model combines one or more categories. A category can either be a
ListCategory or a SqlCategory.

This simplifies the API, and will allow the use of models that combine simple
list-based and sql sources. This is important for two reasons:

- Adding searchengines to url completion
- Using an on-disk sqlite database for history, while keeping bookmarks and
  quickmars as text files.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
921211bbaa Remove web-history-max-items.
This was a performance optimization that shouldn't be needed with the new SQL
history backend. This also removes support for the LIMIT feature from SqlTable
as it only existed to support web-history-max-items.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
99c9b2d396 Fix two small mistakes after SQL code review.
urlmodel is now sorted, so the test had to be adjusted. Also remove one unused
import.
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
c4c5723a61 Sort history completion entries by atime. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
56f3b3a027 Small review fixups for SQL implementation.
Respond to the low-hanging code review fruit:

- Clean up some comments
- Remove an acidentally added duplicate init_autosave
- Combine two test_history tests
- Move test_init cleanup into a fixture to ensure it gets called.
- Name the _ argument of bind(_) to _key
- Ensure index is valid for first_item/last_item
- Move SqlException to top of module
- Rename test_index to test_getitem
- Return QItemFlags.None instead of None
- Fix copyright dates (its 2017 now!)
- Use * to force some args to be keyword-only
- Make some returns explicit
- Add sql to LOGGER_NAMES
- Add a comment to explain the sql escape statement
2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
3c676f9562 Fix pylint/flake8 errors for SQL work. 2017-06-19 07:44:11 -04:00
Ryan Roden-Corrent
a050cb94f6 Report sqlite version with --version. 2017-06-19 07:44:11 -04:00
Florian Bruhin
df0bd23d79 Make pylint shut up about test_version 2017-06-19 13:42:19 +02:00
Ryan Roden-Corrent
4968590075 Mention needed SQL packages in INSTALL.
With the new SQL completion backend, some distros must install sql packages.
This also removes trailing whitespace from one line.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
c6645d47ba Remove newest_slice and StatusBar._option.
newest_slice is no longer needed after the completion refactor. Now that
history is based on the SQL backend, LIMIT is used instead.

StatusBar._option is not used, though I'm not sure why vulture only caught it
now.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
1474e38eec Add urlmodel to perfect_files 2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
6a8b1d51fa Avoid config -> configmodel circular import.
Avoid the config dependency by using objreg.get('config') instead of
config.get.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
6cc2095221 Avoid keyconf circular import.
The new function-based completion API introduced a circular import:
config -> keyconf -> miscmodels -> config.

config only depended on keyconf so it could initialize it as part of
config.init. This can be resolved by moving this to keyconf.init and
initializing keyconf as part of app.init.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
fc5fd6096a Revert "Initialize SQL for two failing tests."
This reverts commit 386e227ce7534f1e427db7ba6d4e53dc153a49f3.
The problem was really state leakage, initializing sql for these tests isn't
necessary.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
788babbb61 Further prevent state leakage from test_init.
test_history.test_init also leaked state by leaving the instantiated history as
the parent of the QApp, which was causing test_debug to fail because it was
trying to dump the history object left from test_history.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
be38e181a8 Install libqt5sql5-sqlite for debian CI.
Needed for tests to pass with the new SQL dependency.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
d658378af3 Eliminate test interference from webkit history.
Initializing the qtwebkit history backend left some global state that was
leaking into other tests.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
21757a96a3 Add docstrings to SqlCompletionModel overrides.
Leaving QAbstractItemModel overrides undocumented made pylint angry.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
490250f5be Initialize SQL for two failing tests.
test_selectors and test_get_all_objects were running fine on my machine, but
for some reason is failing with "Driver not loaded" on Travis. Let's try
initializing SQL and see what happens.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
be07107b1c Fix end2end completion tests for SQL backend.
Change the logging to report the completion function name and have the end2end
tests check for this.

Remove the tests for realtime completion, as it was decided this is not an
important feature and the code is much simpler without it.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
6a04c4b3e8 Allow replacing quickmark with SQL backend.
This functionality was lost with the transition to SQL.
The user should be able to replace a quickmark if they answer 'yes' to the
prompt.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
02fb1a037c Implement canFetchMore for SQL completion.
This just forwards canFetchMore and fetchMore to the underlying tables.
It seems to be returning True and fetching in some cases (with a large
history), so I guess it is useful?
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
ffd044b52b Fix pylint and flake8 for SQL work.
Vanity commit. This also touches up a few comments.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
ea9217a61f Fix qutescheme for new SQL backend.
The qute://history and qute://bookmarks handlers were added during my work, and
had to be adapted to the SQL-based history backend.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
0e650ad719 Return namedtuples from SqlTable.
Instead of returning a regular tuple and trying to remember which index maps to
which field, return named tuples that allow accessing the fields by name.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
d89898ef7d Implement delete_cur_item for sql completion.
This re-enables bookmark/quickmark deletion for url completions via the new SQL
interface.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
fe80878788 Implement custom where clause in SQL.
Allow categories to specify a WHERE clause that applies in addition to the
pattern filter. This allows the url completion model to filter out redirect
entries.

This also fixed the usage of ESCAPE so it applies to all the LIKE statements.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
9f27a9a5d7 Implement column selectors for sql completion.
A SQL completion category can now provide a customized column expression for
the select statement. This enables the url model to format timestamps, as well
as rearrange the name and url in the quickmark section.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
3f6f03e325 Respect web-history-max-items with SQL.
Use a LIMIT with the sql competion model to limit history entries as the old
completion implementation did.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
df995c02a3 Get rid of varargs in sql.run_query.
Things are clearer when just passing a list.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
b70d5ba901 Use QSqlQueryModel instead of QSqlTableModel.
This allows setting the query as a QSqlQuery instead of a string, which allows:

- Escaping quotes
- Using LIMIT (needed for history-max-items)
- Using ORDER BY (needed for sorting history)
- SELECTing columns (needed for quickmark completion)
- Creating a custom select (needed for history timestamp formatting)
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
52d7d1df0c Use SQL completer for quickmarks/bookmarks. 2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
839d49a8ac Fix up pylint/flake8 for completion revamp. 2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
5bd047b70b Fix CompletionView.completion_item_del for new API.
The new function based completion models work a little differently so the view
needed slightly different error handling.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
b381148e06 Unittest CompletionView.completion_item_del.
There were no unit tests for this and the various ways it can fail, and I'm
about to screw with it a bit.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
c3155afc21 Rethrow KeyError as DoesNotExistError in urlmarks.
From @TheCompiler:
To expand on this: I think it's fine to use KeyError on a lower level, i.e.
with the SqlTable object with a dict-like interface. However, on this higher
level, I think it makes sense to re-raise them as more specific exceptions.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
a774647c26 Get test_models mostly working again.
- Adjust _check_completions to work for CompletionModel and SqlCompletionModel
- Move sql initialization into a reusable fixture
- Remove the bookmark/quickmark/history stubs, as they're now handled by sql
- Disable quickmark/bookmark model tests until their completion is ported to
  sql.
- Disable urlmodel tests for features that have to be implemented in SQL:
    - LIMIT (for history-max-items)
    - Configurable column order (for quickmarks)
    - Configurable formatting (for timestamp-format
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
d4f2a70f83 Slightly simplify CompletionModel.new_item.
There was no need to have a branch based on whether the misc value was None or
not.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
93f8984987 Install pyqt5.qtsql bindings for debian CI.
SQL is included in the Archlinux pyqt5 package, but not in Debian.
We need this so the debian-based CI builds will pass with the new
sql-based completion implementation.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
3005374ada Simplify sorting logic in sortfilter.
For URL completion, time-based sorting is handled by the SQL model.
All the other models use simple alphabetical sorting. This allowed cleaning up
some logic in the sortfilter, removing DUMB_SORT, and removing the
completion.Role.sort.

This also removes the userdata completion field as it was only used in url
completion and is no longer necessary with the SQL model.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
acea0d3c67 Use SQL completion for the open command.
Now that history, bookmark, and quickmark storage are SQL-backed, use
a sql completion model to serve url completions.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
6e1ea89ca1 Implement SQL completion model.
This model wraps one or more SQL tables and exposes data in a tiered
manner that can be consumed by the tree view used for completion.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
93d81d96ce Use SQL for quickmark/bookmark storage.
Store quickmarks and bookmarks in an in-memory sql database instead of a
python dict. Long-term storage is not affected, bookmarks and
quickmarks are still persisted in a text file.

The added and deleted signals were removed, as once sql completion
models are used the models will no longer need to update themselves.

This will set the stage for SQL-based history completion.
See #1765.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
9477a2eeb2 Use SQL for history storage.
The browser-wide in-memory web history is now stored in an in-memory sql
database instead of a python dict. Long-term storage is not affected, it
is still persisted in a text file of the same format.

This will set the stage for SQL-based history completion.
See #1765.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
f43f78c40f Implement SQL interface.
When qutebrowser starts, it creates an in-memory sqlite database. One
can instantiate a SqlTable to create a new table in the database. The
object provides an interface to query and modify the table.

This intended to serve as the base class for the quickmark, bookmark,
and history manager objects in objreg. Instead of reading their data
into an in-memory dict, they will read into an in-memory sql table.

Eventually the completion models for history, bookmarks, and quickmarks
can be replaced with SqlQuery models for faster creation and filtering.

See #1765.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
3b30b42211 Remove completion.instances, usertypes.Completion.
The new completion API no longer needs either of these. Instead of
referencing an enum member, cmdutils.argument.completion now points to
a function that returnsthe desired completion model.
This vastly simplifies the addition of new completion types. Previously
it was necessary to define the new model as well as editing usertypes
and completion.models.instances. Now it is only necessary to define a
single function under completion.models.

This is the next step of Completion Model/View Revamping (#74).
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
b36cf0572d Avoid potential circular import in config.py.
There was a circular import from
config -> keyconf -> miscmodels -> config.
This is resolved by scoping config's keyconf import to the one function
that uses it.
2017-06-19 07:42:12 -04:00
Ryan Roden-Corrent
08bb3f4f19 Implement completion models as functions.
First step of Completion Model/View revamping (#74). Rewrite the
completion models as functions that each return an instance of a
CompletionModel class.

Caching is removed from all models except the UrlModel. Models other
than the UrlModel can be generated very quickly so caching just adds
needless complexity and can lead to incorrect results if one forgets to
wire up a signal.
2017-06-19 07:42:12 -04:00
Florian Bruhin
40b949364e Fix qute://backend-warning issues
We now set a title correctly, and don't crash if we find a Debian/Ubuntu without
version.
2017-06-19 13:37:00 +02:00
Florian Bruhin
bef372e5f5 Clear search on page load
Fixes #2728
2017-06-19 10:27:27 +02:00
Florian Bruhin
4ae8e247d0 Show 'legacy QtWebKit' in version output 2017-06-19 10:24:33 +02:00
Florian Bruhin
8191a5465a Regenerate authors 2017-06-19 09:44:04 +02:00
Florian Bruhin
5bb63e67e0 Remove another stray # 2017-06-19 09:43:45 +02:00
Florian Bruhin
8494332c3a Merge branch 'fix-tabbar-padding' of https://github.com/kmarius/qutebrowser 2017-06-19 09:43:26 +02:00
Florian Bruhin
df6c4c6e73 Fix earlyinit.qt_version issues 2017-06-19 09:42:49 +02:00
Florian Bruhin
9b5227b987 Improve test_version output 2017-06-19 09:06:18 +02:00
Florian Bruhin
6c534bea6b Actually remove version import in earlyinit... 2017-06-19 08:59:26 +02:00
Florian Bruhin
fdba676933 Move version.qt_version() to earlyinit
Importing version in earlyinit is a bad idea, as it already pulls in a lot of
stuff we don't want.
2017-06-19 08:57:29 +02:00
Marius
de743732aa remove # inside comment 2017-06-19 08:29:23 +02:00
Marius
ebd442ea95 add needed parens and remove trailing whitespace 2017-06-18 23:07:38 +02:00
Marius
68f172558b fix line length 2017-06-18 22:44:06 +02:00
Marius
4b2bf12efa Fix padding of remaining tabbar space with pinned tabs 2017-06-18 21:49:04 +02:00
Florian Bruhin
a5db21abe9 Update FAQ, fixes #2732 2017-06-17 15:47:39 +02:00
Florian Bruhin
695a2656fe Rename webelem.js functions to match WebEngineElem
Fixes #2726
2017-06-16 23:14:17 +02:00
Florian Bruhin
9cc688ea2b Fix initial tab sizing with vertical tabbar 2017-06-16 23:00:16 +02:00
Iordanis Grigoriou
e14477375b Fix typo in test 2017-06-16 12:41:30 +02:00
Iordanis Grigoriou
f28d523225 Select the last focused tab when running ':tab-focus <current tab number>' 2017-06-16 12:28:56 +02:00
Florian Bruhin
b37d040d44 Add version check for 5.8 search segfault workaround 2017-06-14 10:57:32 +02:00
Florian Bruhin
2ffb10badf Merge pull request #2715 from qutebrowser/pyup-scheduled-update-06-12-2017
Scheduled weekly dependency update for week 24
2017-06-14 10:44:11 +02:00
Florian Bruhin
54154e2434 Mark :stop test as flaky
Looks like the requests sometimes aren't updated, but I have no idea why.
2017-06-12 18:15:05 +02:00
Florian Bruhin
38d54cb112 Stabilize history tests
Get current URL right away in :view-source, and wait until source is shown in
the test.
2017-06-12 18:13:17 +02:00
pyup-bot
c9979d18db Update pytest from 3.1.1 to 3.1.2 2017-06-12 15:45:19 +02:00
pyup-bot
a2878a382c Update hypothesis from 3.11.1 to 3.11.3 2017-06-12 15:45:17 +02:00
pyup-bot
1deb6e53d0 Update chardet from 3.0.3 to 3.0.4 2017-06-12 15:45:16 +02:00
pyup-bot
227fd47f2f Update chardet from 3.0.3 to 3.0.4 2017-06-12 15:45:15 +02:00
pyup-bot
62d56237bd Update chardet from 3.0.3 to 3.0.4 2017-06-12 15:45:13 +02:00
Florian Bruhin
b687ede25c Adjust eslintrc for eslint 4.0 2017-06-12 09:23:20 +02:00
Florian Bruhin
57fbfbd606 Set an initial window size for background tabs
When we open a background tab, it gets a hardcoded size (800x600 or so) because
it doesn't get resized by the layout yet.

By resizing it to the size it'll actually have later, we make sure scrolling to
an anchor in an background tab works, and JS also gets the correct size for
background tabs.

Fixes #1190
Fixes #2495
See #1417
2017-06-11 17:48:01 +02:00
Florian Bruhin
2e5620cac1 Try a different way of fixing userscript crashes 2017-06-11 14:44:19 +02:00
Florian Bruhin
a49adc6298 Revert "Work around userscript crash issue"
This reverts commit 73ff2afb3f.

Doesn't seem to help, at least for pkill9...
2017-06-11 14:41:58 +02:00
Florian Bruhin
73ff2afb3f Work around userscript crash issue 2017-06-11 13:17:40 +02:00
Florian Bruhin
89218c9d31 Improve error handling in version.opengl_vendor()
Not being able to get versionFunctions is now handled, and the cleanup is done
in a finally: block.
2017-06-09 23:14:34 +02:00
Florian Bruhin
9c851293ac pyinstaller: Add PyQt5.QtOpenGL to hiddenimports 2017-06-09 21:50:52 +02:00
Florian Bruhin
ad260366ef Remove ":messages without messages" test
We can never know for sure there aren't any messages - for example, on Travis we get a message about XDG_RUNTIME_DIR being unset on Qt 5.9.
2017-06-09 11:04:21 +02:00
Florian Bruhin
9f9061f146 Update docs 2017-06-09 11:04:04 +02:00
Florian Bruhin
b874432c69 Remove private browsing notes for QtWebKit-NG 2017-06-09 10:31:21 +02:00
Florian Bruhin
250da212cd Adjust tests for new QtWebKit-NG 2017-06-09 10:28:41 +02:00
Florian Bruhin
d2c289b6a6 Adjust changelog 2017-06-08 14:18:40 +02:00
Florian Bruhin
6361a5bab2 Merge branch 'private_tag_tab_title' of https://github.com/craftyguy/qutebrowser 2017-06-08 14:17:43 +02:00
Florian Bruhin
56f1dfb9eb Merge remote-tracking branch 'origin/pyup-update-isort-4.2.14-to-4.2.15' 2017-06-08 14:17:25 +02:00
Florian Bruhin
ddf4521305 Fix :messages tests 2017-06-08 14:16:30 +02:00
Florian Bruhin
c8d4ef13de Adjust default :messages level 2017-06-08 12:35:21 +02:00
Florian Bruhin
63f6409fdb Remove stray StatusBar._option 2017-06-08 12:29:07 +02:00
Clayton Craft
daa12ed435 Add private mode title format for tabs too
This continues the spirit of my previous PR and allows formatting tab
titles to designate when private mode is enabled. I didn't even realize
that tab title-format was a separate thing from window-title-format
(yes, it's in the name.. silly craftyguy), until now.
2017-06-07 08:17:03 -07:00
Florian Bruhin
7e09b7a707 manifest: Exclude all hidden files 2017-06-07 12:25:15 +02:00
Florian Bruhin
1123129dc4 Slow down pyup requirement updates 2017-06-07 11:19:17 +02:00
pyup-bot
b7cb852c1a Update isort from 4.2.14 to 4.2.15 2017-06-07 09:50:12 +02:00
pyup-bot
dbea815c3a Update isort from 4.2.14 to 4.2.15 2017-06-07 09:50:11 +02:00
Florian Bruhin
09baa08948 Remove colon from error page 2017-06-06 22:15:19 +02:00
Florian Bruhin
dd4fb87db6 Update docs 2017-06-06 18:25:42 +02:00
Florian Bruhin
8990513c1b Merge commit '49b8737f7979fc878ba25aed94cc3e57f481ae3a' into craftyguy/private_tab_title 2017-06-06 18:23:51 +02:00
Florian Bruhin
8df0b063be Get rid of utils.unused because it's unused 2017-06-06 17:04:21 +02:00
Clayton Craft
49b8737f79 Implement changing of tab title when privacy mode is enabled 2017-06-06 08:00:19 -07:00
Florian Bruhin
a5af98b063 Add a few tests for qutebrowser.is_ignored_chromium_message 2017-06-06 16:26:01 +02:00
Florian Bruhin
cb03fb7d80 Make process/thread ID optional for Chromium messages
Looks like at least on Travis they're not always there.
2017-06-06 16:18:53 +02:00
Florian Bruhin
dd490f85d8 Update docs 2017-06-06 16:18:15 +02:00
Florian Bruhin
6d175fbb4b Get rid of configtypes.WebKitBytes 2017-06-06 16:17:44 +02:00
Florian Bruhin
f9b046d766 Get proper settings object in WebEngineElement._click_js 2017-06-06 16:15:25 +02:00
Florian Bruhin
a7413d7b4a Remove stale getter 2017-06-06 15:59:42 +02:00
Florian Bruhin
1b0a125cf3 websettings: Improve errors when setting settings=... 2017-06-06 15:59:42 +02:00
Florian Bruhin
b1a0bc13f2 webkitsettings: Use self._get_settings in CookiePolicy._set 2017-06-06 15:59:42 +02:00
Florian Bruhin
30fe3ed328 Remove old websetting comments 2017-06-06 15:46:54 +02:00
Florian Bruhin
e17494c972 Cleanup 2017-06-06 15:25:21 +02:00
Florian Bruhin
9c9a5914b3 Changelog fixup 2017-06-06 14:50:57 +02:00
Florian Bruhin
0ca59f2184 Rename storage -> offline-web-application-storage to -cache 2017-06-06 14:50:57 +02:00
Florian Bruhin
c696723650 Merge storage -> offline-storage-database into local-storage setting
Looks like it's the same with QtWebEngine too - setting LocalStorageEnabled also
toggles WebSQL there.
2017-06-06 14:50:57 +02:00
Florian Bruhin
626d299a0d Add webenginesettings.DefaultProfileSetter.__repr__ 2017-06-06 14:50:57 +02:00
Florian Bruhin
93d21c376d Regenerate docs 2017-06-06 14:50:57 +02:00
Florian Bruhin
2a32e26846 Get rid of various rarely customized settings
All those were customized by some <5 people in the past few years of crash
reports.

Closes #1751.
See #2639.
2017-06-06 14:50:57 +02:00
Florian Bruhin
1785b72393 Refactor websettings default handling
With per-domain settings, having a getter for a setting gets really complicated,
as there isn't one true value for a setting.

The only reason we needed those getters is to save away the default values for
some settings where we were unsure what the defaults are.

- For font setters, we can get the defaults from QFont, like QtWeb{Kit,Engine}
  do.
- For font sizes, we hardcode the defaults QtWeb{Kit,Engine} hardcodes too.
- For maximum-page-in-cache, we hardcode 0, just like QtWebKit.
- For default-encoding, we hardcode iso-8559-1, like QtWeb{Kit,Engine}
- For offline-storage-default-quota, we hardcode 5MB, like QtWebKit
- For offline-web-application-cache-quota, we hardcode MAXINT as default value,
  but we still keep the empty value in the config. It means "no quota"
  internally in QtWebKit, but it's a too confusing value to have in the config.
- For object-cache-capacities it's a bit more complicated (the defaults are
  calculated based on disk space), but let's just get rid of the setting
  altogether in the next commit (see #1751).

Closes #2639.
2017-06-06 14:50:57 +02:00
Florian Bruhin
2f5756e63b Merge commit '0501cc626c27a369c2e311c71c2ce2c5cc3f9442' into pyup-bot/pyup-update-isort-4.2.13-to-4.2.14 2017-06-06 10:19:00 +02:00
Florian Bruhin
998f93dfd3 tests: Properly parse Chromium logging messages
Closes #2519
2017-06-06 10:01:45 +02:00
pyup-bot
0501cc626c Update isort from 4.2.13 to 4.2.14 2017-06-06 09:20:10 +02:00
pyup-bot
d57f96da87 Update isort from 4.2.13 to 4.2.14 2017-06-06 09:20:09 +02:00
Florian Bruhin
f280129e7c Merge commit 'ccdba004272ef40dfa1668a21329876253877155' into pyup-bot/pyup-update-astroid-1.5.2-to-1.5.3 2017-06-06 07:59:15 +02:00
Florian Bruhin
46d11655d8 Merge commit '6a17ee66adee0da5b88c0246c833cf7023bee9cc' into pyup-bot/pyup-update-py-1.4.33-to-1.4.34 2017-06-06 07:59:11 +02:00
Florian Bruhin
b746fe666c Remove colorama from test requirements
Otherwise it collides with the colorama in qutebrowser's own requirements.
2017-06-06 07:56:30 +02:00
Florian Bruhin
d4f58533c0 Add error messages for QtWebEngine downloads
Fixes #2164
2017-06-06 06:29:52 +02:00
Florian Bruhin
0e85342f57 Update changelog 2017-06-05 23:50:24 +02:00
Florian Bruhin
73249d8abe Adjust ignored Chromium messages for Qt 5.9 debug builds 2017-06-05 21:57:53 +02:00
Florian Bruhin
eea3396cdc Add hunter to test requirements 2017-06-05 20:18:36 +02:00
Florian Bruhin
27ea9a6954 Fix test_debug_trace 2017-06-05 20:17:39 +02:00
Florian Bruhin
a45de9cef2 Remove request tracking from NetworkManager
This breaks things (with "ValueError: list.remove(x): x not in list") on
PyQt 5.9 (probably due to the destroyed object tracking it introduces?).

This was originally added in 0abb5cf738 to fix
some segfaults on exit, but things look much better with recent Qt versions.
2017-06-05 18:19:29 +02:00
Florian Bruhin
211f9cfc8c Add SB to backers 2017-06-05 13:04:37 +02:00
Florian Bruhin
4d64bcc852 Make version.opengl_vendor() work with an existing context
This makes it possible to use it in :debug-console
2017-06-04 23:05:23 +02:00
Florian Bruhin
a858611bb9 Don't make errors in version.opengl_vendor() fatal
Fixes #2694
2017-06-04 22:55:39 +02:00
pyup-bot
6a17ee66ad Update py from 1.4.33 to 1.4.34 2017-06-04 18:49:11 +02:00
pyup-bot
c15f7e8e72 Update py from 1.4.33 to 1.4.34 2017-06-04 18:49:09 +02:00
Florian Bruhin
71117f6dea Adjust debian deps in INSTALL 2017-06-04 15:12:11 +02:00
Florian Bruhin
70b3231dd1 Add some more stuff to the FAQ 2017-06-04 15:11:08 +02:00
pyup-bot
ccdba00427 Update astroid from 1.5.2 to 1.5.3 2017-06-03 16:33:05 +02:00
Florian Bruhin
c0705e735f Merge commit '9841f75f915a27a7bb81e917db08b615624cd1b6' into pyup-bot/pyup-update-isort-4.2.9-to-4.2.13 2017-06-02 21:54:51 +02:00
Florian Bruhin
722c117d54 Better handling of OpenSSL 1.1
Fixes #2690
2017-06-02 21:52:53 +02:00
pyup-bot
9841f75f91 Update isort from 4.2.9 to 4.2.13 2017-06-02 18:50:05 +02:00
pyup-bot
5f0f1cb7da Update isort from 4.2.9 to 4.2.13 2017-06-02 18:50:03 +02:00
Florian Bruhin
a90429fe6e Update needed dependencies
Fixes #2683
2017-06-01 19:30:32 +02:00
Florian Bruhin
1615c0aa1a Merge commit '4c9c9bdf989d18ffdd0c80e84fdde0ee9601d448' into pyup-bot/pyup-update-isort-4.2.5-to-4.2.9 2017-06-01 19:14:43 +02:00
pyup-bot
4c9c9bdf98 Update isort from 4.2.5 to 4.2.9 2017-06-01 18:04:04 +02:00
pyup-bot
002cfedaef Update isort from 4.2.5 to 4.2.9 2017-06-01 18:04:03 +02:00
Florian Bruhin
e15b7a4fde Recompile requirements
This reintroduces packages which have been masked before (as they were pip
dependencies).
2017-06-01 16:42:12 +02:00
Florian Bruhin
3523c2e78b Merge commit 'a9d739ec04898563d3d7cb790a621fb97fe0f23d' into pyup-bot/pyup-update-pytest-3.1.0-to-3.1.1 2017-06-01 16:24:34 +02:00
Florian Bruhin
0f9eb2ac54 Merge commit 'bf97bc9d3e97e608734e4ebc0d071c71ab1ab013' into pyup-bot/pyup-update-parse-1.8.0-to-1.8.2 2017-06-01 16:23:12 +02:00
Florian Bruhin
0945179f74 Merge commit '71cca7c154816678f955b242438417a2d8026198' into pyup-bot/pyup-update-setuptools-35.0.2-to-36.0.1 2017-06-01 16:22:58 +02:00
Florian Bruhin
f49bbcbb9f Sort names in recompile_requirements again
This got lost with the previous revert
2017-06-01 16:21:48 +02:00
Florian Bruhin
a7143d5649 Revert "Update recompile_requirements for newer pips"
This reverts commit 8afc215c3d.

Since setuptools 36, it now vendors its dependencies again, as the vendoring has
lead to various issues.
2017-06-01 16:16:04 +02:00
pyup-bot
71cca7c154 Update setuptools from 35.0.2 to 36.0.1 2017-06-01 15:37:03 +02:00
Florian Bruhin
a690d242a4 Update webengine dependency message 2017-06-01 14:03:46 +02:00
Florian Bruhin
c4d2b60f4d Initial backers file update 2017-06-01 13:54:48 +02:00
pyup-bot
bf97bc9d3e Update parse from 1.8.0 to 1.8.2 2017-06-01 02:30:03 +02:00
pyup-bot
a9d739ec04 Update pytest from 3.1.0 to 3.1.1 2017-05-31 19:37:05 +02:00
Florian Bruhin
587861d899 Check for OpenGL ES later
It looks like we still got False on AppVeyor with "versionFunctions: Not
supported on OpenGL ES". Hopefully this helps.
2017-05-31 11:44:34 +02:00
Florian Bruhin
eac284d880 Skip test_opengl_vendor without QtOpenGL
The test fails on Ubuntu Xenial because QtOpenGL is not installed.
This isn't a problem with real-life usage though, as we only call it with
QtWebEngine, and that ensures that QtOpenGL is available.
2017-05-31 10:29:46 +02:00
Florian Bruhin
4cec9adce6 Fix lint 2017-05-31 09:44:17 +02:00
Florian Bruhin
28f7444d9e Update changelog 2017-05-31 07:14:19 +02:00
Florian Bruhin
912cea6e7d Improve version.opengl_vendor()
On Windows with OpenGL ES we can't use versionFunctions, so we just return None
early.

Also, this fixes some lint and adds a smoke test.
2017-05-30 19:23:27 +02:00
Florian Bruhin
b8a32c577f Merge branch 'nouveau' 2017-05-30 17:36:58 +02:00
Florian Bruhin
62b44c5338 Fix lint 2017-05-30 17:07:31 +02:00
Florian Bruhin
eb9a0c01ba Set backend-warning-shown in test_invocations 2017-05-30 16:49:39 +02:00
Florian Bruhin
67755e6f6c Add error message for QtWebEngine and Nouveau
See #2368
2017-05-30 16:47:39 +02:00
Florian Bruhin
048aec1aa6 Revert "Reorganize earlyinit checks"
This reverts commit 6f3f9ede01a6b30b105d5110a48cfea592e8db52.
2017-05-30 15:53:29 +02:00
Florian Bruhin
d0461eece3 Reorganize earlyinit checks
We first do all checks we can without knowing the backend, before getting that.
This is because we need to do some more stuff in get_backend now.
2017-05-30 15:53:29 +02:00
Florian Bruhin
bec8299b2e Update install instructions
Closes #2440
2017-05-30 15:34:46 +02:00
Florian Bruhin
58de271fc1 Regenerate authors 2017-05-30 10:40:33 +02:00
Florian Bruhin
65329c97c7 Merge branch 'pyup-bot/pyup-update-requests-2.16.5-to-2.17.3' 2017-05-30 10:39:50 +02:00
Florian Bruhin
f656cda248 Merge commit '798cae51d4971a74fa5a7de4815b32d9871caad5' 2017-05-30 10:39:20 +02:00
Florian Bruhin
8167c55e61 Merge commit 'ee99b25bf6eb203726a796f53fa60036f5caeb24' into pyup-bot/pyup-update-requests-2.16.5-to-2.17.3 2017-05-30 10:37:11 +02:00
Florian Bruhin
1c6fd6f725 Add a backend warning when using QtWebKit 2017-05-30 08:42:37 +02:00
Florian Bruhin
4cb82af11e Add QUTE_FAKE_OS_RELEASE envvar 2017-05-30 07:37:10 +02:00
pyup-bot
ee99b25bf6 Update requests from 2.16.5 to 2.17.3 2017-05-30 01:20:03 +02:00
pyup-bot
009acc1600 Update requests from 2.16.5 to 2.17.3 2017-05-30 01:20:02 +02:00
pyup-bot
863e1f1d84 Update requests from 2.16.5 to 2.17.3 2017-05-30 01:20:00 +02:00
Philipp Hansch
798cae51d4 Fix pylint issue 2017-05-29 23:15:22 +02:00
Philipp Hansch
ad8cf371b8 Style table of contents properly for qute theme 2017-05-29 21:50:06 +02:00
Philipp Hansch
932b2814b0 Hide false header element from the TOC 2017-05-29 21:50:04 +02:00
Philipp Hansch
abd3333b9f Add TOC to installation instructions
This adds a Table of Contents to the installation instructions to
improve the navigation within the document.

I decided to use the command line to configure the TOC because there
were problems with using just using an attribute entry in the document
header.
Specifically the insertion of the `header.asciidoc` into the resulting
HTML file prevented the attribute entry approach from working.

The TOC can now be inserted into any doc file using

    toc::[]
2017-05-29 21:14:01 +02:00
Florian Bruhin
ef504e5b25 Allow None for WebKitElement.value
This fixes an exception when trying to run :open-editor with a comment field
with QtWebKit:

    16:37:51 DEBUG    webelem    webelem:is_editable:238 Checking if element is editable: <qutebrowser.browser.webkit.webkitelem.WebKitElement html='<div id="writer9997095275-writer" class="writer selectable no-lub put-art-here ui-droppable empty" style="min-height: 146px; width: 1169px;" contenteditable="true"></div>'>
    16:37:51 ERROR    misc       crashsignal:exception_hook:205 Uncaught exception
    Traceback (most recent call last):
      File "/home/florian/proj/qutebrowser/git/qutebrowser/app.py", line 882, in eventFilter
        return handler(event)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/app.py", line 842, in _handle_key_event
        return man.eventFilter(event)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/keyinput/modeman.py", line 337, in eventFilter
        return self._eventFilter_keypress(event)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/keyinput/modeman.py", line 168, in _eventFilter_keypress
        handled = parser.handle(event)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/keyinput/basekeyparser.py", line 307, in handle
        handled = self._handle_special_key(e)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/keyinput/basekeyparser.py", line 136, in _handle_special_key
        self.execute(cmdstr, self.Type.special, count)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/keyinput/keyparser.py", line 44, in execute
        self._commandrunner.run(cmdstr, count)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/commands/runners.py", line 275, in run
        result.cmd.run(self._win_id, args, count=count)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/commands/command.py", line 525, in run
        self.handler(*posargs, **kwargs)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/commands.py", line 1600, in open_editor
        tab.elements.find_focused(self._open_editor_cb)
      File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/webkit/webkittab.py", line 589, in find_focused
        callback(webkitelem.WebKitElement(elem, tab=self._tab))
      File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/commands.py", line 1580, in _open_editor_cb
        text = elem.value()
      File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/webkit/webkitelem.py", line 116, in value
        assert isinstance(val, (int, float, str)), val
    AssertionError: None
2017-05-29 16:56:36 +02:00
Florian Bruhin
7186dcb98f Send crash reports to private pastebin
Fixes #481
2017-05-29 09:20:10 +02:00
Florian Bruhin
b32223acc7 Only inherit private mode when window is set
Otherwise, everything calling _open in a private window (like :quickmark-load)
will open a new window.
2017-05-29 06:37:28 +02:00
pyup-bot
615b027fad Update hypothesis from 3.11.0 to 3.11.1 2017-05-28 16:24:59 +02:00
Florian Bruhin
4f6474dc69 Add new requests requirements 2017-05-28 11:30:28 +02:00
Florian Bruhin
f273939521 Merge commit '9e3847863868e780b5a87975254959731c9ac2fb' into pyup-bot/pyup-update-requests-2.14.2-to-2.16.5 2017-05-28 11:25:12 +02:00
Florian Bruhin
8bd6974042 Open a window with an empty session
With general -> save-session on and only private windows open, we can easily get
a session file with "windows: []" in it. If we loaded such a file, we got no
windows at all when qutebrowser started.

Fixes #2664
2017-05-28 11:15:51 +02:00
Florian Bruhin
beb731c04c Move signal connections around 2017-05-28 10:54:16 +02:00
Florian Bruhin
06e754a632 Track HTML fullscreen per-tab
We now automatically get out of fullscreen when switching away from a
fullscreened tab. This also means we can't get into a situation where we can't
leave fullscreen anymore.

Fixes #2379.
2017-05-28 10:51:14 +02:00
pyup-bot
9e38478638 Update requests from 2.14.2 to 2.16.5 2017-05-28 09:52:02 +02:00
pyup-bot
3014a5207a Update requests from 2.14.2 to 2.16.5 2017-05-28 09:52:00 +02:00
pyup-bot
0106036e9e Update requests from 2.14.2 to 2.16.5 2017-05-28 09:51:59 +02:00
Florian Bruhin
a18ebd52a9 Rename TabWidget methods 2017-05-26 18:39:35 +02:00
Florian Bruhin
75409966a7 pyinstaller: Exclude tkinter 2017-05-24 21:53:53 +02:00
Florian Bruhin
54a4a087d4 nsis: Use solid lzma compressor
File sizes, 32 bit:
- default: 64 MB
- lzma: 50 MB
- lzma solid: 47 MB

64 bit:
- default: 75 MB
- lzma: 58 MB
- lzma solid: 55 MB

Between lzma and lzma solid, installation speed doesn't seem to vary much, so
let's go for the smallest.
2017-05-24 21:31:18 +02:00
Florian Bruhin
464eb29704 Set PATH in build_release.py when calling tox
On Windows, we need to have the proper Python folder in PATH when using PyQt5,
so it can load python3.dll properly.
2017-05-24 20:52:57 +02:00
Florian Bruhin
1adcf28e31 build_release: Adjust Windows Python paths 2017-05-24 13:30:11 +02:00
Florian Bruhin
ee320ade21 Regenerate authors 2017-05-24 08:40:20 +02:00
Florian Bruhin
b06599b2c9 Merge branch 'pyup-bot/pyup-update-hypothesis-3.10.0-to-3.11.0' 2017-05-24 08:39:09 +02:00
Florian Bruhin
52f077a780 Merge commit 'baa46aa7c1e54c5007ec35daf015225e425d0acd' 2017-05-24 08:39:09 +02:00
Florian Bruhin
49d7c44e6d Merge commit 'baa46aa7c1e54c5007ec35daf015225e425d0acd' into pyup-bot/pyup-update-hypothesis-3.10.0-to-3.11.0 2017-05-24 08:38:52 +02:00
Florian Bruhin
4e48f878ba build_release: Call tox with -v 2017-05-24 08:37:06 +02:00
Florian Bruhin
b811b9e380 Run update_3rdparty correctly from build_release 2017-05-24 08:37:06 +02:00
Florian Bruhin
e012b738f7 Add qutebrowser.nsi to MANIFEST.in 2017-05-24 08:37:06 +02:00
Florian Bruhin
59760b58d9 Add windows installers to build_release 2017-05-24 08:37:06 +02:00
Florian Bruhin
b6b78ba5eb Fix up NSIS paths 2017-05-24 08:37:06 +02:00
Florian Bruhin
86a61ba59a Remove nsis subfolder 2017-05-24 08:37:06 +02:00
Florian Bruhin
95d56bfc85 nsis: Use proper folders 2017-05-24 08:37:06 +02:00
Florian Bruhin
4879b48afe Merge nsis files into one 2017-05-24 08:37:06 +02:00
Link
bbd33d24a3 Initial nsis install script 2017-05-24 08:37:06 +02:00
pyup-bot
baa46aa7c1 Update hypothesis from 3.10.0 to 3.11.0 2017-05-24 02:24:52 +02:00
Florian Bruhin
681ce601e3 Add tor to FAQ 2017-05-23 22:23:15 +02:00
Florian Bruhin
e96f085f8d Merge commit '38ca583084e89de0da35cb1b626d21b051ea2c70' 2017-05-23 17:43:01 +02:00
Florian Bruhin
ffb4bb5f7c Improve chrome:// URL docs 2017-05-23 17:28:42 +02:00
Florian Bruhin
bc8e176a70 Update authors 2017-05-23 17:22:20 +02:00
Florian Bruhin
8b7cdb5d15 Merge commit 'a1e1e90ec916bcff0bf4fd5500fe80408f860f8b' 2017-05-23 17:22:08 +02:00
Florian Bruhin
70a28ed810 Update authors 2017-05-23 17:19:10 +02:00
Florian Bruhin
af1e1d9239 Merge commit 'c814ced7b35968cfdeb6284cc79168bfffed7c85' 2017-05-23 17:18:55 +02:00
Florian Bruhin
0f3a17ae88 Fix raw string prefix 2017-05-23 10:09:06 +02:00
Florian Bruhin
ea2fbc427a tests: Use match= for pytest.raises 2017-05-23 09:36:00 +02:00
Florian Bruhin
af7923de4d tests: Use pytest.param 2017-05-23 08:08:46 +02:00
Florian Bruhin
18a761369b requirements: Update pytest-warnings
It's been integrated to pytest core with 3.1
2017-05-23 06:14:32 +02:00
Florian Bruhin
7da6b55767 Merge commit 'aab90f015bbb4d5f406ce37e58b8b557284bb3c2' into pyup-bot/pyup-update-pytest-3.0.7-to-3.1.0 2017-05-23 06:13:08 +02:00
pyup-bot
aab90f015b Update pytest from 3.0.7 to 3.1.0 2017-05-23 05:18:50 +02:00
pyup-bot
a83c18f2c9 Update hypothesis from 3.9.1 to 3.10.0 2017-05-22 17:54:50 +02:00
pyup-bot
10e5aa9e2a Update hypothesis from 3.9.0 to 3.9.1 2017-05-22 11:09:50 +02:00
Florian Bruhin
4684ce8f0c Update changelog 2017-05-22 08:22:08 +02:00
Florian Bruhin
c32c01ffc0 Merge commit '419793c0b9ff4f293babea7623dcaf4787bbaa35' 2017-05-22 07:55:44 +02:00
Jay Kamat
419793c0b9 Misc cleanup and documentation update 2017-05-21 22:42:51 -07:00
Jay Kamat
00f001729b Fix undo with pinned tabs
Add tests for undo with a pinned tab
Add tests for clone with a pinned tab
2017-05-21 21:03:33 -07:00
Jay Kamat
2a961c3951 Clean up pinned status to a centralized location
- Add support for :tab-clone with pinned tabs

Now tabbed_browser.set_tab_pinned can be called independently.
2017-05-21 19:49:10 -07:00
pyup-bot
a26011c62d Update pytest-warnings from 0.2.0 to 0.3.0 2017-05-21 17:13:48 +02:00
Florian Bruhin
64e7e027d8 Merge commit '4096defd134c44449bcc1c62b39e58f2fb0c25d1' into pyup-bot/pyup-update-hypothesis-3.8.5-to-3.9.0 2017-05-21 16:20:57 +02:00
Florian Bruhin
28c651067d Remove crowdfunding notes 2017-05-20 23:30:36 +02:00
Florian Bruhin
aa8e6c8d17 Add parsed distribution to version info
Fixes #2369
2017-05-20 23:26:00 +02:00
Florian Bruhin
fe145b66c1 Add a version.distribution()
See #2369
2017-05-20 23:26:00 +02:00
pyup-bot
4096defd13 Update hypothesis from 3.8.5 to 3.9.0 2017-05-19 17:54:45 +02:00
Florian Bruhin
964b06bf7e Fix shadowed import 2017-05-19 09:26:48 +02:00
Florian Bruhin
802eb51891 Update docs 2017-05-19 08:59:34 +02:00
Florian Bruhin
f66c1a0e44 Merge commit '3d9729839d6d9b5ee5d38afdf6ddf410dfca2027' into abbradar/pac-fix 2017-05-19 08:36:39 +02:00
Florian Bruhin
c4fb2bc609 Fix URL/renderer crash tests with Qt 5.9
The behavior in Qt changed there (in a good way), so we need to adjust the tests
accordingly.

Fixes #2514
2017-05-19 08:10:17 +02:00
Nikolay Amiantov
3d9729839d Fix crash on PAC evaluation error 2017-05-18 16:54:49 +03:00
Florian Bruhin
f67cf17055 Hopefully fix pylint on AppVeyor... 2017-05-17 22:47:17 +02:00
Florian Bruhin
edd10aac56 pylint: Add more stuff to known-standard-library 2017-05-17 22:14:17 +02:00
Florian Bruhin
499f5df2a9 ci: Use Python 3.6 everywhere 2017-05-17 21:40:24 +02:00
Florian Bruhin
f90df52c6a Update changelog 2017-05-17 21:32:59 +02:00
Florian Bruhin
e3f5e8ca9a Disable local storage test for now
It also seems to run unstable on Windows (AppVeyor), so we probably need to wait
for qutewm to run it.
2017-05-17 20:38:30 +02:00
Florian Bruhin
00a7a0cee6 Reorganize pylint config
This removes various stuff we don't need anymoe, and also re-enables and fixes
the import order check.
2017-05-17 20:20:12 +02:00
Florian Bruhin
12520bf4ba Install PyQt from PyPI for pylint
This means we can be sure to have QtWebEngine available and won't have QtWebKit.
2017-05-17 19:08:59 +02:00
Florian Bruhin
608ac89f06 Fix lint 2017-05-17 14:32:13 +02:00
Florian Bruhin
6473d64e40 Merge commit '20e8ce687f04b9cae702a5446b32a5ae3e0351c5' into pyup-bot/pyup-update-hypothesis-3.8.3-to-3.8.5 2017-05-17 13:50:07 +02:00
Florian Bruhin
a4ddc9706a tox: Also use $PYTHON for pylint 2017-05-17 13:48:31 +02:00
Florian Bruhin
dd15b4b953 Fix local storage test
Looks like it needs a window manager to run properly...
2017-05-17 13:38:21 +02:00
Florian Bruhin
c5957bc9d0 Exclude pdfjs from build packages for now
It only makes things bigger, and currently pdfjs doesn't work on QtWebEngine
anyways.
2017-05-17 11:42:58 +02:00
Florian Bruhin
9898d80625 Remove legacy cx_Freeze code
This also removes frozen tests for now. They should be readded at some point...
2017-05-17 11:31:14 +02:00
Florian Bruhin
e955540f71 build_release: More fixes 2017-05-17 11:10:36 +02:00
Florian Bruhin
47bf261994 build_release: Different PyInstaller workaround 2017-05-17 11:10:32 +02:00
Florian Bruhin
71b5d83e19 build_release: Various fixes 2017-05-17 11:10:20 +02:00
Florian Bruhin
dc947bf9a9 build_release: Python version adjustments 2017-05-17 11:09:22 +02:00
Florian Bruhin
49a328727e build_release: Add Windows patching for PyInstaller 2017-05-17 11:09:22 +02:00
Florian Bruhin
9816de9e8d build_release: Initial changes for PyInstaller 2017-05-17 11:06:06 +02:00
Florian Bruhin
70e2963432 build_release: Adjust repo name 2017-05-17 11:05:27 +02:00
Florian Bruhin
68bb0f557f Switch to xoviat pyinstaller branch 2017-05-17 11:05:27 +02:00
pyup-bot
20e8ce687f Update hypothesis from 3.8.3 to 3.8.5 2017-05-17 10:54:42 +02:00
Florian Bruhin
e0ff2d98fe Test for private browsing differently
In a48ea597d0 we fixed settings in private
QtWebEngine windows.

However, this means we also enable local storage for private windows, which was
disabled in QtWebEngine by default:

4ef5831a39 (diff-44ac7d27348388501944f6a8e2e67d8dR207)

It should be safe to enable it, as we get the same behavior as in Chromium, i.e.
a working local storage which entirely lives in RAM.

This also makes those tests work on QtWebKit-NG, presumably because private
browsing for cookies is implemented there.

It also adds a test to at least check whether local storage is isolated from
non-private tabs. I tried writing a test which ensures nothing lands on the hard
disk, but due to QTBUG-52121 this might not happen at all:

https://bugreports.qt.io/browse/QTBUG-52121
2017-05-17 09:42:28 +02:00
Florian Bruhin
a48ea597d0 Set websettings on each profile's setting object
Turns out QWebEngineSettings.globalSettings() only sets things on the default
profile. We now get everything from the default profile settings, but set it on
both the default and the private profile.

Fixes #2638

(cherry picked from commit b11a4388cd10b6ff2fd917fca689ebdc50d581ae)
2017-05-17 06:31:51 +02:00
Jay Kamat
5e3c68530a Regenerate documentation 2017-05-16 21:03:33 -07:00
Jay Kamat
1142a19de9 Add (pinned) keyword to 'following tabs open' tests 2017-05-16 20:16:43 -07:00
Florian Bruhin
00083ad825 Merge commit '7b204c4ec7931ba8da5f685b29352413ec25f194' into pyup-bot/pyup-update-flask-0.12.1-to-0.12.2 2017-05-16 16:51:50 +02:00
Florian Bruhin
8428d72005 Merge commit 'c2ca8e48f58fcf6fe6758f8e206d95bacddb8c58' into pyup-bot/pyup-update-werkzeug-0.12.1-to-0.12.2 2017-05-16 16:50:31 +02:00
Florian Bruhin
407537dbe6 tests: Wait until window is closed after :close
If we don't wait here, we might end up running the subsequent commands (like
:command-history-prev) on the old window while it's still closing, causing an
exception at least on AppVeyor:

    Traceback (most recent call last):
      File "C:\projects\qutebrowser\qutebrowser\app.py", line 110, in <lambda>
        target_arg=target_arg))
      File "C:\projects\qutebrowser\qutebrowser\app.py", line 265, in process_pos_args
        win_id = mainwindow.get_window(via_ipc, force_tab=True)
      File "C:\projects\qutebrowser\qutebrowser\mainwindow\mainwindow.py", line 89, in get_window
        window.setWindowState(window.windowState() & ~Qt.WindowMinimized)
    RuntimeError: wrapped C/C++ object of type MainWindow has been deleted
2017-05-16 15:46:20 +02:00
Florian Bruhin
9408babef5 Also remove test for removed assertion 2017-05-16 12:56:25 +02:00
Florian Bruhin
766a1ebb6d Remove wrong private browsing assertion
This tried to assert that we never create a DiskCache object when private
browsing is turned on. However, when initializing, we still create a global
DiskCache, so this will hit when qutebrowser is started with private browsing
turned on via the config.

We could just not create the DiskCache at all when started in private browsing
mode, however we might still need it later when opening a non-private window.
2017-05-16 11:33:52 +02:00
Florian Bruhin
27aa40428e Also make DownloadManager NAM private if private browsing is on
There's only one global DownloadManager with its own NAM (for downloads not
associated with a page). We can't really decide whether that should be private
or not, so as a best-effort approximation we simply make it private if private
browsing was turned on when starting qutebrowser.
2017-05-16 11:32:35 +02:00
pyup-bot
c2ca8e48f5 Update werkzeug from 0.12.1 to 0.12.2 2017-05-16 09:12:19 +02:00
pyup-bot
7b204c4ec7 Update flask from 0.12.1 to 0.12.2 2017-05-16 09:12:15 +02:00
Florian Bruhin
89dc8185b9 Fix lint 2017-05-16 09:08:59 +02:00
Florian Bruhin
1fcce6d87c Change how error page retries work
A simple reload won't work when e.g. the renderer process crashed, so let's try
this instead.

Also, searchFor seemed to be unused.
2017-05-16 07:51:37 +02:00
Florian Bruhin
a4021e8e7a Show error page for renderer process crashes on 5.9
Fixes #2291
2017-05-16 07:50:26 +02:00
Florian Bruhin
bdf56e63dd Fix long line 2017-05-16 07:31:02 +02:00
Florian Bruhin
37b3ed0ca9 Update changelog 2017-05-16 07:14:03 +02:00
Florian Bruhin
d0dd1644af Set user agent correctly on QtWebEngine 2017-05-16 06:46:45 +02:00
Florian Bruhin
086139110d Merge branch 'new-private-browsing' 2017-05-16 06:32:15 +02:00
Florian Bruhin
adb924a758 Use -p for :save-session --with-private 2017-05-16 06:28:21 +02:00
Florian Bruhin
658abf7b2b Fix coverage on old Qt versions 2017-05-15 13:39:49 +02:00
Florian Bruhin
51163f5e12 Recompile requirements 2017-05-15 11:35:34 +02:00
Florian Bruhin
991b3123d7 check_coverage: Add qutebrowser/ to filter list
For coverage 4.4 we removed qutebrowser/ from filenames, so we need to re-add it
here so the filter still works correctly.
2017-05-15 11:32:41 +02:00
Florian Bruhin
e13a5c0f17 Use a list for stylesheet flags
If we simply use sorted() on a dict, we define insert before private-command,
which means the statusbar isn't going to be green when in insert mode while
private browsing.
2017-05-15 11:07:43 +02:00
Florian Bruhin
3cdcc34d1d Update private-browsing option description 2017-05-15 11:07:43 +02:00
Florian Bruhin
c4307c9f03 Fix lint 2017-05-15 11:07:43 +02:00
Florian Bruhin
3f8b9fb1a5 tests: Improve matching of exceptions to show verbose output
In some situations we can get a TypeError without a stack
2017-05-15 11:07:43 +02:00
Florian Bruhin
f6fc2666ce Generate stylesheet for statusbar 2017-05-15 11:07:43 +02:00
Florian Bruhin
73ca884d24 Add a setting for private command mode color
This also refactors how color properties are handled in StatusBar.
2017-05-15 11:07:43 +02:00
Florian Bruhin
3c3f695af4 Fix things pointed out in reviews 2017-05-15 11:07:43 +02:00
Florian Bruhin
6ee382ef30 Sort windows when saving sessions
This should help with flaky tests when the window order changes
2017-05-15 11:02:29 +02:00
Florian Bruhin
510b437916 Update docs 2017-05-15 11:02:29 +02:00
Florian Bruhin
8993667479 Remove unused imports 2017-05-15 11:02:29 +02:00
Florian Bruhin
c3ac3ccdee Add tests for new private browsing 2017-05-15 11:02:29 +02:00
Florian Bruhin
eda95d7926 Simplify window/private distinction in commands.py 2017-05-15 11:02:29 +02:00
Florian Bruhin
cde36f34b0 Remove QtWebKit-NG warnings
The next release will support private browsing, and we can't easily check the
version somehow.
2017-05-15 11:02:29 +02:00
Florian Bruhin
9805b43c85 Handle private browsing in sessions 2017-05-15 11:02:29 +02:00
Florian Bruhin
f907b6b6b0 Have an isolated command history for private windows 2017-05-15 11:02:26 +02:00
Florian Bruhin
157a0af908 Hopefully fix failing history test on old Qt 2017-05-15 10:29:13 +02:00
Florian Bruhin
56144d6c3d Merge commit '7688f263986f97073d5bd253a506b4d3bbac1759' into pyup-bot/pyup-update-coverage-4.4-to-4.4.1 2017-05-15 09:22:07 +02:00
Florian Bruhin
dd675c4e8d Set title for :view-source pages 2017-05-15 09:16:24 +02:00
Florian Bruhin
5b1d35bef9 Don't add data: URLs to history 2017-05-15 09:04:16 +02:00
Florian Bruhin
920dde4a68 Don't set an URL for :view-source tabs
Otherwise the page URL gets added to the history again with QtWebKit.
2017-05-15 09:03:45 +02:00
pyup-bot
7688f26398 Update coverage from 4.4 to 4.4.1 2017-05-15 08:48:42 +02:00
pyup-bot
b3a509f856 Update coverage from 4.4 to 4.4.1 2017-05-15 08:48:40 +02:00
Florian Bruhin
f2d3d78b12 Update changelog 2017-05-15 08:22:04 +02:00
Jay Kamat
17169812be Misc cleanup and fixes 2017-05-14 00:21:51 -07:00
Florian Bruhin
5174ce6a83 Update authors 2017-05-13 15:55:43 +02:00
Matthias Lisin
c814ced7b3 Add Android UA 2017-05-13 15:05:54 +02:00
Anton Grensjö
47f391d38b Set explicit=False for :navigate --tab
Related to #2624
2017-05-13 04:16:49 +02:00
Jay Kamat
b526c9a2a9 Try to fix a pylint error 2017-05-12 18:38:06 -07:00
Jay Kamat
a5eb3e27f8 Fix some bugs in session saving test case 2017-05-12 17:48:38 -07:00
Jay Kamat
068e47e22c Fix a few style issues 2017-05-12 16:56:07 -07:00
Jay Kamat
1572be83be Add documentation for pinning 2017-05-12 13:28:53 -07:00
Florian Bruhin
273749cce8 Don't set explicit=True for :tab-clone/:view-source
Fixes #2624
2017-05-12 22:27:24 +02:00
Jay Kamat
2ae1bfc033 Keep pinned tabs in place rather than moving them. 2017-05-12 13:09:22 -07:00
Jay Kamat
3e3f4b4164 Add :tab-only tests for --force 2017-05-12 11:06:17 -07:00
Jay Kamat
66dfb1b1c9 Fix a bug with titles not being refreshed when pinning tabs 2017-05-12 09:53:25 -07:00
Florian Bruhin
65952ca290 Fix webkitelem tests 2017-05-12 13:57:33 +02:00
Florian Bruhin
17fdda6a5e Check for href attribute in WebElement.is_link
Fixes #2619
2017-05-12 12:59:25 +02:00
Florian Bruhin
9ab4549b9b requirements: Filter flake8-pep3101 1.1 2017-05-12 10:32:06 +02:00
Florian Bruhin
bd75507c90 Merge commit 'e238f32e7b40f6da9aa893150cd35368814fc403' into pyup-bot/pyup-update-flake8-deprecated-1.1-to-1.2 2017-05-12 10:30:09 +02:00
Florian Bruhin
0e72f2166d Merge commit 'dfc44f05c57885e7c6890318dbfb7204f4e07618' into pyup-bot/pyup-update-pytest-cov-2.5.0-to-2.5.1 2017-05-12 10:30:07 +02:00
Florian Bruhin
9e2aa65c02 Remove webelem.Group.prevnext
Apart from checking for buttons with an href attribute (which made no sense at
all and should never return any element) this was identical to
webelem.Group.links.
2017-05-12 09:41:12 +02:00
Florian Bruhin
203a5dff74 Get rid of webelem.FILTERS
There's actually no good reason to filter javascript links as we might want to
click them (or copy their URL) just like any other link - this fixes #2404.

With that being gone, we don't need FILTERS at all anymore, as we can check for
existence of the href attribute in the CSS selector instead.
2017-05-12 09:41:12 +02:00
pyup-bot
dfc44f05c5 Update pytest-cov from 2.5.0 to 2.5.1 2017-05-12 00:59:40 +02:00
pyup-bot
e238f32e7b Update flake8-deprecated from 1.1 to 1.2 2017-05-12 00:59:36 +02:00
Jay Kamat
21455cf0e7 Clean up pinned tab alert logic
should be a lot more reusable now
2017-05-11 15:37:52 -07:00
Jay Kamat
4c28487fd0 Warn user if pinned tab is closed via tab-only 2017-05-11 14:30:45 -07:00
Jay Kamat
cb654225fd Add a test case for loading/saving pinned tabs in sessions 2017-05-11 14:05:25 -07:00
Jay Kamat
3317834b36 Fix a bug where pinned tabs were occasionally miscounted
Example case: :tab-only. This should cover other cases, but currently those
cases (such as :tab-only) do NOT have a warning message when popping up.
2017-05-11 13:28:26 -07:00
Jay Kamat
725bafea54 Merge branch 'master' into jay/pintab 2017-05-10 23:51:33 -07:00
pyup-bot
d50a08d159 Update requests from 2.14.1 to 2.14.2 2017-05-10 19:08:32 +02:00
pyup-bot
140eb13677 Update requests from 2.14.1 to 2.14.2 2017-05-10 19:08:31 +02:00
pyup-bot
b2abf7a3aa Update requests from 2.14.1 to 2.14.2 2017-05-10 19:08:29 +02:00
Florian Bruhin
c6e31391de Fix most tests/lint 2017-05-10 09:19:24 +02:00
Florian Bruhin
f4d3f97cb7 Implement private browsing for QtWebEngine 2017-05-10 09:17:54 +02:00
Florian Bruhin
1c50377c0a Initial work on new private browsing 2017-05-10 07:00:21 +02:00
Florian Bruhin
1d4c9d3b3f Merge commit '661c0f7b7c74c23db0a8ed2dfa111a711c5f8771' into pyup-bot/pyup-update-pytest-cov-2.4.0-to-2.5.0 2017-05-10 06:52:20 +02:00
Florian Bruhin
5e76810659 Merge commit '1973e61424efb124f453ce0894d1c8b3e5ea99c3' into pyup-bot/pyup-update-hypothesis-3.8.2-to-3.8.3 2017-05-10 06:52:18 +02:00
pyup-bot
661c0f7b7c Update pytest-cov from 2.4.0 to 2.5.0 2017-05-10 00:08:34 +02:00
pyup-bot
1973e61424 Update hypothesis from 3.8.2 to 3.8.3 2017-05-10 00:08:30 +02:00
pyup-bot
3bd7e33c4a Update requests from 2.13.0 to 2.14.1 2017-05-09 22:16:27 +02:00
pyup-bot
a0a9c9d32e Update requests from 2.13.0 to 2.14.1 2017-05-09 22:16:25 +02:00
pyup-bot
56d42b6c82 Update requests from 2.13.0 to 2.14.1 2017-05-09 22:16:24 +02:00
Florian Bruhin
b91d4ee9c2 Clean up :debug-webaction 2017-05-09 22:02:30 +02:00
Florian Bruhin
822623f2ed Finally update copyrights... 2017-05-09 21:37:03 +02:00
Florian Bruhin
905032924a Remove search_displayed initialization in subclasses
We set this in BrowserTab anyways, and the value in WebKitTab was wrong.
2017-05-09 17:58:28 +02:00
Florian Bruhin
4b5e528d05 Add AbstractTab.key_press 2017-05-09 17:56:07 +02:00
Florian Bruhin
76fa126133 Simplify debug string 2017-05-09 17:55:51 +02:00
Florian Bruhin
e3eda28d88 Update docstrings 2017-05-09 17:52:13 +02:00
Florian Bruhin
5f2fb2c4fc Update docs 2017-05-09 17:48:40 +02:00
Jay Kamat
e10d636ca0 Fix a few small issues
- Remove an unused warnings
- Reverse if statement arguments to simplify logic
2017-05-09 08:08:05 -07:00
Jay Kamat
a3d41c0467 Refactor search method of AbstractBrowserTab into a field 2017-05-09 00:24:13 -07:00
Jay Kamat
02f79c2990 Add tests for manual selection 2017-05-09 00:11:25 -07:00
Jay Kamat
d1aac9e9e9 Add docstrings to key_press methods 2017-05-08 23:43:21 -07:00
Jay Kamat
5bdd291d28 Refactor key_press into _repeated_key_press
Also split off generic key pressing ability from WebKitScroller to WebKitTab
2017-05-08 23:11:50 -07:00
Jay Kamat
63cffaf558 Refactor _key_press from WebEngineScroller to WebEngineTab 2017-05-08 22:49:14 -07:00
Jay Kamat
5ba81e3611 Add tests for follow_selected 2017-05-08 22:32:53 -07:00
Jay Kamat
c9953b9f0d Add support for follow_selected via fake-clicks 2017-05-08 22:31:29 -07:00
Jay Kamat
e07a1045a8 Add is_link method to webelem 2017-05-08 22:00:11 -07:00
Florian Bruhin
6c3f29d570 Merge commit '2b0fc0f52efccd0004b2cd8f90f930852947f403' into pyup-bot/pyup-update-coverage-4.3.4-to-4.4 2017-05-09 06:23:05 +02:00
Florian Bruhin
27bed81353 Merge commit '7a3651426f0152c6b23ed4f83bab0eab2e763d91' into pyup-bot/pyup-update-beautifulsoup4-4.5.3-to-4.6.0 2017-05-09 06:23:03 +02:00
Florian Bruhin
af18b208bb Merge commit '00c48427bcee63921705f85251d71795dab980bd' into pyup-bot/pyup-update-lazy-object-proxy-1.3.0-to-1.3.1 2017-05-09 06:23:00 +02:00
Florian Bruhin
9db92de2d5 Add a no cover pragma for certificate error hashing 2017-05-09 06:15:21 +02:00
Florian Bruhin
8052249b1b Make check_coverage.py work with coverage 4.4
With coverage 4.4, the source name (qutebrowser/) is not added to the filename
anymore. To adjust for that, we remove qutebrowser/ from all paths, and also
make sure to remove it from what coverage returns (in case someone is running an
older version).
2017-05-09 06:13:35 +02:00
pyup-bot
2b0fc0f52e Update coverage from 4.3.4 to 4.4 2017-05-08 07:26:27 +02:00
pyup-bot
ee2a6ae6f0 Update coverage from 4.3.4 to 4.4 2017-05-08 07:26:25 +02:00
pyup-bot
7a3651426f Update beautifulsoup4 from 4.5.3 to 4.6.0 2017-05-07 16:42:20 +02:00
pyup-bot
00c48427bc Update lazy-object-proxy from 1.3.0 to 1.3.1 2017-05-05 15:51:20 +02:00
pyup-bot
2beba920e7 Update lazy-object-proxy from 1.3.0 to 1.3.1 2017-05-05 15:51:18 +02:00
pyup-bot
88545dec4d Update lazy-object-proxy from 1.2.2 to 1.3.0 2017-05-04 08:36:26 +02:00
pyup-bot
caa3be2277 Update lazy-object-proxy from 1.2.2 to 1.3.0 2017-05-04 08:36:25 +02:00
Florian Bruhin
789aebd742 Merge commit '120379dd217d8daaa6b48cb21c8cb3de7679bbec' into rcorre/benchmark_history 2017-05-03 23:15:36 +02:00
Florian Bruhin
eab7c79cf7 Merge commit '3b0bb6a831791c22a77f25aa2f3223c24e6ba628' into pyup-bot/pyup-update-cheroot-5.4.0-to-5.5.0 2017-05-03 23:15:26 +02:00
Florian Bruhin
90b0af97ce Improve serialization crash check
It now works correctly with view-source URLs and is disabled on Qt 5.9.

Fixes #2289
See #2458
2017-05-03 23:15:17 +02:00
Florian Bruhin
ea2d5e97e2 Disable serialization crash check on Qt 5.9 2017-05-03 21:31:09 +02:00
Florian Bruhin
ebf3d208f6 Adjust Qt 5.8.1 check
There's never going to be a 5.8.1
2017-05-03 21:25:00 +02:00
Florian Bruhin
a320aa5ef7 Disable renderer process crash workaround on Qt 5.9 2017-05-03 21:24:25 +02:00
Florian Bruhin
2a4af0666b Regenerate authors 2017-05-03 18:36:48 +02:00
Ryan Roden-Corrent
120379dd21 Benchmark url completion.
This benchmark simulates what I expect to be the most common use-case for url
completion: opening completion and entering several letters.
2017-05-03 07:43:02 -04:00
Florian Bruhin
a77cb44723 Block all request methods in host blocker 2017-05-03 08:42:37 +02:00
pyup-bot
3b0bb6a831 Update cheroot from 5.4.0 to 5.5.0 2017-05-02 11:43:35 +02:00
Florian Bruhin
7c6981e512 Remove unused imports 2017-05-02 10:41:51 +02:00
Florian Bruhin
d5c5d09b18 Hopefully stabilize test_version
When using QuteProcess here, we fight with it over who can read the output.
Just use a raw QProcess instead.
2017-05-02 09:12:06 +02:00
Florian Bruhin
7b4ab901e9 tests: Fix Chromium message matching 2017-05-02 08:24:57 +02:00
Florian Bruhin
d8e134c5f0 Merge commit '64a4e33caa539b751acfc7e0eb76c871e8ab423d' into pyup-bot/pyup-update-flake8-tuple-0.2.12-to-0.2.13 2017-05-02 08:22:43 +02:00
Florian Bruhin
55db8719f2 Merge commit '6ae6df9d74b9d94f56489b5d6a4586995aeda340' into stevepeak/patch-1 2017-05-02 08:22:37 +02:00
Florian Bruhin
2fb59958a6 Merge commit 'fe02267de2f9bc164cb265c357770d8f56c68554' into pyup-bot/pyup-update-pytest-bdd-2.18.1-to-2.18.2 2017-05-02 08:22:32 +02:00
Florian Bruhin
64e144f3eb Make text selectable in prompts 2017-05-01 13:52:46 +02:00
pyup-bot
fe02267de2 Update pytest-bdd from 2.18.1 to 2.18.2 2017-05-01 12:43:14 +02:00
Steve Peak
6ae6df9d74 Update codecov.yml 2017-04-30 14:55:35 -04:00
pyup-bot
64a4e33caa Update flake8-tuple from 0.2.12 to 0.2.13 2017-04-30 12:29:12 +02:00
Florian Bruhin
6e0d138d23 flake8 requirements: Pin flake8-docstrings to < 1.1.0
Closes #2593
2017-04-29 13:45:14 +02:00
Florian Bruhin
5bbd16c92a Fix qWebKitVersion issues 2017-04-28 22:59:24 +02:00
Florian Bruhin
bffdea6719 Read qWebKitVersion in qtutils.is_webkit_ng.
This means we need to try and import qWebKitVersion in qtutils, but better there
than at every place which calls it.
2017-04-28 21:36:02 +02:00
Florian Bruhin
8101fe99a8 Fix starting with Python 2
Fixes #2567
2017-04-28 20:51:38 +02:00
Florian Bruhin
a5b1c293a4 Ignore comment position with eslint 2017-04-28 20:29:20 +02:00
Florian Bruhin
0a3e20f5ab Merge commit '26b4d13c6faf6217bb116e15c01eec37c10dd976' into pyup-bot/pyup-update-setuptools-35.0.1-to-35.0.2 2017-04-28 19:44:59 +02:00
Florian Bruhin
9f942cb9a8 Merge commit '11383169d83f1ff14d2df40e6963221e46ab29d1' into pyup-bot/pyup-update-codecov-2.0.8-to-2.0.9 2017-04-28 19:44:57 +02:00
Florian Bruhin
421aa0d319 Also try harder to get text content 2017-04-28 19:11:02 +02:00
Florian Bruhin
76ec465f67 Allow to set cookies-store at runtime with Qt 5.9
Fixes #2588
2017-04-28 17:40:43 +02:00
Florian Bruhin
c8090b5388 Don't wait for click message in webelem tests
Looks like we get this sometimes:

----> Waiting for 'Clicked non-editable element!' in the log
14:02:14.976 DEBUG    webview    webkittab:find_at_pos:618 Hit test result element is null!
14:02:14.976 DEBUG    mouse      mouse:_mousepress_insertmode_cb:149 Got None element, scheduling check on mouse release
14:02:14.977 DEBUG    mouse      webview:mousePressEvent:299 Normal click, setting normal target
14:02:14.978 DEBUG    mouse      mouse:mouserelease_insertmode_cb:173 Element vanished!
2017-04-28 17:29:19 +02:00
pyup-bot
11383169d8 Update codecov from 2.0.8 to 2.0.9 2017-04-28 17:27:11 +02:00
Florian Bruhin
5ed870e0c6 Fix lint 2017-04-28 16:29:44 +02:00
Florian Bruhin
20da495376 Add missing file 2017-04-28 15:22:29 +02:00
Florian Bruhin
a2c8e093f4 Move webelement checks to javascript.feature 2017-04-28 15:16:36 +02:00
Florian Bruhin
6458c692cb Improve JS value type checks 2017-04-28 15:15:32 +02:00
Florian Bruhin
571f0c4486 Loosen JS value type check 2017-04-28 14:57:14 +02:00
Florian Bruhin
0c653c4703 Handle elem.className in webelem.js 2017-04-28 14:48:30 +02:00
Florian Bruhin
513f83d446 Try harder to get tag name from element
This could happen for any of the attributes, but for tagName this actually
happens in the wild... Since elem.tagName is equal to elem.nodeName we just try
to use this.

Fixes #2569
2017-04-28 14:48:30 +02:00
Florian Bruhin
06e317ac53 Do type checks on values we get from JS 2017-04-28 14:48:30 +02:00
Florian Bruhin
4f92fe6895 Add an assert for tag_name we get from JS
This should help tracking down #2569 once we get another report about it.
2017-04-28 10:33:57 +02:00
pyup-bot
26b4d13c6f Update setuptools from 35.0.1 to 35.0.2 2017-04-27 22:07:03 +02:00
Florian Bruhin
7b283cd58e Merge branch 'haasn/favicon-scale' 2017-04-27 21:15:09 +02:00
Florian Bruhin
d8bfa6d6b7 Merge commit '6549fd84ce461d3098c13818219df4e4bfd6b444' 2017-04-27 21:15:09 +02:00
Florian Bruhin
f9055dc1e4 Update changelog 2017-04-27 21:14:28 +02:00
Florian Bruhin
5823af0b7b Merge commit '6549fd84ce461d3098c13818219df4e4bfd6b444' into haasn/favicon-scale 2017-04-27 21:13:17 +02:00
Florian Bruhin
0efbd085b0 Merge commit 'c12347189fca26261af7dcdce121e51c170b521d' into pyup-bot/pyup-update-colorama-0.3.8-to-0.3.9 2017-04-27 21:12:21 +02:00
Florian Bruhin
44e6b9ac54 Merge commit '0e14117fdad0442520c4e1fe64231b447306cbc7' into pyup-bot/pyup-update-codecov-2.0.7-to-2.0.8 2017-04-27 21:12:18 +02:00
Florian Bruhin
d62ebdb926 Make most of search BDD tests work with QtWebEngine 2017-04-27 21:02:26 +02:00
Florian Bruhin
4cd977cab6 Fix zero handling in qflags_key 2017-04-27 20:14:51 +02:00
pyup-bot
0e14117fda Update codecov from 2.0.7 to 2.0.8 2017-04-27 18:27:03 +02:00
pyup-bot
c12347189f Update colorama from 0.3.8 to 0.3.9 2017-04-27 09:42:00 +02:00
Niklas Haas
6549fd84ce Add tabs->favicon-scale setting
This allows users to change the size of the favicon independently from
the size of the font/tab, in order to adjust the balance between
favicons and text. The drawing code is also adjusted to place the icon
relative to the text center, rather than the text top.

Works as expected even for values of 0.0 (which is equivalent to hiding
the favicon completely).

Closes #2549.
2017-04-27 08:53:51 +02:00
Florian Bruhin
046401c489 Clean up search.feature 2017-04-27 08:20:55 +02:00
pyup-bot
38099c45bd Update hypothesis from 3.8.1 to 3.8.2 2017-04-26 21:48:21 +02:00
Florian Bruhin
b094f2d513 Merge branch 'pyup-bot/pyup-update-vulture-0.13-to-0.14' 2017-04-26 21:30:56 +02:00
Florian Bruhin
5e7e159ac7 Merge commit '9ef17d434ddc85c6cda4d08f00fef15b7904add1' 2017-04-26 21:30:56 +02:00
Florian Bruhin
9f8937fd80 Merge commit '9ef17d434ddc85c6cda4d08f00fef15b7904add1' into pyup-bot/pyup-update-vulture-0.13-to-0.14 2017-04-26 21:30:16 +02:00
pyup-bot
e252862f51 Update hypothesis from 3.8.0 to 3.8.1 2017-04-26 15:15:11 +02:00
pyup-bot
9ef17d434d Update vulture from 0.13 to 0.14 2017-04-26 10:32:43 +02:00
pyup-bot
b1d88b47c1 Update vulture from 0.13 to 0.14 2017-04-26 10:32:42 +02:00
Florian Bruhin
27057622ba Update authors 2017-04-26 08:56:41 +02:00
Florian Bruhin
4f444b870e Merge branch 'imransobir/hostname-in-history' 2017-04-26 08:54:39 +02:00
Florian Bruhin
95b866e4f4 Merge commit 'fe7d21dfbe0b9dabcb66eaa61c20a5d16c9e175c' 2017-04-26 08:54:39 +02:00
Florian Bruhin
abb82ce922 Merge branch 'pyup-bot/pyup-update-codecov-2.0.5-to-2.0.7' 2017-04-26 07:23:09 +02:00
Florian Bruhin
4bee5deacc Merge commit 'ab61fc57a98abcbfe6ac50622e9cbff25ad0325c' 2017-04-26 07:23:09 +02:00
Florian Bruhin
cbfb155a05 Merge commit 'ab61fc57a98abcbfe6ac50622e9cbff25ad0325c' into pyup-bot/pyup-update-codecov-2.0.5-to-2.0.7 2017-04-26 07:22:46 +02:00
Florian Bruhin
6a35797a2c Mention C++/JS in CONTRIBUTING 2017-04-25 22:57:39 +02:00
Florian Bruhin
70d7a56b11 Also set Fusion style for downloads and completion
This makes those UI elements look the same on different platforms/OS styles,
with the small drawback of overriding the context menu style.

This most likely fixes #80 (though I couldn't reproduce that on Windows 10).
2017-04-25 22:20:37 +02:00
Florian Bruhin
66eb330a0a Always base tabbar on Fusion style.
Fixes crashes with qt5ct.
Fixes #2477.
Fixes #1554.
2017-04-25 21:44:15 +02:00
Florian Bruhin
ca0e04fd0d Mention :open in issue template
See #2574
2017-04-25 18:41:00 +02:00
Florian Bruhin
1015badb8b Disable animation for completion view 2017-04-25 09:18:31 +02:00
Florian Bruhin
c3e6222296 Close the current tab when the tabbar itself is clicked 2017-04-25 06:59:51 +02:00
Florian Bruhin
3125b69d19 Fix no-cover pragma 2017-04-25 06:43:31 +02:00
pyup-bot
ab61fc57a9 Update codecov from 2.0.5 to 2.0.7 2017-04-25 00:34:15 +02:00
Florian Bruhin
111944fb65 Revert "Raise exception when a stylesheet is unparsable."
This reverts commit 0400945ac4.

See #2571
2017-04-24 23:16:10 +02:00
Imran Sobir
fe7d21dfbe Show hostname in non-javascript history page. 2017-04-24 15:30:01 +05:00
Florian Bruhin
11c026bf4c Reenable QtWebKit cache with Qt 5.9.
This was fixed here:
https://codereview.qt-project.org/#/c/190818/

See #2427
2017-04-24 12:27:00 +02:00
Florian Bruhin
1539301d64 Fix test coverage for statusbar.url 2017-04-24 08:41:29 +02:00
Florian Bruhin
bf4e343887 Merge commit '18082526f48afcef3fc574e1536ef282aa0cf5bd' into imransobir/hostname-in-history 2017-04-24 08:06:13 +02:00
Florian Bruhin
2120429960 Regenerate authors 2017-04-24 08:01:44 +02:00
Imran Sobir
18082526f4 Show hostname in history page. 2017-04-24 10:59:11 +05:00
Marcel Schilling
930b0f0818 typo fix (in comment) 2017-04-24 07:56:44 +02:00
Florian Bruhin
52f31ed15c Rename urlutils.safe_display_url to safe_display_string 2017-04-24 07:49:12 +02:00
Florian Bruhin
b632fe3285 Fix invalid URL handling in statusbar 2017-04-24 07:47:58 +02:00
Florian Bruhin
38294c1ca6 Merge commit '02cccb3673e7880fb1c507ca0f3e12e3ed954d6e' into pyup-bot/pyup-update-colorama-0.3.7-to-0.3.8 2017-04-24 07:15:56 +02:00
Florian Bruhin
a71b2e482e Merge commit '4220cfc34e85c10fc810a779a37eb1f3871e2ff4' into pyup-bot/pyup-update-hypothesis-3.7.3-to-3.8.0 2017-04-24 07:13:40 +02:00
Florian Bruhin
195d0ea207 Show Punycode URL for IDN pages in addition to decoded one
This helps when Unicode homographs are used for phishing purposes.
Fixes #2547
2017-04-24 06:58:41 +02:00
Florian Bruhin
beb661cdc7 Add xos4 Terminus to default monospace fonts 2017-04-23 23:11:12 +02:00
Florian Bruhin
a1de313aa3 Add qapp to test_proxy_from_url_pac 2017-04-23 23:10:29 +02:00
pyup-bot
4220cfc34e Update hypothesis from 3.7.3 to 3.8.0 2017-04-23 16:45:10 +02:00
pyup-bot
02cccb3673 Update colorama from 0.3.7 to 0.3.8 2017-04-23 11:48:10 +02:00
pyup-bot
616a764b6d Update hypothesis from 3.7.0 to 3.7.3 2017-04-21 20:00:01 +02:00
Florian Bruhin
1ebe0f2ce8 Regenerate docs 2017-04-20 04:40:03 +02:00
Florian Bruhin
c485b67fc0 Merge commit '6151b43c47f1ed0b8a6f0118037ba8bb93447f42' into rcorre/fix-qutescheme-bench 2017-04-20 04:39:45 +02:00
Florian Bruhin
0b118f4fd8 Blacklist pydocstyle >= 2.0.0
Closes #2539
2017-04-20 04:35:10 +02:00
pyup-bot
0c96a32366 Update setuptools from 35.0.0 to 35.0.1 2017-04-19 01:52:32 +02:00
Florian Bruhin
b82aada50b Fix highlights in crowdfunding note 2017-04-18 16:38:36 +02:00
Florian Bruhin
59a01b860f Add crowdfunding note to README/website 2017-04-18 16:36:14 +02:00
Ryan Roden-Corrent
6151b43c47 Fix qute_history benchmark.
This benchmark was running very quickly due to an improper setup.
The current history implementation expects that a newly inserted entry must
be more recent than any existing entries and sorts according to this
assumption.

The benchmark test inserts increasingly older entries, breaking this invariant.
When run in the benchmark, the qute://history/data implementation would
see an entry older than the oldest time in the time window and would
immediately return with a single "next" entry.

This patch inserts data in an order that mantains history's invariant and adds
a sanity-check at the end of the test. It does not check for the exact length
as not all entries will be within the time window. The length will be some
values <= 100000, the check just ensures that there is at least something more
than a "next" entry.

Before:
---------------------------------------------- benchmark: 1 tests ----------------------------------------------
Name (time in us)                  Min      Max    Mean  StdDev  Median     IQR  Outliers(*)  Rounds  Iterations
----------------------------------------------------------------------------------------------------------------
test_qute_history_benchmark     9.3050  21.9250  9.6143  0.2454  9.5880  0.1070      230;360    9930           1
----------------------------------------------------------------------------------------------------------------

After:
-------------------------------------------------- benchmark: 1 tests -------------------------------------------------
Name (time in ms)                    Min       Max      Mean  StdDev    Median     IQR  Outliers(*)  Rounds  Iterations
-----------------------------------------------------------------------------------------------------------------------
test_qute_history_benchmark     220.7040  223.1900  221.7536  1.1070  221.1939  1.8803          1;0       5           1
-----------------------------------------------------------------------------------------------------------------------
2017-04-17 12:15:49 -04:00
Florian Bruhin
db8b6d3e68 Add test for QNetworkReply.abort 2017-04-17 16:02:57 +02:00
Florian Bruhin
d60fc90ffd Merge commit '6fb48a5514f2f5dd6759ccfae0ea66ec8ad8297a' into pyup-bot/pyup-update-astroid-1.5.1-to-1.5.2 2017-04-17 16:01:36 +02:00
pyup-bot
00e4bf7640 Update pylint from 1.7.0 to 1.7.1 2017-04-17 15:20:23 +02:00
pyup-bot
6fb48a5514 Update astroid from 1.5.1 to 1.5.2 2017-04-17 14:00:24 +02:00
Florian Bruhin
ad9e82b91e Adjust bookmark tests 2017-04-16 21:13:01 +02:00
Florian Bruhin
9d2734ff62 Make sure host is valid for qute:// redirects 2017-04-16 13:15:15 +02:00
Florian Bruhin
c82bd83715 Implement RedirectNetworkReply.abort 2017-04-16 13:14:19 +02:00
Florian Bruhin
6deb079c2a Merge commit 'dd24039d64e72d4a79cda9ee3b7d0d0b19f146a4' into danieljakots/master 2017-04-16 13:09:09 +02:00
Florian Bruhin
d1d858b630 Merge commit '9050aac71e433dc82d087d47eb31f1f4e764d809' into pyup-bot/pyup-update-setuptools-34.4.1-to-35.0.0 2017-04-16 13:09:03 +02:00
Florian Bruhin
2d45257dcc Remove exclamation mark for bookmark messages 2017-04-16 13:08:15 +02:00
Florian Bruhin
842c2d297e Allow to set message clear timer to 0
Fixes #2527
2017-04-16 13:07:33 +02:00
pyup-bot
9050aac71e Update setuptools from 34.4.1 to 35.0.0 2017-04-15 17:37:14 +02:00
Daniel Jakots
dd24039d64 OpenBSD 6.1 is now released. Also prefer the package than the port. 2017-04-14 12:37:41 -04:00
Florian Bruhin
7c4e4a5818 Adjust flake8 config
Since we now ignore this on a per-file level for pylint, we need to do the
same for flake8 too.
2017-04-13 21:12:58 +02:00
Florian Bruhin
1d0f187fab Adjustments for new pylint version 2017-04-13 18:22:16 +02:00
Florian Bruhin
90e9850ad9 Merge commit '4511d042a1b0dc2ec3174716da8696dd6a87202c' into pyup-bot/pyup-update-astroid-1.4.9-to-1.5.1 2017-04-13 17:34:22 +02:00
pyup-bot
10b1c954b2 Update pylint from 1.6.5 to 1.7.0 2017-04-13 17:30:12 +02:00
pyup-bot
4511d042a1 Update astroid from 1.4.9 to 1.5.1 2017-04-13 17:30:03 +02:00
Florian Bruhin
4a480e6f5f Ignore Chromium NETLINK message 2017-04-12 13:24:10 +02:00
Florian Bruhin
fdaff02a58 Update docs 2017-04-12 12:43:38 +02:00
Fritz Reichwald
68c655bd9c Add period at end of docstring to make flake happy 2017-04-12 10:21:03 +02:00
Fritz Reichwald
b00c1dc906 Add docstring 2017-04-12 09:23:29 +02:00
Fritz Reichwald
ff767dd965 Add neccessary metadata to py script 2017-04-12 08:47:39 +02:00
Fritz Reichwald
c38dc95c23 Add posix to stdin test beacause the py script fails on windows 2017-04-12 07:59:40 +02:00
Fritz Reichwald
b784ddeddd Also test stdin close for detached start 2017-04-12 07:40:11 +02:00
Fritz Reichwald
590a9b4f78 Indent with spaces and minor changes 2017-04-12 07:32:40 +02:00
Fritz Reichwald
3d549bf607 Remove closeWriteChannel from detached start 2017-04-12 07:32:12 +02:00
Fritz Reichwald
424d0aec5a change test_stdinclose.py to stdinclose.py 2017-04-12 07:31:24 +02:00
Fritz Reichwald
bc7f8018c0 Close stdin after starting QProcess Fixes 2491 2017-04-12 06:56:38 +02:00
Fritz Reichwald
75f8d2a1d1 Test if stdin gets closed when starting QProcess 2017-04-12 06:54:39 +02:00
Florian Bruhin
c47da15bb1 Remove nargs=1 for --debug-flag
Otherwisse we get [['foo'], ['bar']] from argparse...
2017-04-11 21:26:23 +02:00
Florian Bruhin
20b17f3fb1 Improve --debug-flag error message 2017-04-11 21:21:07 +02:00
Florian Bruhin
13c5150e58 Update docs 2017-04-11 21:21:07 +02:00
Florian Bruhin
b966034250 Merge commit 'f31aead992e829cb15c4fbedbf816a23d2a916a7' into jswz72/master 2017-04-11 21:17:49 +02:00
pyup-bot
a4c3aaaf1d Update setuptools from 34.4.0 to 34.4.1 2017-04-10 18:34:47 +02:00
Florian Bruhin
b1e3add02e Update screenshots 2017-04-10 08:47:43 +02:00
Jacob Sword
f31aead992 Add default to --debug-flag 2017-04-09 23:34:33 -04:00
Jacob Sword
dcf8f29a67 Remove old --pdb-postmortem and --debug-exit flags 2017-04-09 10:43:40 -05:00
Jacob Sword
c0ac1bd79a Add 'dest' for '--debug-flag' 2017-04-09 10:34:51 -05:00
Florian Bruhin
fc37223d1b Regenerate docs properly for qute:help test 2017-04-09 11:36:13 +02:00
Jacob Sword
37d91cd17b Merge branch 'master' of https://github.com/jswz72/qutebrowser 2017-04-08 19:05:22 -04:00
Jacob Sword
7588cdb185 fixed formatting issues 2017-04-08 19:04:25 -04:00
Jacob Sword
6ccb420230 Fix syntax error in debug-exit 2017-04-08 18:42:26 -04:00
Florian Bruhin
778832a813 Set path when redirecting qute:* URLs
Fixes #2513
2017-04-08 23:04:10 +02:00
Jacob Sword
45dff6c0c8 update usage of debug-flag arguments 2017-04-08 16:54:08 -04:00
Florian Bruhin
28e6158a04 Stabilize some tests with Qt 5.9 QtWebEngine 2017-04-08 20:38:23 +02:00
Florian Bruhin
232f091bfe Merge branch 'pyup-bot/pyup-update-setuptools-34.3.3-to-34.4.0' 2017-04-08 20:24:03 +02:00
Florian Bruhin
ee31922c46 Merge commit '043039d673e9435d80034a80dcfe389f26d2dd06' into pyup-bot/pyup-update-setuptools-34.3.3-to-34.4.0 2017-04-08 20:15:13 +02:00
Florian Bruhin
6051f93c02 Avoid checking for scroll position in macro tests
This makes them simpler and more stable.
2017-04-08 19:54:30 +02:00
Florian Bruhin
e23318fe91 Mark failing test as flaky on QtWebEngine
It consistently fails on Qt 5.9 now while waiting the page to be scrolled to
0/20, but I can't figure out why that is happening.

See #2514, #2410
2017-04-08 19:29:46 +02:00
Florian Bruhin
a081d4184d tests: Adjust percent-encoding tests for Qt 5.9 changes
See #2514
2017-04-08 19:25:55 +02:00
Florian Bruhin
c23e4b1c5f tests: Allow @qt<... marker for BDD tests 2017-04-08 19:20:53 +02:00
pyup-bot
043039d673 Update setuptools from 34.3.3 to 34.4.0 2017-04-08 05:19:34 +02:00
Jacob Sword
dadbf7657f Merge remote-tracking branch 'upstream/master' 2017-04-07 21:21:01 -04:00
Jacob Sword
3b87e7c297 Add --debug-exit argument and validity check 2017-04-07 21:12:42 -04:00
Florian Bruhin
0068d87382 Merge commit '8878f867a7c8565801bc0187796e6638bfe02c85' into pyup-bot/pyup-update-tox-2.6.0-to-2.7.0 2017-04-06 21:44:32 +02:00
Florian Bruhin
fd9b86a340 Remove unused imports 2017-04-06 21:40:26 +02:00
Florian Bruhin
871504d91b Fix undefined names 2017-04-06 21:37:23 +02:00
pyup-bot
8878f867a7 Update tox from 2.6.0 to 2.7.0 2017-04-06 21:19:49 +02:00
Florian Bruhin
4ec5700cbf Redirect qute:foo to qute://foo
Before, we just returned the same data for both, but then we'll run into
same-origin restrictions as qute:history and qute:history/data are not the same
host.
2017-04-06 21:18:58 +02:00
Florian Bruhin
3cc9f9f073 Don't use from-import 2017-04-06 20:36:54 +02:00
Florian Bruhin
6d4948f9d0 Update authors 2017-04-06 20:35:32 +02:00
Florian Bruhin
760dca475e Merge commit 'be254be13a61171d4109224450db9e67d1076080' into imransobir/fix-webkit-history 2017-04-06 20:34:49 +02:00
Florian Bruhin
6f952c83af Update docs 2017-04-06 07:16:18 +02:00
Florian Bruhin
d9d0fbb6ae Merge commit 'e7755f5d9f8a5e995b83a239c05016cf1d58abba' 2017-04-06 07:10:22 +02:00
Martin Tournoij
e7755f5d9f Add :debug-log-filter none
This allows us to clear any filters. Useful for users, and needed for
the tests.
2017-04-04 20:51:14 +01:00
Martin Tournoij
857565c384 Mention that qutebrowser@ also gets the mails from qutebrowser-announce@ 2017-04-04 19:58:51 +01:00
Martin Tournoij
200e439a30 Fix crash of :debug-log-filter when --filter wasn't given
There was no `LogFilter`. The fix is to always initialize a
`LogFilter()` with `None`. as the "filter".

Fixes #2303.
2017-04-04 17:45:23 +01:00
Florian Bruhin
6c8ca30766 Update docs 2017-04-04 18:26:04 +02:00
Imran Sobir
be254be13a Use new history page on webkit-ng. 2017-04-04 19:21:25 +05:00
Martin Tournoij
c5427a0127 Fix display of errors while reading the key config file
Also catch `cmdexc.CommandError` on startup to show these errors in the
alert dialog on startup.

Fixes #1340
2017-04-04 09:50:12 +01:00
Florian Bruhin
0de3b5460e Only disable the cache on Qt 5.7.1
I ended up bisecting it, and https://codereview.qt-project.org/#/c/153977/
causes this, which is not in 5.7.0.
2017-04-04 08:24:50 +02:00
Florian Bruhin
2eb365b146 Also disable cache on Qt 5.7 2017-04-03 20:22:54 +02:00
Florian Bruhin
b6642e66fa Fix cache tests on Qt 5.8 2017-04-03 19:41:37 +02:00
Florian Bruhin
1b0ea19ca4 Disable QtNetwork cache on Qt 5.8
See #2427
2017-04-03 17:49:13 +02:00
pyup-bot
8f82113748 Update jinja2 from 2.9.5 to 2.9.6 2017-04-03 16:32:48 +02:00
Florian Bruhin
cb4c64eec9 Remove null argument for QtValueError 2017-04-03 10:18:56 +02:00
Florian Bruhin
2c3fcda18e Remove qtutils.ensure_not_null
It's not used anymore.
2017-04-03 09:32:13 +02:00
Florian Bruhin
3b1b325711 Fix logging 2017-04-03 09:04:28 +02:00
Florian Bruhin
a11356bb99 Don't require working icon to start 2017-04-03 08:32:39 +02:00
Florian Bruhin
9dc5e978ac Update docs 2017-04-03 06:55:54 +02:00
Florian Bruhin
35181ff84e Merge commit '4004d5adf09e6d22dae5d781a02c5fc2bbd26724' into Carpetsmoker/unwritable-keyconf 2017-04-03 06:55:01 +02:00
Martin Tournoij
4004d5adf0 Don't crash when trying to write an unwritable keyconf.
Also change the logic in _load_default a wee bit so that it won't try to
write the keys.conf on startup.

Fixes #1235
2017-04-03 01:48:39 +01:00
Florian Bruhin
30655e29fc Regenerate authors 2017-04-02 22:58:22 +02:00
Florian Bruhin
55b0f16383 Merge commit 'cdb3605b03911e0cffce7cc7a07bb5b120d195ce' into Penaz91/master 2017-04-02 22:57:47 +02:00
Florian Bruhin
e3fc23fa30 Update authors 2017-04-02 19:24:06 +02:00
Florian Bruhin
2108846948 Merge commit '1a337f6a77cf9e284abcf14813b6c70241e0045c' into Carpetsmoker/document-spell 2017-04-02 19:23:52 +02:00
Florian Bruhin
ad6ed83782 Update changelog 2017-04-02 19:17:13 +02:00
Florian Bruhin
248ff09624 Merge commit '5efca155948bc467e4fb7b19dafd98d47e33745b' into Carpetsmoker/config-comments 2017-04-02 19:14:00 +02:00
Florian Bruhin
48094fb33d Update authors 2017-04-02 18:47:16 +02:00
Florian Bruhin
b20267b57d Merge commit '7f13c9a3c31aa719144ca3afcad7af305dd2f6ed' into Carpetsmoker/relax-cmdline 2017-04-02 18:47:00 +02:00
Florian Bruhin
338307ac24 Add #noqa for Quitter._shutdown 2017-04-02 18:35:10 +02:00
Florian Bruhin
f595c2a7fb Update changelog 2017-04-02 18:34:39 +02:00
Florian Bruhin
e2cf02c705 Merge commit '79a22f1f4751741cabd5f5a19ee4bcdb6b6dfce8' into Carpetsmoker/unknown-setting-c 2017-04-02 18:34:12 +02:00
Florian Bruhin
f2ddf608a8 Update authors 2017-04-02 18:33:55 +02:00
Florian Bruhin
bf1834e132 Merge commit '522e105aaf4c326d27e087222c0ba76680d1bed3' into pyup-bot/pyup-update-flask-0.12-to-0.12.1 2017-04-02 18:11:34 +02:00
Florian Bruhin
2238a888dc Fix changelog 2017-04-02 15:20:44 +02:00
Penaz
cdb3605b03 Update INSTALL.asciidoc 2017-04-02 10:36:11 +02:00
Penaz
1f2e04c466 Update INSTALL.asciidoc
Updated Install.asciidoc to include Live Install on Gentoo
2017-04-01 23:32:42 +02:00
Martin Tournoij
79a22f1f47 Allow pressing ^C when there's an unknown setting
All of it is just converting `objreg.get('xxx')` to `objreg.get('xxx',
None)` and adding a `if xxx is not None` check.

Fixes #1170
2017-04-01 21:14:35 +01:00
Martin Tournoij
1a337f6a77 Document how to do spell checking in the FAQ 2017-03-31 18:51:04 +01:00
pyup-bot
522e105aaf Update flask from 0.12 to 0.12.1 2017-03-31 19:49:32 +02:00
Martin Tournoij
7f13c9a3c3 Relax commandline parsing a bit
Problem 1: Entering a command of `:::save` gives an error.
Problem 2: Entering a command of `:save\n` gives an error.

Both scenarios may seem a bit silly at first, but I encountered both by
copy/pasting a command:

1. Enter `:` in qutebrowser.
2. Copy a full line from a terminal starting with `:`.
3. You will now have both of the above problems.

Solution: Trim all whitespace and `:` of a command. This is also what
Vim does, by the way.
2017-03-31 17:14:11 +01:00
Florian Bruhin
9cd2c9aa6d Merge branch 'Carpetsmoker/feature-modeline' 2017-03-31 17:47:34 +02:00
Florian Bruhin
05059b4a5e Merge commit '8af5cfb4ac9e6d928cfeb0522fa729ba616df70a' 2017-03-31 17:47:34 +02:00
Florian Bruhin
80a5613b80 Merge commit '8af5cfb4ac9e6d928cfeb0522fa729ba616df70a' into Carpetsmoker/feature-modeline 2017-03-31 17:47:02 +02:00
Martin Tournoij
8af5cfb4ac Add a modeline to all the *.feature files
This really tripped me up yesterday, My "Vim default" is to use tabs.

This (where `!···` is a tab) does not work as you'll hope it works:

    Scenario: Retrying a failed download when the directory didn't exist (issue 2445)
        When I download http://localhost:(port)/data/downloads/download.bin to <path>
        And I wait for the error "Download error: No such file or directory: *"
        And I make the directory <mkdir>
        And I run :download-retry
!···!···And I wait until the download is finished
        Then the downloaded file <expected> should exist

        Examples:
        | path                 | mkdir   | expected             |
        | asd/zxc/             | asd/zxc | asd/zxc/download.bin |

Unfortunately, pytest-bdd uses the "Python 2 behaviour" of "expand all
tabs to 8 spaces", and doesn't give any errors on strange/inconsistent
whitespace. It can cause very confusing errors.
2017-03-31 16:16:31 +01:00
Florian Bruhin
189c1721af Don't wait for download.bin in windows downloads 2017-03-31 14:46:29 +02:00
Florian Bruhin
fd276dabc7 appveyor_install: Don't install old PyQt if unneeded 2017-03-31 13:05:35 +02:00
Florian Bruhin
c28c428051 appveyor: Add Python36 to PATH
Otherwise the PyQt in the virtualenv won't be able to find python3.dll.
2017-03-31 13:05:35 +02:00
Florian Bruhin
a6041834f8 Try adding a PyPI testenv on AppVeyor 2017-03-31 13:05:34 +02:00
Florian Bruhin
6c3abadb32 Stabilize :repeat-command test 2017-03-31 13:05:34 +02:00
Florian Bruhin
004eb742f6 Stabilize test_guiprocess 2017-03-31 13:05:34 +02:00
Florian Bruhin
43155b0cc8 Stabilize history.replaceState tests 2017-03-31 13:05:34 +02:00
Florian Bruhin
eb202d761c Stabilize dumping bookmarks test
For some reason, with QtWebEngine on Windows, sometimes the :debug-dump-page
callback does not get called if we try to dump the same page again...
2017-03-31 13:05:34 +02:00
Florian Bruhin
1eda2b0ea4 Fallback to clipboard when primary selection is unsupported 2017-03-31 13:05:34 +02:00
Florian Bruhin
64feb62fb1 Paste clipboard when using shift-insert in prompts 2017-03-31 13:05:34 +02:00
Florian Bruhin
7dba877354 tests: Update "Unable to set geometry" ignore 2017-03-31 13:05:34 +02:00
Florian Bruhin
2884277dbd Fix Shift-Insert without it being supported 2017-03-31 13:05:34 +02:00
Florian Bruhin
dc405ec3a8 Skip QtWebEngine SSL tests on Windows 2017-03-31 13:05:34 +02:00
Florian Bruhin
a4619d07db tests: Wait until about:blank is loaded 2017-03-31 13:03:40 +02:00
Florian Bruhin
bf66bb221f Ignore getrlimit error during tests 2017-03-31 13:03:40 +02:00
Florian Bruhin
708b46d6c0 Fix text with empty primary selection 2017-03-31 13:03:40 +02:00
Florian Bruhin
4d49d9da09 Skip renderer process crash test on Windows 2017-03-31 13:03:40 +02:00
Florian Bruhin
c551c62c27 Stabilize JS tests 2017-03-31 13:03:40 +02:00
Florian Bruhin
dc0a782839 Run python in hints tests 2017-03-31 13:03:40 +02:00
Florian Bruhin
2c4e549d80 Close temporary download file for QtWebEngine
Otherwise, Chromium won't be able to write on it on Windows - and we only
need the name anyways.
2017-03-31 13:03:18 +02:00
Florian Bruhin
edb197b028 Make waiting for download prompt more robust 2017-03-31 13:03:18 +02:00
Florian Bruhin
e28eabe5eb Add marker for #2478 2017-03-31 13:03:17 +02:00
Florian Bruhin
5a16133685 Fix prompt with SSL error test 2017-03-31 13:03:17 +02:00
Florian Bruhin
a3a885f053 Ignore bogus Qt warning during tests 2017-03-31 13:03:17 +02:00
Florian Bruhin
a55d1b1ee8 Save old socket for IPC
At least on Windows with Qt 5.8, we get readyRead notifications *after*
disconnect...
2017-03-31 13:03:17 +02:00
Florian Bruhin
57223b78f3 Merge commit '03704ecb4b3b603379f7caf297ae568f0902f90a' 2017-03-31 12:06:07 +02:00
Florian Bruhin
390006281f Merge commit '3c8e2a630a374fb571d70ed8c5a9f0c7faefd64a' into pyup-bot/pyup-update-pyqt5-5.8.1.1-to-5.8.2 2017-03-31 12:04:17 +02:00
Florian Bruhin
150676404e Merge commit '47c7feea551e8a6822d5da522187cca417ca3223' into pyup-bot/pyup-update-pytest-mock-1.5.0-to-1.6.0 2017-03-31 12:04:15 +02:00
Florian Bruhin
134155480e tox: Update PyQt5 to 5.8.2 2017-03-31 10:10:55 +02:00
Florian Bruhin
3b351d9066 Run more invocation tests with QtWebEngine 2017-03-31 06:18:43 +02:00
pyup-bot
47c7feea55 Update pytest-mock from 1.5.0 to 1.6.0 2017-03-31 01:25:27 +02:00
Florian Bruhin
eb31f679f4 Allow unknown args in testbrowser 2017-03-30 21:50:19 +02:00
Martin Tournoij
5efca15594 Put option comments right above the option value
Problem: I like to edit `~/.config/qutebrowser/qutebrowser.conf`
manually with Vim. This works great, except that the current format is a
bit of a pain to deal with:

	[section-name]
	# section description
	#
	# [ Description of all the options]

	actual options

So if I want to know the description or what the default value is, I
need to scroll up and back down.

Solution: change the order of the comments to:

	# section description
	[section-name]

	# Option description
	option = value

	# Option description two
	optiontwo = value

	# Hello, world!
	[section-two]
	...

Which is much more convenient (and also what almost any other program
does).

(This patch changes much less code than it looks in the diff; I just
de-looped and moved `_str_option_desc` below `_str_items` as that makes
more sense since it gets called by `_str_items`).
2017-03-30 18:45:28 +01:00
pyup-bot
3c8e2a630a Update pyqt5 from 5.8.1.1 to 5.8.2 2017-03-30 13:39:30 +02:00
pyup-bot
03704ecb4b Update sip from 4.19.1 to 4.19.2 2017-03-30 12:39:24 +02:00
Florian Bruhin
6939f81de7 Merge commit '563a5431e35831cb0a8c418835c54d0264d92c78' into Kingdread/windows-drive-cwd 2017-03-30 10:48:39 +02:00
Florian Bruhin
2377235c14 Merge commit 'caf0a87e16cf930f67ce9fc64ea94e17cae6269d' into amosbird/master 2017-03-30 10:48:32 +02:00
Florian Bruhin
20c414a62c Update changelog 2017-03-30 10:44:11 +02:00
Florian Bruhin
203b2d30cc Update changelog 2017-03-30 10:42:43 +02:00
Florian Bruhin
6a144ef7bd Merge branch 'Kingdread/windows-drive-cwd' 2017-03-30 10:41:58 +02:00
Daniel Schadt
563a5431e3 fixup! use message.error instead of a tooltip 2017-03-29 18:32:07 +02:00
Daniel Schadt
186eab8eb1 use message.error instead of a tooltip 2017-03-29 17:07:53 +02:00
Daniel Schadt
99f7bfa712 show messages on top of the prompt
Otherwise, errors are hidden behind the prompt, which makes it hard to
use them in the filename prompt.
2017-03-29 16:44:29 +02:00
Imran Sobir
3aaebe83fb Remove noscript message from history.html. 2017-03-29 14:22:58 +05:00
Amos Bird
caf0a87e16 Fix #2476, recognize SOCKS5, SOCKS4 in proxy. 2017-03-29 14:22:37 +08:00
Florian Bruhin
93a12797aa Fix quteprocess tests with Python 3.6 on Windows
Values smaller than 86400 would result in a negative unsupported timestamp and
thus throw ValueError in Python 3.6
2017-03-28 20:53:11 +02:00
Florian Bruhin
5d9cd98c0f tox: Add a mkvenv-win-pypi env 2017-03-28 20:42:23 +02:00
Florian Bruhin
fe81f153cf tests: Ignore "Unable to locate theme engine" messages 2017-03-28 20:41:23 +02:00
Imran Sobir
4a4c7b96d1 Add nojs history page. 2017-03-28 18:34:47 +05:00
Florian Bruhin
607710eeae Update changelog
[ci skip]
2017-03-27 08:02:43 +02:00
Florian Bruhin
bcb4649235 Fix crash when window_ids change during init 2017-03-27 08:00:19 +02:00
Florian Bruhin
b98d34b29c Handle None-tab in get_tab_fields
I can't reproduce this but I got a crash report about it.
2017-03-27 07:57:43 +02:00
Florian Bruhin
bcee6d295c Handle None-widget in tabbedbrowser.widgets()
I can't reproduce this, but got a crash report about it.
2017-03-27 07:52:33 +02:00
Florian Bruhin
5a4d11be68 Fix lint 2017-03-27 07:16:10 +02:00
Florian Bruhin
a8bc531eee Add a test for :open with -s 2017-03-27 07:09:55 +02:00
Florian Bruhin
43090d146b Update docs 2017-03-27 07:09:48 +02:00
Florian Bruhin
f6906512dc Merge commit 'df93e30ec20dd1b2b4fe163bdb5a69c232fb8c71' into Al-Caveman/master 2017-03-27 07:00:53 +02:00
Florian Bruhin
37d22a7cfd Merge commit '9dccd00ebb2483fd0bb6c6447f57c76a4b40d335' into Kingdread/windows-drive-cwd 2017-03-26 22:14:47 +02:00
pyup-bot
b3660cf3f4 Update setuptools from 34.3.2 to 34.3.3 2017-03-26 18:21:23 +02:00
Florian Bruhin
39b09f7822 Improve messageview hide code 2017-03-26 15:03:44 +02:00
Florian Bruhin
59094b71a9 Update docs 2017-03-26 15:03:44 +02:00
Florian Bruhin
2181e1ddc4 Merge commit '13677d3563dbd01ae188a2b1a79c7dd840a5dc5e' into pkill-nine/upstream-master-close_message_on_click 2017-03-26 14:59:08 +02:00
pkill9
13677d3563 Add mouse back button to click test. 2017-03-25 21:16:51 +00:00
pkill9
5e1c530d71 Add docstring to MessageView.mousePressEvent 2017-03-25 21:03:21 +00:00
pkill9
bf2493c1c4 Add test. 2017-03-25 20:06:58 +00:00
pkill9
67034273f7 Move criteria into a list and add middle mouse button. 2017-03-25 15:58:37 +00:00
caveman
df93e30ec2 fixes #2468 2017-03-25 11:44:36 +04:00
Daniel Schadt
9dccd00ebb fix unused import 2017-03-24 14:49:30 +01:00
Daniel Schadt
a011034ff7 fix tests 2017-03-24 13:21:09 +01:00
Daniel Schadt
df83f7aa99 also add path transformations to :download 2017-03-24 12:30:29 +01:00
Daniel Schadt
07b3a7db7c add integration tests for reserved filenames 2017-03-24 11:57:05 +01:00
Daniel Schadt
bc4430e5d9 prevent reserved filenames on Windows
Fixes #82

Prevents filenames like COM1, ...
2017-03-24 11:36:19 +01:00
Daniel Schadt
9d905ebb5c disallow filenames like E:filename
Per-drive working directories are not really supported.
2017-03-24 11:04:20 +01:00
Florian Bruhin
52b448e368 pylint: Ignore no-else-return
This will be added in the next pylint release, and it seems we can already add
it without getting an error.
2017-03-23 20:51:37 +01:00
Florian Bruhin
38beba98b9 pylint-master requirements: Add github3.py 2017-03-23 20:32:58 +01:00
Daniel Schadt
3da21a32d2 treat E: and E:\ the same when downloading
Fixes #2305
2017-03-23 18:16:15 +01:00
Florian Bruhin
a7d6cc6509 Update docs 2017-03-23 06:17:48 +01:00
Ryan Roden-Corrent
a68f997d95 Make keyhint delay configurable.
ui.keyhint-delay controls the time from starting a keychain to showing the
keyhint dialog. Resolves #2462.
2017-03-22 21:50:26 -04:00
Florian Bruhin
0c7d012420 Update changelog 2017-03-22 22:54:33 +01:00
Florian Bruhin
042ffeca91 Merge commit '631936361405d812f353b4108246c883cdf48100' into Kingdread/issue-2304 2017-03-22 22:50:28 +01:00
Daniel Schadt
6319363614 add a test for downloading a 500 inline attachment 2017-03-22 13:38:03 +01:00
Florian Bruhin
4d65abfcc6 Check if widget is deleted in _on_webkit_icon_changed 2017-03-22 06:32:09 +01:00
Daniel Schadt
ebc70f66e5 Check for None-reply in _do_die
Fixes #2304

In some cases, the finished handler fired before the error handler, e.g.
when downloading a 500 error page that is sent as attachment:

    HTTP/1.1 500 Internal Server Error
    Content-Type: application/octet-stream
    Content-Disposition: inline; filename="attachment.jpg"

here we downloaded 0 bytes, fired the finished handler and after that
fired the error handler because of the 500 - but the finished handler
had already set our reply to None (and displayed the error message).
2017-03-21 18:54:21 +01:00
Florian Bruhin
f8e043214a Update WORKAROUND comments 2017-03-21 10:29:31 +01:00
Florian Bruhin
081abde9cd Fix indent 2017-03-20 22:06:05 +01:00
Florian Bruhin
3fbb9a14e0 Fix continuing a search after clearing it
Fixes #2438
2017-03-20 21:34:33 +01:00
Florian Bruhin
41268f994d Merge branch 'pyup-bot/pyup-update-hypothesis-3.6.1-to-3.7.0' 2017-03-20 17:58:34 +01:00
Florian Bruhin
78ae6a7a5f Merge commit 'cd91da32c4a1680cb201e58e40dfb3744628eca8' 2017-03-20 17:58:34 +01:00
Florian Bruhin
13878647b2 Merge commit 'cd91da32c4a1680cb201e58e40dfb3744628eca8' into pyup-bot/pyup-update-hypothesis-3.6.1-to-3.7.0 2017-03-20 16:48:41 +01:00
Florian Bruhin
c996245012 Fix line length 2017-03-20 16:48:21 +01:00
Florian Bruhin
c48339fe06 Update changelog 2017-03-20 16:47:36 +01:00
pyup-bot
cd91da32c4 Update hypothesis from 3.6.1 to 3.7.0 2017-03-20 16:04:22 +01:00
Florian Bruhin
98f17a03bb Prevent page without history from being serialized
Fixes #2458
2017-03-20 11:50:04 +01:00
Florian Bruhin
4b6b9c2d21 Add missing file 2017-03-20 11:28:01 +01:00
Florian Bruhin
ed4cd816d4 Update docs 2017-03-20 09:45:27 +01:00
Florian Bruhin
6888ac04e1 Fix handling of failed downloads with QtWebEngine 2017-03-20 09:44:07 +01:00
Florian Bruhin
3e2ba32240 Fix retrying downloads with QtWebEngine
Fixes #2298
2017-03-20 09:35:53 +01:00
Florian Bruhin
1581db2d59 Update changelog 2017-03-20 09:16:26 +01:00
Florian Bruhin
1179ee7a93 Merge branch 'imransobir/newhistory' 2017-03-20 09:11:58 +01:00
Florian Bruhin
7652b6ae03 Merge commit '724e6b29c38a55f722f17997379f1ebe190fa6db' 2017-03-20 09:11:47 +01:00
pyup-bot
26f5fb8eb4 Update cheroot from 5.3.0 to 5.4.0 2017-03-19 17:19:46 +01:00
thuck
20d058741e Merge branch 'pintab' of https://github.com/thuck/qutebrowser into pintab 2017-03-19 14:43:36 +01:00
thuck
650b1de3b6 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2017-03-19 14:26:48 +01:00
thuck
02bf0401ab Last pinned to pinned_count 2017-03-19 14:05:21 +01:00
thuck
2eb07fc9cc Fix line size 2017-03-19 14:03:24 +01:00
MikeinRealLife
a1e1e90ec9 Issue #2292
Added a list of chrome urls that work.  A couple of with (?) next to
them did nothing and didn't hang or kill the browser, so I removed them.
They only work in OSX, not windows (opened separate issue for this).
2017-03-18 20:05:21 -07:00
Florian Bruhin
1254f4d132 Add -bb when running tests
Fixes #1989
2017-03-18 21:08:07 +01:00
Florian Bruhin
069f908a61 Get rid of run_pytest.py
Fixes #2452
2017-03-18 21:03:52 +01:00
Florian Bruhin
7c94b06be1 Merge commit '724e6b29c38a55f722f17997379f1ebe190fa6db' into imransobir/newhistory 2017-03-18 18:31:45 +01:00
pyup-bot
dc50c6ac3d Update py from 1.4.32 to 1.4.33 2017-03-17 04:29:28 +01:00
pyup-bot
4b4c28fc6a Update py from 1.4.32 to 1.4.33 2017-03-17 04:29:26 +01:00
Florian Bruhin
99c7301fb4 Update IPC atime once all 3h
See #996
2017-03-16 09:24:49 +01:00
Imran Sobir
724e6b29c3 Make session interval configurable. 2017-03-16 12:11:16 +05:00
Imran Sobir
fb97c6dffc Send history item atime in milliseconds. 2017-03-16 12:03:40 +05:00
Florian Bruhin
befb1afb2c Fix vulture 2017-03-16 07:50:23 +01:00
Florian Bruhin
d33e590ce5 Fix lint 2017-03-15 22:15:52 +01:00
Florian Bruhin
a70012b32e Merge commit '5f17887a255494e1872c33c96f0596d6701e35fc' into pyup-bot/pyup-update-werkzeug-0.12-to-0.12.1 2017-03-15 20:01:02 +01:00
Florian Bruhin
85fff35eef Merge branch 'gl-workaround' 2017-03-15 19:52:33 +01:00
Florian Bruhin
0877092cea Add workaround for black screen with QtWebEngine
Fixes #2441
2017-03-15 19:52:21 +01:00
pyup-bot
5f17887a25 Update werkzeug from 0.12 to 0.12.1 2017-03-15 19:00:29 +01:00
Florian Bruhin
54eddc4658 Merge commit '578fac1331ea5d733088379b28edc760964147b1' into pyup-bot/pyup-update-pytest-3.0.6-to-3.0.7 2017-03-15 08:24:17 +01:00
pyup-bot
d19979aa4a Update wrapt from 1.10.8 to 1.10.10 2017-03-15 01:48:48 +01:00
pyup-bot
c40844dc09 Update wrapt from 1.10.8 to 1.10.10 2017-03-15 01:48:47 +01:00
pyup-bot
578fac1331 Update pytest from 3.0.6 to 3.0.7 2017-03-15 01:18:51 +01:00
Florian Bruhin
608a16c8b7 Regen docs 2017-03-14 17:32:02 +01:00
Florian Bruhin
84d2e9adc6 Improve documentation around scrolling
Fixes #2447
2017-03-14 16:58:33 +01:00
Florian Bruhin
3a88b70eca Fix PyQt5 version in tox.ini 2017-03-13 09:11:22 +01:00
Florian Bruhin
f50485420a Merge commit 'b5d5f323bb85cfe6824bab97a6e29efe5204616f' into pyup-bot/pyup-update-werkzeug-0.11.15-to-0.12 2017-03-13 07:47:58 +01:00
Florian Bruhin
db4ca46ec1 Merge commit '4d9d4490f59401d790139b4e5cf45dc2b9096eee' into pyup-bot/pyup-update-setuptools-34.3.1-to-34.3.2 2017-03-13 07:47:56 +01:00
Florian Bruhin
b35be46b8d Merge commit '4b5af2296d07c7c9f0e6197d7167509ecc35c4f4' into pyup-bot/pyup-update-cheroot-5.2.0-to-5.3.0 2017-03-13 07:47:53 +01:00
Florian Bruhin
68247a1ef0 Fix PyQt5 requirements
See https://www.riverbankcomputing.com/pipermail/pyqt/2017-March/038964.html
2017-03-13 07:39:21 +01:00
Florian Bruhin
8d9030ec47 Use debug log for on_timeout message 2017-03-13 07:01:21 +01:00
Florian Bruhin
ecec836111 Fix adblock UTF-8 test on Windows 2017-03-13 07:01:13 +01:00
Florian Bruhin
7d9686f917 Don't keep temporary files around in asciidoc2html
Fixes #2431
2017-03-13 06:56:29 +01:00
pyup-bot
4b5af2296d Update cheroot from 5.2.0 to 5.3.0 2017-03-12 18:54:35 +01:00
pkill9
b1771a13c9 Removed setting. 2017-03-12 16:48:57 +00:00
pkill9
87c4c143bf Clear notification messages in a window when they're clicked. 2017-03-11 20:45:12 +00:00
pyup-bot
4d9d4490f5 Update setuptools from 34.3.1 to 34.3.2 2017-03-11 15:59:29 +01:00
pyup-bot
b5d5f323bb Update werkzeug from 0.11.15 to 0.12 2017-03-10 13:22:25 +01:00
Imran Sobir
ccbf8572c3 Check for null when receiving history. 2017-03-09 22:16:46 +05:00
Imran Sobir
a1bec12b2e Ensure qute:javascript throws QuteSchemeOSError on 404. 2017-03-09 22:07:55 +05:00
Imran Sobir
50bca33618 Use OSError instead of IOError. 2017-03-09 21:47:12 +05:00
Imran Sobir
19b7f779ef Fix ambiguity in history table ID. 2017-03-09 21:41:57 +05:00
Imran Sobir
3fbeecbec2 Hide 'Show more' when Javascript is disabled. 2017-03-09 21:35:22 +05:00
Florian Bruhin
0b5838f9fd Fix BDD version check operators 2017-03-08 20:56:30 +01:00
Florian Bruhin
685393c289 Update docs 2017-03-08 19:23:01 +01:00
Florian Bruhin
eb2888a957 Merge commit 'd3b16bbd075f9e8c8656a402975d776088c2dab8' into pkill-nine/upstream-master-close_messages 2017-03-08 19:19:30 +01:00
Florian Bruhin
4278cd5e3e Remove unused operator imports 2017-03-08 19:10:29 +01:00
Florian Bruhin
3925fa2872 Use separate requirements file for PyQt 2017-03-08 19:09:34 +01:00
pkill9
d3b16bbd07 Add command to clear messages - cleaner 2017-03-08 10:49:15 +00:00
Florian Bruhin
7d7f5350c5 Add test for utils.get_clipboard with empty clipboard 2017-03-08 09:33:36 +01:00
Florian Bruhin
7ba01e6764 Get rid of utils.actute_warning
Only Ubuntu Trusty still uses Qt < 5.3, and the issue seems to be fixed there by
now.
2017-03-08 09:25:46 +01:00
Florian Bruhin
f86f9cd92a Refactor qtutils.version_check API
Fixes #2423
2017-03-08 08:41:18 +01:00
Florian Bruhin
ac0409c60d Don't install requirements-pip.txt
It causes stuff to blow up when something in there got upgraded, and we ask pip
to downgrade one of its dependencies.

We still keep the file around so we get notified about updates.
2017-03-08 07:42:08 +01:00
Florian Bruhin
dfb4374ae1 Release v0.10.1 2017-03-08 06:26:22 +01:00
Florian Bruhin
6052d36ef0 Merge commit '2304fd81b5440e55d2686f7cb33c10bb8eaa9e92' into pyup-bot/pyup-update-markupsafe-0.23-to-1.0 2017-03-08 05:11:08 +01:00
Florian Bruhin
4110355167 Merge commit '9512206f97bc51bb2884c38a86b93a72e556428d' into pyup-bot/pyup-update-pyqt5-5.8-to-5.8.1 2017-03-08 05:11:00 +01:00
Florian Bruhin
589ea70626 Update changelog for v0.10.1
(cherry picked from commit 361e4e93ed)
2017-03-08 05:09:53 +01:00
Florian Bruhin
6bdf8495aa pylint: Disable too-many-boolean-expressions 2017-03-08 05:06:35 +01:00
Florian Bruhin
7c9d004bbc Fix compiled version check
Fixes #2412
2017-03-07 22:05:17 +01:00
Florian Bruhin
4c3c86081f Refactor adblock parsing 2017-03-07 21:46:04 +01:00
Florian Bruhin
3258ef7e3f Merge commit 'c50e652cc70dcf1f86dd440b82c2b3f3c8fd5663' into pyup-bot/pyup-update-appdirs-1.4.2-to-1.4.3 2017-03-07 20:37:36 +01:00
Florian Bruhin
ace4006179 Stringify py.path.local in adblock tests 2017-03-07 20:36:50 +01:00
Florian Bruhin
c45019f0a0 Handle invalid UTF8 data in hostblock lists
Fixes #2301
2017-03-07 20:25:13 +01:00
pyup-bot
2304fd81b5 Update markupsafe from 0.23 to 1.0 2017-03-07 17:20:17 +01:00
pyup-bot
9512206f97 Update pyqt5 from 5.8 to 5.8.1 2017-03-07 12:10:15 +01:00
pyup-bot
c50e652cc7 Update appdirs from 1.4.2 to 1.4.3 2017-03-07 09:00:55 +01:00
Florian Bruhin
3cc4f69125 Merge commit '7ef71750e769f9402991f72b1d0e78c0efacf14a' into pyup-bot/pyup-update-flake8-tidy-imports-1.0.5-to-1.0.6 2017-03-07 06:51:34 +01:00
Florian Bruhin
d42dff67f2 Reorder initialization
marcos.init() really belongs into _init_modules, and we need to do _process_args
after everything has been initialized.

Fixes #2408.
2017-03-07 06:46:35 +01:00
pyup-bot
7ef71750e7 Update flake8-tidy-imports from 1.0.5 to 1.0.6 2017-03-07 06:16:53 +01:00
Florian Bruhin
35a58b27af Merge pull request #2406 from qutebrowser/pyup-update-vulture-0.12-to-0.13
Update vulture to 0.13
2017-03-06 16:12:04 +01:00
pyup-bot
694a1247a1 Update vulture from 0.12 to 0.13 2017-03-06 13:30:50 +01:00
pyup-bot
990ee1826e Update vulture from 0.12 to 0.13 2017-03-06 13:30:49 +01:00
Florian Bruhin
3870e9f6b4 Merge pull request #2405 from qutebrowser/pyup-update-pyparsing-2.1.10-to-2.2.0
Update pyparsing to 2.2.0
2017-03-06 06:31:19 +01:00
Florian Bruhin
5fb6d26465 Stabilize some tests 2017-03-06 06:28:26 +01:00
pyup-bot
a19ebfb6d0 Update pyparsing from 2.1.10 to 2.2.0 2017-03-06 03:58:50 +01:00
Florian Bruhin
b117d981a5 Install debug packages on Ubuntu 2017-03-05 20:28:27 +01:00
Florian Bruhin
23a26bf08b Improve travis backtrace script 2017-03-05 20:28:27 +01:00
Florian Bruhin
8fb640f1ff Debug segfaults on travis
Fixes #2097
2017-03-05 20:28:27 +01:00
pkill9
74be2fa4b9 Add command to close all messages. 2017-03-05 14:55:28 +00:00
Florian Bruhin
271cb3be3d Merge branch 'Kingdread-fast-open-download' 2017-03-05 15:51:35 +01:00
Florian Bruhin
27edc89d88 Update changelog 2017-03-05 15:51:14 +01:00
Florian Bruhin
ec42d2fd2a Merge branch 'fast-open-download' of https://github.com/Kingdread/qutebrowser into Kingdread-fast-open-download 2017-03-05 15:50:38 +01:00
Florian Bruhin
0e56cff702 Merge branch 'TomRiddle01-hide_adblock_message' 2017-03-05 15:19:09 +01:00
Florian Bruhin
6fbaa16366 Update authors 2017-03-05 15:18:59 +01:00
Florian Bruhin
a585015d9d Merge branch 'hide_adblock_message' of https://github.com/TomRiddle01/qutebrowser into TomRiddle01-hide_adblock_message 2017-03-05 15:18:43 +01:00
Florian Bruhin
a1c7d179e3 Only call QApplication::sync() with QtWebEngine 2017-03-05 15:16:14 +01:00
Florian Bruhin
fa89fff668 Stabilize session tests 2017-03-05 15:15:12 +01:00
Florian Bruhin
199a2ffe27 Remove unneeded deleted attribute for FakeSocket 2017-03-05 15:15:12 +01:00
Florian Bruhin
efe18b056a Merge pull request #2401 from qutebrowser/pyup-update-cssutils-1.0.1-to-1.0.2
Update cssutils to 1.0.2
2017-03-05 11:03:21 +01:00
Florian Bruhin
c422897abb Make sure to process history after the rest of init is done
Otherwise, with 5ccafd62d4 the history starts
processing before the webview opened, and opening it is delayed until the whole
history is read.

Instead, call _process_args directly (I'm not even sure why it was using a 0ms
QTimer...) and schedule _init_late_modules after everything is really done.
2017-03-04 18:24:44 +01:00
Florian Bruhin
5ccafd62d4 Fix initial keyboard focus with QtWebEngine
Fixes #2321.
2017-03-04 18:11:34 +01:00
Florian Bruhin
e81edc8224 ipc: Delay deleting of QLocalSocket on disconnect
Fixes #2396.

See https://bugreports.qt.io/browse/QTBUG-59297 and
https://github.com/qutebrowser/qutebrowser/issues/2321#issuecomment-284024213
2017-03-04 18:11:34 +01:00
pyup-bot
52518f6abe Update cssutils from 1.0.1 to 1.0.2 2017-03-04 17:50:46 +01:00
Yannis Rohloff
7984643365 flake8 fails fixed 2017-03-04 17:16:52 +01:00
Yannis Rohloff
5d5652a24b always read the host file 2017-03-04 17:08:53 +01:00
Yannis Rohloff
6219b37c39 adblock: Don't show message if host-blocking-enabled is true
Fixes #2364
2017-03-04 16:39:44 +01:00
Imran Sobir
0092b18c44 Fix qute:javascript on Windows. 2017-03-04 19:37:48 +05:00
Daniel Schadt
90f12a1d5a return fast from DownloadItem.open_file
Fixes #2296

By using a singleshot timer, we return fast from DownloadItem.open_file,
which in turn closes the prompt fast, which in turn doesn't allow a
second Ctrl-x to be registered, which in turn doesn't want to set the
filename twice.
2017-03-04 11:30:41 +01:00
Florian Bruhin
550514c20b Merge pull request #2393 from qutebrowser/pyup-update-setuptools-34.3.0-to-34.3.1
Update setuptools to 34.3.1
2017-03-03 07:31:41 +01:00
pyup-bot
0eeb3a51d3 Update setuptools from 34.3.0 to 34.3.1 2017-03-03 01:50:32 +01:00
Florian Bruhin
a5af039bf4 Merge pull request #2391 from qutebrowser/pyup-update-cheroot-5.1.0-to-5.2.0
Update cheroot to 5.2.0
2017-03-02 22:49:32 +01:00
Florian Bruhin
0186a9bde5 Fix lint 2017-03-02 21:10:31 +01:00
pyup-bot
88a04556ea Update cheroot from 5.1.0 to 5.2.0 2017-03-02 20:45:31 +01:00
Florian Bruhin
75bc400e74 Add Chromium version to version output
This also restructures things a bit to show the backend version together with
the backend.

Fixes #2380
2017-03-02 20:22:17 +01:00
Imran Sobir
907d94591d Make a now fixture to hold time of test. 2017-03-02 23:55:59 +05:00
Imran Sobir
96e81f595f Fix a case where 'next' is not correctly returned. 2017-03-02 23:14:00 +05:00
Florian Bruhin
56ab02f54d Set tab as parent for print dialogs
Fixes #2366
2017-03-02 18:44:07 +01:00
Imran Sobir
895620b536 Don't assume 'next' appears last. 2017-03-02 22:40:24 +05:00
Florian Bruhin
ea653e6fe4 Merge pull request #2388 from qutebrowser/pyup-initial-update
Initial Update
2017-03-02 10:16:49 +01:00
Florian Bruhin
65a701a180 Stabilize existing text test 2017-03-02 08:38:07 +01:00
Florian Bruhin
d6f47bd3fb Fix lint 2017-03-02 08:29:43 +01:00
Florian Bruhin
d4124c5c2a Ignore pyup-bot for author list 2017-03-01 23:55:19 +01:00
pyup-bot
22650785aa Update parse from 1.6.6 to 1.8.0 2017-03-01 23:52:42 +01:00
Florian Bruhin
81a36ffd7d Strip QtWebEngine download suffixes properly
Fixes #2386
2017-03-01 23:43:04 +01:00
Florian Bruhin
88904864c9 Skip failing tests on Qt < 5.8 2017-03-01 20:24:34 +01:00
Florian Bruhin
f4490fb90c Fix WebKitElement._move_text_cursor with old PyQt 2017-03-01 20:19:40 +01:00
Florian Bruhin
1f12b4c1c1 Relax validation of QssColor values
Fixes #2370
2017-03-01 18:11:53 +01:00
Florian Bruhin
65f407e926 Remove webelem.style_property()
It's not used anymore, and not possible to support with QtWebEngine without a
massive performance hit when serializing elements.
2017-03-01 17:54:27 +01:00
Florian Bruhin
b4af966167 Make stubbed methods fail tests again
Only some caret browsing stuff and a few webelement methods are stubbed out now.
Make them fail tests so we notice when we use a stub.
2017-03-01 17:43:33 +01:00
Florian Bruhin
03f1e0913d Add _js_call to WebEngineElement 2017-03-01 17:34:21 +01:00
Florian Bruhin
bc0a9cd94d Move cursor to end with input elements on QtWebEngine 2017-03-01 17:30:48 +01:00
Florian Bruhin
1e1ba34b60 Fix selecting text fields with QtWebKit
Using focus() in JS there means that existing text in the field gets selected.
Move the cursor to the end after focusing it to prevent that.

Fixes #2359
2017-03-01 17:13:02 +01:00
Florian Bruhin
f9697f1ebe Update changelog 2017-03-01 14:26:38 +01:00
Florian Bruhin
deb59fc66e Don't strip info when loading PAC from a file 2017-03-01 14:19:23 +01:00
Florian Bruhin
9bb5c9fdab Remove UserInfo and path/query for PAC URLs 2017-03-01 14:19:13 +01:00
Florian Bruhin
5d0c9440f6 Fix monkeypatch 2017-03-01 12:12:40 +01:00
Florian Bruhin
ca4f249c30 Use three-argument form of monkeypatch.*attr 2017-03-01 11:33:41 +01:00
Florian Bruhin
1e42fd1319 Fix lint 2017-03-01 11:12:28 +01:00
Florian Bruhin
642afb0aff Merge branch 'wasamasa-ZZ-and-ZQ' 2017-02-28 21:23:18 +01:00
Florian Bruhin
0bd167cf96 Update authors 2017-02-28 21:23:10 +01:00
Florian Bruhin
61e7d5883f Merge branch 'ZZ-and-ZQ' of https://github.com/wasamasa/qutebrowser into wasamasa-ZZ-and-ZQ 2017-02-28 21:22:55 +01:00
Imran Sobir
cb6c6b814e Fix pylint errors. 2017-02-28 20:11:51 +05:00
Imran Sobir
9e6b0240f6 Put javascript in module, fix lint errors 2017-02-28 19:23:31 +05:00
Imran Sobir
3e45f739fc Show message when Javascript is turned off. 2017-02-28 19:22:10 +05:00
Imran Sobir
e8db008671 Move qute:history javascript to own file. 2017-02-27 22:44:13 +05:00
Imran Sobir
3b3846c9dc Add qute:javascript to serve JS files. 2017-02-27 22:37:24 +05:00
Imran Sobir
783769d302 Load new history items from next item's time. 2017-02-27 21:44:23 +05:00
Imran Sobir
c4416c8ac0 Prevent crash with invalid start_time param. 2017-02-27 21:41:35 +05:00
Imran Sobir
c223f6c69d Style/misc fixes. 2017-02-27 21:39:51 +05:00
Imran Sobir
76bf8c0049 Convert history to list before converting to JSON. 2017-02-26 19:58:14 +05:00
Imran Sobir
845f21b275 New qute:history page. 2017-02-26 17:07:30 +05:00
Vasilij Schneidermann
ce433bd139 Add ZZ and ZQ keys to (save and) quit the session 2017-02-25 23:10:18 +01:00
Daniel Karbach
38ca583084 new default keybinds 2016-11-28 10:57:16 +01:00
thuck
a254097558 Using log instead of prompt functions for test 2016-11-24 00:05:17 +01:00
thuck
8d4b55bb80 Fix comments and change self.pinned to self.pinned_count 2016-11-23 22:18:55 +01:00
thuck
e9c79e9be3 Fix for comments on configdata 2016-11-23 08:18:10 +01:00
thuck
05d3631750 Test for accidental url opened in a pinned tab 2016-11-23 08:10:13 +01:00
thuck
9dff4299e8 flake8 fixes 2016-11-23 08:10:13 +01:00
thuck
be980a7268 Including tests for pinned tab prompt
Duplicate function for "I wait for a prompt"
2016-11-23 08:10:13 +01:00
thuck
9547938f79 Fix initial tests 2016-11-23 08:10:13 +01:00
thuck
92e1181680 Included --force option for tab-close
This makes possible to close pinned tabs without
any confirmation.
2016-11-23 08:10:13 +01:00
thuck
b920de764f Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-23 08:10:11 +01:00
thuck
982e4f46e0 Test for accidental url opened in a pinned tab 2016-11-22 07:24:02 +01:00
thuck
175744761b flake8 fixes 2016-11-22 06:57:00 +01:00
thuck
69c82f8563 Including tests for pinned tab prompt
Duplicate function for "I wait for a prompt"
2016-11-21 20:56:34 +01:00
thuck
41adafdec4 Fix initial tests 2016-11-21 20:56:34 +01:00
thuck
e514b0d58e Included --force option for tab-close
This makes possible to close pinned tabs without
any confirmation.
2016-11-21 20:56:34 +01:00
thuck
bcb0010fcb Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-21 20:56:31 +01:00
thuck
e2a6f97c07 Initial tests 2016-11-16 07:48:12 +01:00
thuck
abe3c19646 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-14 19:01:49 +01:00
thuck
6053078637 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-13 14:16:05 +01:00
thuck
84c41c964b First test for tab-pin 2016-11-13 09:40:07 +01:00
thuck
a8ccfe050d Remove unecessary empty line 2016-11-13 08:56:43 +01:00
thuck
785c03c15c Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-13 08:56:19 +01:00
thuck
9eb0a85bae Some fixes for pyflake, pylint and remove useless function 2016-11-11 17:10:46 +01:00
thuck
25b69fe76a Configuration for the size of a pinned tab 2016-11-11 13:57:01 +01:00
thuck
19cc721eb1 Changed behavior on location of tab being pinned
Now when a tab is pinned it goes to the end of all pinned tabs.
Before it went to the index 1.
2016-11-11 12:05:04 +01:00
thuck
00f2b4df96 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-11 11:07:30 +01:00
thuck
23628cdfbf Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-10 20:20:52 +01:00
thuck
9f70fa3ec8 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-10 00:28:31 +01:00
thuck
9beb097c53 Corrected some unecessary spaces 2016-11-09 23:52:56 +01:00
thuck
d7f5f61f03 Implemented counter for total number of tabs
With this counter we can better control the space on the tabbar.
2016-11-09 23:50:41 +01:00
thuck
6f8aaccc2b Attach pin information to tabwidget
Simple access to pin information on tab widget.
Some change for the fmt_pin to not use fields as cheap trick
2016-11-08 21:12:20 +01:00
thuck
d8b5ca295e Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-08 19:53:46 +01:00
thuck
17b7b5c663 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-08 08:13:15 +01:00
thuck
931b008f89 Update title when title-format-pinned is modified 2016-11-08 08:12:40 +01:00
thuck
4f0034911a title-format-pinned initial work
Created configuration configdata.
Load and use template defined on configdata.

TODO: ability to conserve information between restart
TODO: ability to update title on configuration change
2016-11-08 07:56:13 +01:00
thuck
b24ac0ae78 More small fixes
Removed unsed variables.
Removed some empty lines.
Inncluded docstring.
2016-11-08 04:45:07 +01:00
thuck
f9b1d998d4 Last configuration as pin changed to pinned 2016-11-07 22:32:42 +01:00
thuck
f10284b04a Initial work on message.confirm_async
Creation of _tab_close and usage of partial.
2016-11-07 22:28:05 +01:00
thuck
49b2a19925 Merge branch 'master' of https://github.com/The-Compiler/qutebrowser into pintab 2016-11-07 21:25:36 +01:00
thuck
ec50d39578 Some fixes for the pylint 2016-11-07 21:25:05 +01:00
thuck
4ed046d5e7 Everything is pinned instead of pin, and one if corrected 2016-11-07 21:12:34 +01:00
thuck
20eae4d671 Modifed exception structure 2016-11-07 08:11:47 +01:00
thuck
f8dffb4e5c Some modifications from initial feedback
Moved pin information from BrowserTab to TabData.
Changed attribute from pin to pinned.
Changed "ifs" to implicit check boolen value.
Removed blancked line on before else statement.
2016-11-07 08:02:25 +01:00
thuck
29d1c0d68b Small fix for situations where we cannot find the tab for the index
Need to investigate better why and when this is excatly happening
2016-11-06 23:27:06 +01:00
thuck
d7a1a542b6 Change shortcut to tab-pin 2016-11-06 23:25:36 +01:00
thuck
d592651c50 Change command from pin/unpin to tab-pin 2016-11-06 23:24:24 +01:00
thuck
6d7a6db130 Proper title and size for pinned tab
As I'm using self.count() without taking in consideration the number of
pinned tabs the end result is a lot of empty space.
2016-11-06 19:04:32 +01:00
thuck
22133beb72 Fix small bug because result was not declared 2016-11-06 18:24:33 +01:00
thuck
6f610e9c44 Initial development to support pin tabs #926
Done so far:
Two new commands pin/unpin, both accept a index to help the organization
(maybe this should be more a flag and not exactly two commands)
Crtl+p to pin, Crtl+O to unpin (not sure which should a good default
shortcut)
If user tries to close a pinned tab it's asked to confirm
If user tries to open a URL in a pinned tab it receives a message with a
information that the tab is pinned and ignore the openurl command
Preserve the pinned information across restart if session is activated

Missing:
Visual indication of the tab being pinned
Tab appearance being distinct over other tabs
Make pinned tabs to be the firsts on the tab bar

This is not ready, but it would be good to get some feedback earlier
2016-11-06 15:52:23 +01:00
499 changed files with 28635 additions and 24081 deletions

View File

@@ -5,13 +5,15 @@ cache:
build: off
environment:
PYTHONUNBUFFERED: 1
PYTHON: C:\Python36\python.exe
matrix:
- TESTENV: py34
- TESTENV: unittests-frozen
- TESTENV: py36-pyqt59
- TESTENV: pylint
install:
- C:\Python27\python -u scripts\dev\ci\appveyor_install.py
- '%PYTHON% -m pip install -U pip'
- '%PYTHON% -m pip install -r misc\requirements\requirements-tox.txt'
- 'set PATH=%PATH%;C:\Python36'
test_script:
- C:\Python34\Scripts\tox -e %TESTENV%
- '%PYTHON% -m tox -e %TESTENV%'

7
.codecov.yml Normal file
View File

@@ -0,0 +1,7 @@
coverage:
status:
project: off
patch: off
changes: off
comment: off

View File

@@ -11,6 +11,7 @@ exclude = .*,__pycache__,resources.py
# (for pytest's __tracebackhide__)
# F401: Unused import
# N802: function name should be lowercase
# N806: variable in function should be lowercase
# P101: format string does contain unindexed parameters
# P102: docstring does contain unindexed parameters
# P103: other string does contain unindexed parameters
@@ -35,13 +36,15 @@ max-complexity = 12
putty-auto-ignore = True
putty-ignore =
/# pylint: disable=invalid-name/ : +N801,N806
/# pylint: disable=wildcard-import/ : +F403
/# pragma: no mccabe/ : +C901
tests/*/test_*.py : +D100,D101,D401
tests/unit/browser/webkit/test_history.py : +N806
tests/conftest.py : +F403
tests/unit/browser/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
# FIXME:conf
tests/unit/completion/test_models.py : +F821
copyright-check = True
copyright-regexp = # Copyright [\d-]+ .*
copyright-min-file-size = 110

8
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,8 @@
qutebrowser/browser/history.py @rcorre
qutebrowser/completion/* @rcorre
qutebrowser/misc/sql.py @rcorre
tests/end2end/features/completion.feature @rcorre
tests/end2end/features/test_completion_bdd.py @rcorre
tests/unit/browser/test_history.py @rcorre
tests/unit/completion/* @rcorre
tests/unit/misc/test_sql.py @rcorre

9
.github/CONTRIBUTING.asciidoc vendored Normal file
View File

@@ -0,0 +1,9 @@
- Before you start to work on something, please leave a comment on the relevant
issue (or open one). This makes sure there is no duplicate work done.
- Either run the testsuite locally, or keep an eye on Travis CI / AppVeyor
after pushing changes.
See the full contribution docs for details:
include::../doc/contributing.asciidoc[]

View File

@@ -1,2 +1,2 @@
<!-- If this is a bug report, please remember to mention your version info from
the `qute:version` page or `qutebrowser --version` -->
`:open qute:version` or `qutebrowser --version` -->

5
.gitignore vendored
View File

@@ -15,11 +15,8 @@ __pycache__
/qutebrowser/3rdparty
/doc/*.html
/README.html
/CHANGELOG.html
/CONTRIBUTING.html
/FAQ.html
/INSTALL.html
/qutebrowser/html/doc/
/qutebrowser/html/*.html
/.venv*
/.coverage
/htmlcov

View File

@@ -31,20 +31,23 @@ disable=no-self-use,
bare-except,
eval-used,
exec-used,
file-ignored,
wrong-import-order,
ungrouped-imports,
redefined-variable-type,
suppressed-message,
too-many-return-statements,
duplicate-code,
wrong-import-position
wrong-import-position,
no-else-return,
# https://github.com/PyCQA/pylint/issues/1698
unsupported-membership-test,
unsupported-assignment-operation,
unsubscriptable-object
[BASIC]
function-rgx=[a-z_][a-z0-9_]{2,50}$
const-rgx=[A-Za-z_][A-Za-z0-9_]{0,30}$
method-rgx=[a-z_][A-Za-z0-9_]{1,50}$
attr-rgx=[a-z_][a-z0-9_]{0,30}$
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{1,30}|(__.*__))$
argument-rgx=[a-z_][a-z0-9_]{0,30}$
variable-rgx=[a-z_][a-z0-9_]{0,30}$
docstring-min-length=3
@@ -52,12 +55,9 @@ no-docstring-rgx=(^_|^main$)
[FORMAT]
max-line-length=79
ignore-long-lines=(<?https?://|^# Copyright 201\d|# (pylint|flake8): disable=)
ignore-long-lines=(<?https?://|^# Copyright 201\d)
expected-line-ending-format=LF
[SIMILARITIES]
min-similarity-lines=8
[VARIABLES]
dummy-variables-rgx=_.*
@@ -68,12 +68,11 @@ 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,
qutebrowser.browser.downloads.UnsupportedAttribute
ignored-modules=PyQt5,PyQt5.QtWebKit
ignored-classes=_CountingAttr
[IMPORTS]
# WORKAROUND
# For some reason, pylint doesn't know about some Python 3 modules on
# AppVeyor...
known-standard-library=faulthandler,http,enum,tokenize,posixpath,importlib,types

1
.pyup.yml Normal file
View File

@@ -0,0 +1 @@
schedule: "every week on monday"

View File

@@ -1,14 +1,11 @@
sudo: required
sudo: false
dist: trusty
language: generic
language: python
group: edge
python: 3.6
matrix:
include:
- os: linux
env: TESTENV=py34-cov
- os: linux
env: DOCKER=debian-jessie
services: docker
- os: linux
env: DOCKER=archlinux
services: docker
@@ -16,36 +13,32 @@ matrix:
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: linux
python: 3.5
env: TESTENV=py35-pyqt59
- os: linux
env: TESTENV=py36-pyqt59-cov
- os: osx
env: TESTENV=py36 OSX=elcapitan
osx_image: xcode7.3
env: TESTENV=py36 OSX=sierra
osx_image: xcode8.3
language: generic
# https://github.com/qutebrowser/qutebrowser/issues/2013
# - os: osx
# env: TESTENV=py35 OSX=yosemite
# osx_image: xcode6.4
- os: linux
env: TESTENV=pylint
env: TESTENV=pylint PYTHON=python3.6
- os: linux
env: TESTENV=flake8
- os: linux
env: TESTENV=docs
addons:
apt:
packages:
- asciidoc
- os: linux
env: TESTENV=vulture
- os: linux
@@ -56,10 +49,9 @@ matrix:
env: TESTENV=check-manifest
- os: linux
env: TESTENV=eslint
allow_failures:
- os: osx
env: TESTENV=py36 OSX=elcapitan
osx_image: xcode7.3
language: node_js
python: null
node_js: node
fast_finish: true
cache:
@@ -67,12 +59,9 @@ cache:
- $HOME/.cache/pip
- $HOME/build/qutebrowser/qutebrowser/.cache
before_install:
# We need to do this so we pick up the system-wide python properly
- 'export PATH="/usr/bin:$PATH"'
install:
- bash scripts/dev/ci/travis_install.sh
- ulimit -c unlimited
script:
- bash scripts/dev/ci/travis_run.sh
@@ -80,6 +69,9 @@ script:
after_success:
- '[[ $TESTENV == *-cov ]] && codecov -e TESTENV -X gcov'
after_failure:
- bash scripts/dev/ci/travis_backtrace.sh
notifications:
webhooks:
- https://buildtimetrend.herokuapp.com/travis

View File

@@ -1,356 +0,0 @@
Installing qutebrowser
======================
On Debian / Ubuntu
------------------
qutebrowser should run on these systems:
* Debian jessie or newer
* Ubuntu Trusty (14.04 LTS) or newer
* Any other distribution based on these (e.g. Linux Mint 17+)
Unfortunately there is no Debian package in the official repos yet, but installing qutebrowser is
still relatively easy!
You can use packages that are built for every release or build it yourself from git.
Using the packages
~~~~~~~~~~~~~~~~~~
Install the dependencies via apt-get:
----
# 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 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:
----
# dpkg -i python3-pypeg2_*_all.deb
# dpkg -i qutebrowser_*_all.deb
----
Build it from git
~~~~~~~~~~~~~~~~~
Install the dependencies via apt-get:
[NOTE]
==========================
On Debian, it's recommended to install the Qt packages from the
https://wiki.debian.org/DebianExperimental[experimental] repository as those
are a much newer version of Qt which is more stable.
Add the following line to your `/etc/apt/sources.list`:
----
deb http://ftp.debian.org/debian experimental main
----
Then install the packages like this:
----
# apt-get update
# apt-get install -t experimental python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python3-sip python3-dev
# apt-get install python-tox
----
It's also recommended to pin those packages to receive updates by creating a
file `/etc/apt/preferences.d/qutebrowser` with the following contents:
----
Package: python3-pyqt5* libqt5*
Pin: release a=experimental
Pin-Priority: 800
----
==========================
For distributions other than Debian or if you prefer to not use the
experimental repo:
----
# 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
repository (rather than a release):
----
# apt-get install asciidoc source-highlight
$ python3 scripts/asciidoc2html.py
----
If video or sound don't seem to work, try installing the gstreamer plugins:
----
# apt-get install gstreamer1.0-plugins-{bad,base,good,ugly}
----
Then <<tox,install qutebrowser via tox>>.
On Fedora
---------
qutebrowser is available in the official repositories for Fedora 22 and newer.
----
# dnf install qutebrowser
----
On Archlinux
------------
qutebrowser is available in the official [community] repository.
----
# pacman -S qutebrowser
----
There is also a -git version available in the AUR:
https://aur.archlinux.org/packages/qutebrowser-git/[qutebrowser-git].
You can install it using `makepkg` like this:
----
$ git clone https://aur.archlinux.org/qutebrowser-git.git
$ cd qutebrowser-git
$ makepkg -si
$ cd ..
$ rm -r qutebrowser-git
----
or you could use an AUR helper, e.g. `yaourt -S qutebrowser-git`.
If video or sound don't seem to work, try installing the gstreamer plugins:
----
# pacman -S gst-plugins-{base,good,bad,ugly} gst-libav
----
On Gentoo
---------
qutebrowser is available in the main repository and can be installed with:
----
# emerge -av qutebrowser
----
Make sure you have `python3_4` in your `PYTHON_TARGETS`
(`/etc/portage/make.conf`) and rebuild your system (`emerge -uDNav @world`) if
necessary.
If video or sound don't seem to work, try installing the gstreamer plugins:
----
# emerge -av gst-plugins-{base,good,bad,ugly,libav}
----
On Void Linux
-------------
qutebrowser is available in the official repositories and can be installed
with:
----
# xbps-install qutebrowser
----
On NixOS
--------
Nixpkgs collection contains `pkgs.qutebrowser` since June 2015. You can install
it with:
----
$ nix-env -i qutebrowser
----
On openSUSE
-----------
There are prebuilt RPMs available for Tumbleweed and Leap 42.1:
http://software.opensuse.org/download.html?project=home%3Aarpraher&package=qutebrowser[One Click Install]
Or add the repo manually:
----
# zypper addrepo http://download.opensuse.org/repositories/home:arpraher/openSUSE_Tumbleweed/home:arpraher.repo
# zypper refresh
# 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
----------
There are different ways to install qutebrowser on Windows:
Prebuilt binaries
~~~~~~~~~~~~~~~~~
Prebuilt standalone packages and MSI installers
https://github.com/qutebrowser/qutebrowser/releases[are built] for every
release.
https://chocolatey.org/packages/qutebrowser[Chocolatey package]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* PackageManagement PowerShell module
----
PS C:\> Install-Package qutebrowser
----
* Chocolatey's client
----
C:\> choco install qutebrowser
----
Manual install
~~~~~~~~~~~~~~
* Use the installer from http://www.python.org/downloads[python.org] to get
Python 3 (be sure to install pip).
* Use the installer from
http://www.riverbankcomputing.com/software/pyqt/download5[Riverbank computing]
to get Qt and PyQt5.
* Install https://testrun.org/tox/latest/index.html[tox] via
https://pip.pypa.io/en/latest/[pip]:
----
$ pip install tox
----
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/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.
==== Homebrew
----
$ brew install qt5
$ pip3 install qutebrowser
----
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.
----
$ brew install qt5 --with-qtwebkit
$ brew install -s pyqt5
$ pip3 install qutebrowser
----
Packagers
---------
There are example .desktop and icon files provided. They would go in the
standard location for your distro (`/usr/share/applications` and
`/usr/share/pixmaps` for example).
The normal `setup.py install` doesn't install these files, so you'll have to do
it as part of the packaging process.
[[tox]]
Installing qutebrowser with tox
-------------------------------
First of all, clone the repository using http://git-scm.org/[git] and switch
into the repository folder:
----
$ git clone https://github.com/qutebrowser/qutebrowser.git
$ cd qutebrowser
----
Then run tox inside the qutebrowser repository to set up a
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.
You can then create a simple wrapper script to start qutebrowser somewhere in
your `$PATH` (e.g. `/usr/local/bin/qutebrowser` or `~/bin/qutebrowser`):
----
#!/bin/bash
~/path/to/qutebrowser/.venv/bin/python3 -m qutebrowser "$@"
----
If you are developing on qutebrowser, you may want to redirect it to a local
config:
----
#!/bin/bash
~/path/to/qutebrowser/.venv/bin/python3 -m qutebrowser -c .qutebrowser-local "$@"
----
Updating
~~~~~~~~
When you updated your local copy of the code (e.g. by pulling the git repo, or
extracting a new version), the virtualenv should automatically use the updated
code. However, if dependencies got added, this won't be reflected in the
virtualenv. Thus it's recommended to run the following command to recreate the
virtualenv:
----
$ tox -r -e mkvenv
----

View File

View File

@@ -8,15 +8,16 @@ graft icons
graft doc/img
graft misc/apparmor
graft misc/userscripts
recursive-include scripts *.py
recursive-include scripts *.py *.sh
include qutebrowser/utils/testfile
include qutebrowser/git-commit-id
include COPYING doc/* README.asciidoc CONTRIBUTING.asciidoc FAQ.asciidoc INSTALL.asciidoc CHANGELOG.asciidoc
include qutebrowser.desktop
include LICENSE doc/* README.asciidoc
include misc/qutebrowser.desktop
include requirements.txt
include tox.ini
include qutebrowser.py
include misc/cheatsheet.svg
include qutebrowser/config/configdata.yml
prune www
prune scripts/dev
@@ -26,24 +27,19 @@ exclude scripts/asciidoc2html.py
exclude doc/notes
recursive-exclude doc *.asciidoc
include doc/qutebrowser.1.asciidoc
include doc/changelog.asciidoc
prune tests
prune qutebrowser/3rdparty
prune misc/requirements
prune misc/docker
exclude .editorconfig
exclude pytest.ini
exclude qutebrowser.rcc
exclude .coveragerc
exclude .pylintrc
exclude qutebrowser/javascript/.eslintrc.yaml
exclude qutebrowser/javascript/.eslintignore
exclude doc/help
exclude .appveyor.yml
exclude .travis.yml
exclude codecov.yml
exclude .pydocstylerc
exclude .*
exclude misc/appveyor_install.py
exclude misc/qutebrowser.spec
exclude .flake8
exclude misc/qutebrowser.nsi
global-exclude __pycache__ *.pyc *.pyo

View File

@@ -9,9 +9,8 @@ qutebrowser
// QUTE_WEB_HIDE
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/qutebrowser/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/LICENSE"]
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/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"]
@@ -36,11 +35,8 @@ Downloads
---------
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).
See link:INSTALL.asciidoc[INSTALL] for detailed instructions on how to get
qutebrowser running for various platforms.
page] for available downloads and the link:doc/install.asciidoc[INSTALL] file for
detailed instructions on how to get qutebrowser running on various platforms.
Documentation
-------------
@@ -48,14 +44,15 @@ Documentation
In addition to the topics mentioned in this README, the following documents are
available:
* A https://qutebrowser.org/img/cheatsheet-big.png[key binding cheatsheet]: +
* 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]
* link:CHANGELOG.asciidoc[Change Log]
* https://www.shortcutfoo.com/app/dojos/qutebrowser[Free training course] to remember those key bindings
* link:doc/faq.asciidoc[Frequently asked questions]
* link:doc/help/configuring.asciidoc[Configuring qutebrowser]
* link:doc/contributing.asciidoc[Contributing to qutebrowser]
* link:doc/install.asciidoc[Installing qutebrowser]
* link:doc/changelog.asciidoc[Change Log]
* link:doc/stacktrace.asciidoc[Reporting segfaults]
* link:doc/userscripts.asciidoc[How to write userscripts]
@@ -70,14 +67,18 @@ 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[].
There's also an https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[announce-only mailinglist]
at mailto:qutebrowser-announce@lists.qutebrowser.org[] (the announcements also
get sent to the general qutebrowser@ list).
If you're a reddit user, there's a
https://www.reddit.com/r/qutebrowser/[/r/qutebrowser] subreddit there.
Contributions / Bugs
--------------------
You want to contribute to qutebrowser? Awesome! Please read
link:CONTRIBUTING.asciidoc[the contribution guidelines] for details and
link:doc/contributing.asciidoc[the contribution guidelines] for details and
useful hints.
If you found a bug or have a feature request, you can report it in several
@@ -97,29 +98,36 @@ Requirements
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 (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
* http://www.python.org/[Python] 3.5 or newer (3.6 recommended)
* http://qt.io/[Qt] 5.7.1 or newer with the following modules:
- QtCore / qtbase
- QtQuick (part of qtbase in some distributions)
- QtSQL (part of qtbase in some distributions)
- QtOpenGL
- QtWebEngine, or
- QtWebKit - only the
link:https://github.com/annulen/webkit/wiki[updated fork] (5.212) is
supported
* http://www.riverbankcomputing.com/software/pyqt/intro[PyQt] 5.7.0 or newer
(5.9 recommended) for Python 3
* https://pypi.python.org/pypi/setuptools/[pkg_resources/setuptools]
* http://fdik.org/pyPEG/[pyPEG2]
* http://jinja.pocoo.org/[jinja2]
* http://pygments.org/[pygments]
* http://pyyaml.org/wiki/PyYAML[PyYAML]
* http://www.attrs.org/[attrs]
The following libraries are optional and provide a better user experience:
The following libraries are optional:
* http://cthedot.de/cssutils/[cssutils]
* http://cthedot.de/cssutils/[cssutils] (for an improved `:download --mhtml`
with QtWebKit).
* On Windows, https://pypi.python.org/pypi/colorama/[colorama] for colored log
output.
* http://asciidoc.org/[asciidoc] to generate the documentation for the `:help`
command, when using the git repository (rather than a release).
To generate the documentation for the `:help` command, when using the git
repository (rather than a release), http://asciidoc.org/[asciidoc] is needed.
On Windows, https://pypi.python.org/pypi/colorama/[colorama] is needed to
display colored log output.
See link:INSTALL.asciidoc[INSTALL] for directions on how to install qutebrowser
and its dependencies.
See link:doc/install.asciidoc[the documentation] for directions on how to
install qutebrowser and its dependencies.
Donating
--------
@@ -140,206 +148,62 @@ get in touch!
Authors
-------
Contributors, sorted by the number of commits in descending order:
qutebrowser's primary author is Florian Bruhin (The Compiler), but qutebrowser
wouldn't be what it is without the help of
https://github.com/qutebrowser/qutebrowser/graphs/contributors[hundreds of contributors]!
// QUTE_AUTHORS_START
* 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
* Kevin Velghe
* Raphael Pierzina
* Joel Torstensson
* Patric Schmitz
* Tarcisio Fedrizzi
* Claude
* Corentin Julé
* meles5
* Philipp Hansch
* Imran Sobir
* Panagiotis Ktistakis
* Artur Shaik
* Nathan Isom
* Thorsten Wißmann
* Austin Anderson
* Fritz Reichwald
* Jimmy
* Niklas Haas
* Maciej Wołczyk
* Spreadyy
* Alexey "Averrin" Nabrodov
* nanjekyejoannah
* avk
* ZDarian
* Milan Svoboda
* John ShaggyTwoDope Jenkins
* 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
* Samuel Walladge
* Peter Rice
* Ismail S
* Halfwit
* David Vogt
* Claire Cavanaugh
* rikn00
* kanikaa1234
* haitaka
* Nick Ginther
* Michał Góral
* Michael Ilsaas
* Martin Zimmermann
* Jussi Timperi
* Cosmin Popescu
* Brian Jackson
* thuck
* sbinix
* rsteube
* neeasade
* jnphilipp
* Tobias Patzl
* Stefan Tatschner
* 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
* 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
* Helen Sherwood-Taylor
* HalosGhost
* 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:
Additionally, the following people have contributed graphics:
* Jad/link:http://yelostudio.com[yelo] (new icon)
* WOFall (original icon)
* regines (key binding cheatsheet)
Thanks / Similar projects
-------------------------
Also, thanks to everyone who contributed to one of qutebrowser's
link:doc/backers.asciidoc[crowdfunding campaigns]!
Many projects with a similar goal as qutebrowser exist:
* http://portix.bitbucket.org/dwb/[dwb] (C, GTK+ with WebKit1, currently
http://www.reddit.com/r/linux/comments/2huqbc/dwb_abandoned/[unmaintained] -
main inspiration for qutebrowser)
* https://github.com/fanglingsu/vimb[vimb] (C, GTK+ with WebKit1, active)
* http://sourceforge.net/p/vimprobable/wiki/Home/[vimprobable] (C, GTK+ with
WebKit1, dead)
* http://surf.suckless.org/[surf] (C, GTK+ with WebKit1, active)
* https://mason-larobina.github.io/luakit/[luakit] (C/Lua, GTK+ with
WebKit1, not very active)
* http://pwmt.org/projects/jumanji/[jumanji] (C, GTK+ with WebKit1, not very
active)
* http://www.uzbl.org/[uzbl] (C, GTK+ with WebKit1/WebKit2, active)
* http://conkeror.org/[conkeror] (Javascript, Emacs-like, XULRunner/Gecko,
active)
* https://github.com/AeroNotix/lispkit[lispkit] (quite new, lisp, GTK+ with
WebKit, active)
* http://www.vimperator.org/[Vimperator] (Firefox addon)
* http://5digits.org/pentadactyl/[Pentadactyl] (Firefox addon)
* https://github.com/akhodakivskiy/VimFx[VimFx] (Firefox addon)
* https://github.com/1995eaton/chromium-vim[cVim] (Chrome/Chromium addon)
* http://vimium.github.io/[vimium] (Chrome/Chromium addon)
* https://chrome.google.com/webstore/detail/vichrome/gghkfhpblkcmlkmpcpgaajbbiikbhpdi?hl=en[ViChrome] (Chrome/Chromium addon)
* https://github.com/jinzhu/vrome[Vrome] (Chrome/Chromium addon)
Similar projects
----------------
Many projects with a similar goal as qutebrowser exist.
Most of them were inspirations for qutebrowser in some way, thanks for that!
Thanks as well to the following projects and people for helping me with
problems and helpful hints:
Active
~~~~~~
* http://eric-ide.python-projects.org/[eric5] / Detlev Offenbach
* https://code.google.com/p/devicenzo/[devicenzo]
* portix
* seir
* nitroxleecher
* https://fanglingsu.github.io/vimb/[vimb] (C, GTK+ with WebKit2)
* https://luakit.github.io/luakit/[luakit] (C/Lua, GTK+ with WebKit2)
* http://surf.suckless.org/[surf] (C, GTK+ with WebKit1/WebKit2)
* http://www.uzbl.org/[uzbl] (C, GTK+ with WebKit1/WebKit2)
* Chrome/Chromium addons:
https://github.com/1995eaton/chromium-vim[cVim],
http://vimium.github.io/[Vimium],
https://github.com/brookhong/Surfingkeys[Surfingkeys],
https://key.saka.io/[Saka Key]
* Firefox addons (based on WebExtensions):
https://addons.mozilla.org/en-GB/firefox/addon/vimium-ff/[Vimium-FF] (experimental),
https://key.saka.io[Saka Key],
https://github.com/cmcaine/tridactyl[Tridactyl] (in early development, working
on a https://bugzilla.mozilla.org/show_bug.cgi?id=1215061[better API] for
keyboard integration in Firefox).
Also, thanks to:
Inactive
~~~~~~~~
* Everyone contributing to the link:doc/backers.asciidoc[crowdfunding].
* Everyone who had the patience to test qutebrowser before v0.1.
* Everyone triaging/fixing my bugs in the
https://bugreports.qt.io/secure/Dashboard.jspa[Qt bugtracker]
* Everyone answering my questions on http://stackoverflow.com/[Stack Overflow]
and in IRC.
* All the projects which were a great help while developing qutebrowser.
* https://bitbucket.org/portix/dwb[dwb] (C, GTK+ with WebKit1,
https://bitbucket.org/portix/dwb/pull-requests/22/several-cleanups-to-increase-portability/diff[unmaintained] -
main inspiration for qutebrowser)
* http://sourceforge.net/p/vimprobable/wiki/Home/[vimprobable] (C, GTK+ with
WebKit1)
* http://pwmt.org/projects/jumanji/[jumanji] (C, GTK+ with WebKit1)
* http://conkeror.org/[conkeror] (Javascript, Emacs-like, XULRunner/Gecko)
* Firefox addons (not based on WebExtensions or no recent activity):
http://www.vimperator.org/[Vimperator],
http://5digits.org/pentadactyl/[Pentadactyl],
https://github.com/akhodakivskiy/VimFx[VimFx],
https://github.com/shinglyu/QuantumVim[QuantumVim]
* Chrome/Chromium addons:
https://chrome.google.com/webstore/detail/vichrome/gghkfhpblkcmlkmpcpgaajbbiikbhpdi?hl=en[ViChrome],
https://github.com/jinzhu/vrome[Vrome]
License
-------
@@ -355,7 +219,7 @@ 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 this program. If not, see <http://www.gnu.org/licenses/>.
along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
pdf.js
------

View File

@@ -1,9 +0,0 @@
status:
project:
enabled: no
patch:
enabled: no
changes:
enabled: no
comment: off

View File

@@ -1,13 +1,135 @@
Crowdfunding backers
====================
2017
----
Mid-2017, qutebrowser had its
https://www.kickstarter.com/projects/the-compiler/qutebrowser-v10-with-per-domain-settings[second crowdfunding]
with the goal of implementing the new config system and releasing v1.0.
Thanks a lot to the following people who contributed to it:
Gold sponsors
~~~~~~~~~~~~~
TODO
Silver sponsors
~~~~~~~~~~~~~~~
TODO
Other sponsors
~~~~~~~~~~~~~~
TODO: people with t-shirts or higher pledge levels
- 7scan
- Alex Suykov
- Alexey Zhikhartsev
- Allan Nordhøy
- Anirudh Sanjeev
- Anssi Puustinen
- Benedikt Steindorf
- Bernardo Kuri
- Blaise Duszynski
- Bostan
- Bruno Oliveira
- Colin Jacobs
- Daniel Andersson
- Danilo
- David Beley
- David Hollings
- David Parrish
- Derin Yarsuvat
- Dmytro Kostiuchenko
- Frederik Thorøe
- G4v4g4i
- Gyula Teleki
- H
- Hosaka
- Iordanis Grigoriou
- Isaac Sandaljian
- Jakub Podeszwik
- Jamie Anderson
- Jasper Woudenberg
- Jens Højgaard
- Johannes
- John Baber-Lucero
- Jonas Schürmann
- Kenichiro Ito
- Kenny Low
- Lars Ivar Igesund
- Lucas Aride Moulin
- Ludovic Chabant
- Lukas Gierth
- Marulkan
- Matthew Chun-Lum
- Matthew Cronen
- Matthew Quigley
- Michael Schönwälder
- Mika Kutila
- Mitchell Stokes
- Nathan Howell
- Nathan Schlehlein
- Noël Zindel
- Obri
- Patrik Peng
- Peter DiMarco
- Peter Rice
- Philipp Middendorf
- Pkill9
- Prescott
- Robotichead
- Roshless
- Ryan Ellis
- Ryan P Deslandes
- Sam Doshi
- Sam Stone
- Sean Herman
- Sebastian Frysztak
- Shelby Cruver
- SirCmpwn
- Soham Pal
- Stewart Webb
- Sven Reinecke
- Tom Bass
- Tomas Slusny
- Tomasz Kramkowski
- Tommy Thomas
- Vasilij Schneidermann
- Vlaaaaaaad
- beanieuptop
- demure
- evenorbert
- fishss
- gsnewmark
- guillermohs9
- hubcaps
- lobachevsky
- neodarz
- nihlaeth
- notbenh
- patrick suwanvithaya
- pyratebeard
- randm_dave
- sabreman
- toml
- vimja
- wiz
- 43 Anonymous
2016
----
Mid-2016, qutebrowser did run a http://igg.me/at/qutebrowser[crowdfunding] for
QtWebEngine support in qutebrowser.
Thanks a lot to the following people who contributed to it:
Gold sponsors
-------------
~~~~~~~~~~~~~
- Chris Salzberg
- Clayton Craft
@@ -16,7 +138,7 @@ Gold sponsors
- 1 Anonymous
Day sponsors
------------
~~~~~~~~~~~~
- Agent 42
- Iggy Jackson
@@ -28,7 +150,7 @@ Day sponsors
- 4 Anonymous
Other sponsors
--------------
~~~~~~~~~~~~~~
- AP M
- Alessandro Balzano

View File

@@ -4,7 +4,8 @@ Change Log
// http://keepachangelog.com/
All notable changes to this project will be documented in this file.
This project adheres to http://semver.org/[Semantic Versioning].
This project adheres to http://semver.org/[Semantic Versioning], though minor
breaking changes (such as renamed commands) can happen in minor releases.
// tags:
// `Added` for new features.
@@ -14,6 +15,282 @@ This project adheres to http://semver.org/[Semantic Versioning].
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
v1.0.2
------
Fixes
~~~~~
- Fix workaround for black screens or crashes with Nvidia cards
- Handle a filesystem going read-only gracefully
- Fix crash when setting `fonts.monospace`
- Fix list options not being modifyable via `.append()` in `config.py`
- Mark the content.notifications setting as QtWebKit only correctly
- Fix wrong rendering of keys like `<back>` in the completion
Changed
~~~~~~~
- Nicer error messages and other minor improvements
v1.0.1
------
Fixes
~~~~~
- Fixed starting after customizing `fonts.tabs` or `fonts.debug_console`.
- Fixed starting with old PyQt versions compiled against newer Qt versions.
- Fixed check for PyQt version to correctly enforce 5.7 (not 5.2).
v1.0.0
------
Major changes
~~~~~~~~~~~~~
- Dependency changes:
* Support for legacy QtWebKit (before 5.212 which is
https://github.com/annulen/webkit/wiki[distributed independently from Qt])
is dropped.
* Support for Python 3.4 is dropped.
* Support for Qt before 5.7.1 and PyQt before 5.7 is dropped.
* New dependency on the QtSql module and Qt sqlite support.
* New dependency on the http://www.attrs.org/[attrs] project (packaged as
`python-attr` in some distributions).
* The depedency on PyOpenGL (when using QtWebEngine) got removed. Note
that PyQt5.QtOpenGL is still a dependency.
* PyQt5.QtOpenGL is now always required, even with QtWebKit.
- The QtWebEngine backend is now used by default. Note this means that
QtWebEngine now should be a required dependency, and QtWebKit (if new enough)
should be changed to an optional dependency.
- Completely rewritten configuration system which ignores the old config file.
See link:qute://help/configuring.html[] for details.
- Various documentation files got moved to the doc/ subfolder;
`qutebrowser.desktop` got moved to misc/.
- `:set` now doesn't support toggling/cycling values anymore, that functionality
got moved to `:config-cycle`.
- New completion engine based on sqlite, which allows to complete
the entire browsing history. The default for
`completion.web_history_max_items` got changed to `-1` (unlimited). If the
completion is too slow on your machine, try setting it to a few 1000 items.
Added
~~~~~
- QtWebEngine: Spell checking support, see the `spellcheck.languages` setting.
- New `qt.args` setting to pass additional arguments to Qt/Chromium.
- New `backend` setting to select the backend to use.
Together with the previous setting, this should make most wrapper scripts
unnecessary.
- qutebrowser can now be set as the default browser on macOS.
- New config commands:
* `:config-cycle` to cycle an option between multiple values.
* `:config-unset` to remove a configured option.
* `:config-clear` to remove all configured options.
* `:config-source` to (re-)read a `config.py` file.
* `:config-edit` to open the `config.py` file in an editor.
* `:config-write-py` to write a `config.py` template file.
- New `:version` command which opens `qute://version`.
- New back/forward indicator in the statusbar.
- New `bindings.key_mappings` setting to map keys to other keys.
- QtWebEngine: Support for proxy authentication.
Changed
~~~~~~~
- Using `:download` now uses the page's title as filename.
- Using `:back` or `:forward` with a count now skips intermediate pages.
- When there are multiple messages shown, the timeout is increased.
- `:search` now only clears the search if one was displayed before, so pressing
`<Escape>` doesn't un-focus inputs anymore.
- Pinned tabs now adjust to their text's width, so the `tabs.width.pinned`
setting got removed.
- `:set-cmd-text` now has a `--run-on-count` argument to run the underlying
command directly if a count was given.
- `:scroll-perc` got renamed to `:scroll-to-perc`.
Removed
~~~~~~~
- Migrating QtWebEngine data written by versions before 2016-11-15 (before
v0.9.0) is now not supported anymore.
- Upgrading qutebrowser with a version older than v0.4.0 still running now won't
work properly anymore.
- The `--harfbuzz` and `--relaxed-config` commandline arguments got dropped.
Fixes
~~~~~
- Exiting fullscreen via `:fullscreen` or buttons on a page now
restores the correct previous window state (maximized/fullscreen).
- When `input.insert_mode.auto_load` is set, background tabs now don't enter
insert mode anymore.
- The keybinding help widget now works correctly when using keybindings with a
count.
- The `window.hide_wayland_decoration` setting now works correctly again.
v0.11.1
-------
Fixes
~~~~~
- Fixed empty space being shown after tabs in the tabbar in some cases.
- Fixed `:restart` in private browsing mode.
- Fixed printing on macOS.
- Closing a pinned tab via mouse now also prompts for confirmation.
- The "try again" button on error pages works correctly again.
- :spawn -u -d is now disallowed.
- :spawn -d shows error messages correctly now.
v0.11.0
-------
New dependencies
~~~~~~~~~~~~~~~~
- New dependency on `PyQt5.QtOpenGL` if QtWebEngine is used. QtWebEngine depends
on QtOpenGL already, but on distributions packaging split PyQt5 wrappers, the
wrappers for QtOpenGL are now required.
- New dependency on `PyOpenGL` if QtWebEngine is used.
Added
~~~~~
- Private browsing is now implemented for QtWebEngine, *and changed its
behavior*: The `general -> private-browsing` setting now only applies to newly
opened windows, and you can use the `-p` flag to `:open` to open a private
window.
- New "pinned tabs" feature, with a new `:tab-pin` command (bound
to `<Ctrl-p>` by default).
- (QtWebEngine) Implemented `:follow-selected`.
- New `:clear-messages` command to clear shown messages.
- New `ui -> keyhint-delay` setting to configure the delay until
the keyhint overlay pops up.
- New `-s` option for `:open` to force a HTTPS scheme.
- `:debug-log-filter` now accepts `none` as an argument to clear any log
filters.
- New `--debug-flag` argument which replaces `--debug-exit` and
`--pdb-postmortem`.
- New `tabs -> favicon-scale` option to scale up/down favicons.
- `colors -> statusbar.bg/fg.private` and `.command.private` to
customize statusbar colors for private windows.
- New `{private}` field displaying `[Private Mode]` for
`ui -> window-title-format` and `tabs -> title-format`.
- (QtWebEngine) Proxy support with Qt 5.7.1 (already was supported for 5.8 and
newer)
Changed
~~~~~~~
- To prevent elaborate phishing attacks, the Punycode version (`xn--*`) is now
shown in addition to the decoded version for international domain names
(IDN).
- Starting with legacy QtWebKit now shows a warning message.
*With the next release, support for it will be removed.*
- The Windows releases are redone from scratch, which means:
* They now use the new QtWebEngine backend
* The bundled Qt is updated from 5.5 to 5.9
* The bundled Python is updated from 3.4 to 3.6
* They are now generated with PyInstaller instead of cx_Freeze
* The installer is now generated using NSIS instead of being a MSI
- Improved `qute://history` page (with lazy loading)
- Crash reports are not public anymore.
- Paths like `C:` are now treated as absolute paths on Windows for downloads,
and invalid paths are handled properly.
- Comments in the config file are now placed before the individual options
instead of being before sections.
- Messages are now hidden when clicked.
- stdin is now closed immediately for processes spawned from qutebrowser.
- When `ui -> message-timeout` is set to 0, messages are now never cleared.
- Middle/right-clicking the blank parts of the tab bar (when vertical) now
closes the current tab.
- The adblocker now also blocks non-GET requests (e.g. POST).
- `javascript:` links can now be hinted.
- `:view-source`, `:tab-clone` and `:navigate --tab` now don't open the tab as
"explicit" anymore, i.e. (with the default settings) open it next to the
active tab.
- `qute:*` pages now use `qute://*` instead (e.g. `qute://version` instead of
`qute:version`), but the old versions are automatically redirected.
- Texts in prompts are now selectable.
- The default level for `:messages` is now `info`, not `error`
- Trying to focus the currently focused tab with `:tab-focus` now focuses the
last viewed tab.
- (QtWebEngine) With Qt 5.9, `content -> cookies-store` can now be set without
a restart.
- (QtWebEngine) With Qt 5.9, better error messages are now shown for failed
downloads.
- (QtWebEngine) The underlying Chromium version is now shown in the version
info.
- (QtWebKit) Renderer process crashes now show an error page on Qt 5.9 or newer.
- (QtWebKit) storage -> offline-web-application-storage` got renamed to `...-cache`
- (QtWebKit) PAC now supports SOCKS5 as type.
Fixed
~~~~~
- The macOS .dmg is now built against Qt 5.9 which fixes various
important issues (such as not being able to type dead keys).
- Fixed crash with `:download` on PyQt 5.9.
- Cloning a page without history doesn't crash anymore.
- When a download results in a HTTP error, it now shows the error correctly
instead of crashing.
- Pressing ctrl-c while a config error is shown works as intended now.
- When the key config isn't writable, we now show an error instead of crashing.
- Fixed crash when unbinding an unbound key in the key config.
- Fixed crash when using `:debug-log-filter` when `--filter` wasn't given on startup.
- Fixed crash with some invalid setting values.
- Continuing a search after clearing it now works correctly.
- The tabbar and completion should now be more consistently and correctly
styled with various system styles.
- Applying styiles in `qt5ct` now shouldn't crash anymore.
- The validation for colors in stylesheets is now less strict,
allowing for all valid Qt values.
- `data:` URLs now aren't added to the history anymore.
- Accidentally starting with Python 2 now shows a proper error message again.
- For some people, running some userscripts crashed - this should now be fixed.
- Various other rare crashes should now be fixed.
- The settings documentation was truncated with v0.10.1 which should now be
fixed.
- Scrolling to an anchor in a background tab now works correctly, and javascript
gets the correct window size for background tabs.
- (QtWebEngine) Added a workaround for a black screen with some setups
- (QtWebEngine) Starting with Nouveau graphics now shows an error message
instead of crashing in Qt.
- (QtWebEngine) Retrying downloads now shows an error instead of crashing.
- (QtWebEngine) Cloning a view-source tab now doesn't crash anymore.
- (QtWebEngine) `window.navigator.userAgent` is now set correctly when
customizing the user agent.
- (QtWebEngine) HTML fullscreen is now tracked for each tab separately, which
means it's not possible anymore to accidentally get stuck in fullscreen state
by closing a tab with a fullscreen video.
- (QtWebEngine) `:scroll-page` with `--bottom-navigate` now works correctly.
- (QtWebKit) The HTTP cache is disabled on Qt 5.7.1 and 5.8 now as it leads to
frequent crashes due to a Qt bug.
- (QtWebKit) Fixed Crash when a PAC file returns an invalid value.
v0.10.1
-------
Changed
~~~~~~~
- `--qt-arg` and `--qt-flag` can now also be used to pass arguments to Chromium when using QtWebEngine.
Fixed
~~~~~
- URLs are now redacted properly (username/password, and path/query for HTTPS) when using Proxy Autoconfig with QtWebKit
- Crash when updating adblock lists with invalid UTF8-chars in them
- Fixed the web inspector with QtWebEngine
- Version checks when starting qutebrowser now also take the Qt version PyQt was compiled against into account
- Hinting a input now doesn't select existing text anymore with QtWebKit
- The cursor now moves to the end when input elements are selected with QtWebEngine
- Download suffixes like (1) are now correctly stripped with QtWebEngine
- Crash when trying to print a tab which was closed in the meantime
- Crash when trying to open a file twice on Windows
v0.10.0
-------
@@ -36,7 +313,7 @@ Added
- 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
- macOS builds are back, and built with QtWebEngine
Changed
~~~~~~~
@@ -52,6 +329,18 @@ Changed
- `network -> proxy` can also be set to `pac+file://...` now to
use a local proxy autoconfig file (on QtWebKit)
Removed
~~~~~~~
- (QtWebKit) Various rarely customized settings were removed:
* `ui -> css-media-type` (defaults to desktop)
* `general -> site-specific-quirks` (now always turned on)
* `storage -> offline-storage-default-quota` (defaults to 5MB)
* `storage -> offline-web-application-cache-quota` (defaults to no quota)
* `storage -> object-cache-capacities` (default depends on disk space)
* `content -> css-regions` (now always turned off)
* `storage -> offline-storage-database` (merged into `storage -> local-storage`)
Fixed
~~~~~
@@ -326,7 +615,7 @@ 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
- Hide Harfbuzz warning with the macOS .app
v0.8.0
------
@@ -689,7 +978,7 @@ Fixed
- Fixed scrolling to the very left/right with `:scroll-perc`.
- Using an external editor should now work correctly with some funny chars
(U+2028/U+2029/BOM).
- Movements in caret mode now should work correctly on OS X and Windows.
- Movements in caret mode now should work correctly on macOS and Windows.
- Fixed upgrade from earlier config versions.
- Fixed crash when killing a running userscript.
- Fixed characters being passed through when shifted with
@@ -764,7 +1053,7 @@ Changed
- The completion widget doesn't show a border anymore.
- The tabbar doesn't display ugly arrows anymore if there isn't enough space
for all tabs.
- Some insignificant Qt warnings which were printed on OS X are now hidden.
- Some insignificant Qt warnings which were printed on macOS are now hidden.
- Better support for Qt 5.5 and Python 3.5.
Fixed
@@ -875,7 +1164,7 @@ Fixed
- Fixed AssertionError when closing many windows quickly.
- Various fixes for deprecated key bindings and auto-migrations.
- Workaround for qutebrowser not starting when there are NUL-bytes in the history (because of a currently unknown bug).
- Fixed handling of keybindings containing Ctrl/Meta on OS X.
- Fixed handling of keybindings containing Ctrl/Meta on macOS.
- Fixed crash when downloading a URL without filename (e.g. magnet links) via "Save as...".
- Fixed exception when starting qutebrowser with `:set` as argument.
- Fixed horrible completion performance when the `shrink` option was set.
@@ -973,7 +1262,7 @@ Changed
- Add a `:search` command in addition to `/foo` so it's more visible and can be used from scripts.
- Various improvements to documentation, logging, and the crash reporter.
- Expand `~` to the users home directory with `:run-userscript`.
- Improve the userscript runner on Linux/OS X by using `QSocketNotifier`.
- Improve the userscript runner on Linux/macOS by using `QSocketNotifier`.
- Add luakit-like `gt`/`gT` keybindings to cycle through tabs.
- Show default value for config values in the completion.
- Clone tab icon, tab text and zoom level when cloning tabs.
@@ -993,7 +1282,7 @@ Changed
* `init_venv.py` and `run_checks.py` have been replaced by http://tox.readthedocs.org/[tox]. Install tox and run `tox -e mkvenv` instead.
* The tests now use http://pytest.org/[pytest]
* Many new tests added
* Mac Mini buildbot to run the tests on OS X.
* Mac Mini buildbot to run the tests on macOS.
* Coverage recording via http://nedbatchelder.com/code/coverage/[coverage.py].
* New `--pdb-postmortem argument` to drop into the pdb debugger on exceptions.
* Use https://github.com/ionelmc/python-hunter[hunter] for line tracing instead of a selfmade solution.
@@ -1129,7 +1418,7 @@ Fixed
* Fix rare exception when a key is pressed shortly after opening a window
* Fix exception with certain invalid URLs like `http:foo:0`
* Work around Qt bug which renders checkboxes on OS X unusable
* Work around Qt bug which renders checkboxes on macOS unusable
* Fix exception when a local files can't be read in `:adblock-update`
* Hide 2 more Qt warnings.
* Add `!important` to hint CSS so websites don't override the hint look
@@ -1165,7 +1454,7 @@ Changes
* Set zoom to default instead of 100% with `:zoom`/`=`.
* Adjust page zoom if default zoom changed.
* Force tabs to be focused on `:undo`.
* Replace manual installation instructions on OS X with homebrew/macports.
* Replace manual installation instructions on macOS with homebrew/macports.
* Allow min-/maximizing of print preview on Windows.
* Various documentation improvements.
* Various other small improvements and cleanups.

View File

@@ -39,8 +39,13 @@ pointers:
* https://github.com/qutebrowser/qutebrowser/labels/easy[Issues which should
be easy to solve]
* https://github.com/qutebrowser/qutebrowser/labels/not%20code[Issues which
require little/no coding]
* https://github.com/qutebrowser/qutebrowser/labels/component%3A%20docs[Documentation issues which require little/no coding]
If you prefer C++ or Javascript to Python, see the relevant issues which involve
work in those languages:
* https://github.com/qutebrowser/qutebrowser/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3Ac%2B%2B[C++] (mostly work on Qt, the library behind qutebrowser)
* https://github.com/qutebrowser/qutebrowser/issues?q=is%3Aopen+is%3Aissue+label%3Ajavascript[JavaScript]
There are also some things to do if you don't want to write code:
@@ -92,25 +97,24 @@ unittests and several linters/checkers.
Currently, the following tox environments are available:
* Tests using https://www.pytest.org[pytest]:
- `py34`: Run pytest for python-3.4.
- `py35`: Run pytest for python-3.5.
- `py34-cov`: Run pytest for python-3.4 with code coverage report.
- `py35-cov`: Run pytest for python-3.5 with code coverage report.
- `py35`, `py36`: Run pytest for python 3.5/3.6 with the system-wide PyQt.
- `py36-pyqt57`, ..., `py36-pyqt59`: Run pytest with the given PyQt version (`py35-*` also works).
- `py36-pyqt59-cov`: Run with coverage support (other Python/PyQt versions work too).
* `flake8`: Run https://pypi.python.org/pypi/flake8[flake8] checks:
https://pypi.python.org/pypi/pyflakes[pyflakes],
https://pypi.python.org/pypi/pep8[pep8],
https://pypi.python.org/pypi/mccabe[mccabe]
https://pypi.python.org/pypi/mccabe[mccabe].
* `vulture`: Run https://pypi.python.org/pypi/vulture[vulture] to find
unused code portions.
* `pylint`: Run http://pylint.org/[pylint] static code analysis.
* `pydocstyle`: Check
https://www.python.org/dev/peps/pep-0257/[PEP257] compliance with
https://github.com/PyCQA/pydocstyle[pydocstyle]
https://github.com/PyCQA/pydocstyle[pydocstyle].
* `pyroma`: Check packaging practices with
https://pypi.python.org/pypi/pyroma/[pyroma]
https://pypi.python.org/pypi/pyroma/[pyroma].
* `eslint`: Run http://eslint.org/[ESLint] javascript checker.
* `check-manifest`: Check MANIFEST.in completeness with
https://github.com/mgedmin/check-manifest[check-manifest]
https://github.com/mgedmin/check-manifest[check-manifest].
* `mkvenv`: Bootstrap a virtualenv for testing.
* `misc`: Run `scripts/misc_checks.py` to check for:
- untracked git files
@@ -127,7 +131,7 @@ 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, then add the
* If you think you have a good reason to suppress a message, then add the
following comment:
+
----
@@ -175,7 +179,7 @@ In the _scripts/_ subfolder there's a `run_profile.py` which profiles the code
and shows a graphical representation of what takes how much time.
It uses the built-in Python
https://docs.python.org/3.4/library/profile.html[cProfile] module and can show
https://docs.python.org/3.6/library/profile.html[cProfile] module and can show
the output in four different ways:
* Raw profile file (`--profile-tool=none`)
@@ -214,7 +218,7 @@ Documentation of used Python libraries:
* http://pygments.org/docs/[pygments]
* http://fdik.org/pyPEG/index.html[pyPEG2]
* http://pythonhosted.org/setuptools/[setuptools]
* http://cx-freeze.readthedocs.org/en/latest/overview.html[cx_Freeze]
* http://www.pyinstaller.org/[PyInstaller]
* https://pypi.python.org/pypi/colorama[colorama]
Related RFCs and standards:
@@ -286,7 +290,7 @@ There are some exceptions to that:
* `QThread` is used instead of Python threads because it provides signals and
slots.
* `QProcess` is used instead of Python's `subprocess`
* `QProcess` is used instead of Python's `subprocess`.
* `QUrl` is used instead of storing URLs as string, see the
<<handling-urls,handling URLs>> section for details.
@@ -307,7 +311,7 @@ carefully be checked.
* Methods of Qt objects have certain maximum values based on their
underlying C++ types.
+
To avoid passing too large of a numeric parameter to a Qt function, all
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).
@@ -321,7 +325,7 @@ dictionaries which map object names to the actual long-living objects.
There are currently these object registries, also called 'scopes':
* The `global` scope, with objects which are used globally (`config`,
`cookie-jar`, etc.)
`cookie-jar`, etc.).
* The `tab` scope with objects which are per-tab (`hintmanager`, `webview`,
etc.). Passing this scope to `objreg.get()` selects the object in the currently
focused tab by default. A tab can be explicitly selected by passing
@@ -430,14 +434,14 @@ def foo(bar: int, baz=True):
----
Possible values:
- A callable (`int`, `float`, etc.): Gets called to validate/convert the
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]`
- A callable (`int`, `float`, etc.): Gets called to validate/convert the 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]`.
You can customize how an argument is handled using the `@cmdutils.argument`
decorator *after* `@cmdutils.register`. This can, for example, be used to
decorator *after* `@cmdutils.register`. This can, for example, be used to
customize the flag an argument should get:
[source,python]
@@ -464,10 +468,11 @@ For `typing.Union` types, the given `choices` are only checked if other types
The following arguments are supported for `@cmdutils.argument`:
- `flag`: Customize the short flag (`-x`) the argument will get.
- `win_id=True`: Mark the argument as special window ID argument
- `count=True`: Mark the argument as special count argument
- `hide=True`: Hide the argument from the documentation
- `completion`: A `usertypes.Completion` member to use as completion.
- `win_id=True`: Mark the argument as special window ID argument.
- `count=True`: Mark the argument as special count argument.
- `hide=True`: Hide the argument from the documentation.
- `completion`: A completion function (see `qutebrowser.completions.models.*`)
to use when completing arguments for the given command.
- `choices`: The allowed string choices for the argument.
The name of an argument will always be the parameter name, with any trailing
@@ -529,12 +534,12 @@ ____
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]
* Install https://www.python.org/downloads/release/python-362/[Python 3.6].
* Install PyQt via `pip install PyQt5`.
* Create a file at `C:\Windows\system32\python3.bat` with the following content (adjust the path as necessary):
`@C:\Python36\python %*`.
This will make the Python 3.6 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`.
@@ -546,6 +551,28 @@ Rebuilding the website
If you want to rebuild the website, run `./scripts/asciidoc2html.py --website <outputdir>`.
Chrome URLs
~~~~~~~~~~~
With the QtWebEngine backend, qutebrowser supports several chrome:// urls which
can be useful for debugging:
- chrome://appcache-internals/
- chrome://blob-internals/
- chrome://gpu/
- chrome://histograms/
- chrome://indexeddb-internals/
- chrome://media-internals/
- chrome://network-errors/
- chrome://serviceworker-internals/
- chrome://webrtc-internals/
- chrome://crash/ (crashes the current renderer process!)
- chrome://kill/ (kills the current renderer process!)
- chrome://gpucrash/ (crashes qutebrowser!)
- chrome://gpuhang/ (hangs qutebrowser!)
- chrome://gpuclean/ (crashes the current renderer process!)
- chrome://ppapiflashcrash/
- chrome://ppapiflashhang/
Style conventions
-----------------
@@ -631,7 +658,7 @@ New Qt release
https://bugreports.qt.io/issues/?jql=reporter%20%3D%20%22The%20Compiler%22%20ORDER%20BY%20fixVersion%20ASC[Qt bugtracker]
and make sure all bugs marked as resolved are actually fixed.
* Update own PKGBUILDs based on upstream Archlinux updates and rebuild.
* Update recommended Qt version in `README`
* Update recommended Qt version in `README`.
* Grep for `WORKAROUND` in the code and test if fixed stuff works without the
workaround.
* Check relevant
@@ -641,37 +668,32 @@ bugs] and check if they're fixed.
New PyQt release
~~~~~~~~~~~~~~~~
* See above
* Install new PyQt in Windows VM (32- and 64-bit)
* 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
* 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
* 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`
- `sed '/^#/d' conf/config/qutebrowser.conf > tests/unit/config/old_configs/qutebrowser-v0.x.y.conf`
- `rm -r conf`
- commit
* Adjust `__version_info__` in `qutebrowser/__init__.py`.
* Update changelog (remove *(unreleased)*)
* Run tests again
* Commit
* Update changelog (remove *(unreleased)*).
* Run tests again.
* Commit.
* Create annotated git tag (`git tag -s "v0.$x.$y" -m "Release v0.$x.$y"`)
* `git push origin`; `git push origin v0.$x.$y`
* Create annotated git tag (`git tag -s "v1.$x.$y" -m "Release v1.$x.$y"`).
* `git push origin`; `git push origin v1.$x.$y`.
* If committing on minor branch, cherry-pick release commit to master.
* Create release on github
* Create release on github.
* Mark the milestone at https://github.com/qutebrowser/qutebrowser/milestones
as closed.
* 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 and qutebrowser-announce mailinglist
* Linux: Run `python3 scripts/dev/build_release.py --upload v1.$x.$y`.
* Windows: Run `C:\Python36-32\python scripts\dev\build_release.py --asciidoc C:\Python27\python C:\asciidoc-8.6.9\asciidoc.py --upload v1.X.Y` (replace X/Y by hand).
* macOS: Run `python3 scripts/dev/build_release.py --upload v1.X.Y` (replace X/Y by hand).
* On server: Run `python3 scripts/dev/download_release.py v1.X.Y` (replace X/Y by hand).
* Update `qutebrowser-git` PKGBUILD if dependencies/install changed.
* Announce to qutebrowser and qutebrowser-announce mailinglist.

View File

@@ -72,8 +72,8 @@ Is there an adblocker?::
http://www.reddit.com/r/programming/comments/25j41u/adblock_pluss_effect_on_firefoxs_memory_usage/chhpomw[big
impact] on browsing speed and
https://blog.mozilla.org/nnethercote/2014/05/14/adblock-pluss-effect-on-firefoxs-memory-usage/[RAM
usage], so implementing it properly might take some time and won't be done
for v0.1 if at all.
usage], so implementing support for AdBlockPlus-like lists is currently not
a priority.
How do I play Youtube videos with mpv?::
You can easily add a key binding to play youtube videos inside a real video
@@ -124,6 +124,66 @@ When using quickmark, you can give them all names, like
`:open foodrecipes`, you will see a list of all the food recipe sites,
without having to remember the exact website title or address.
How do I use spell checking?::
Configuring spell checking in qutebrowser depends on the backend in use
(see https://github.com/qutebrowser/qutebrowser/issues/700[#700] for
a more detailed discussion).
+
For QtWebKit:
. Install https://github.com/QupZilla/qtwebkit-plugins[qtwebkit-plugins].
. Note: with QtWebKit reloaded you may experience some issues. See
https://github.com/QupZilla/qtwebkit-plugins/issues/10[#10].
. The dictionary to use is taken from the `DICTIONARY` environment variable.
The default is `en_US`. For example to use Dutch spell check set `DICTIONARY`
to `nl_NL`; you can't use multiple dictionaries or change them at runtime at
the moment.
(also see the README file for `qtwebkit-plugins`).
. Remember to install the hunspell dictionaries if you don't have them already
(most distros should have packages for this).
+
For QtWebEngine:
. Make sure your versions of PyQt and Qt are 5.8 or higher.
. Use `install_dict.py` script to install dictionaries.
Run the script with `-h` for the parameter description.
. Set `spellcheck.languages` to the desired list of languages, e.g.:
`:set spellcheck.languages "['en-US', 'pl-PL']"`
How do I use Tor with qutebrowser?::
Start tor on your machine, and do `:set network proxy socks://localhost:9050/`
in qutebrowser. Note this won't give you the same amount of fingerprinting
protection that the Tor Browser does, but it's useful to be able to access
`.onion` sites.
Why does J move to the next (right) tab, and K to the previous (left) one?::
One reason is because https://bitbucket.org/portix/dwb[dwb] did it that way,
and qutebrowser's keybindings are designed to be compatible with dwb's.
The rationale behind it is that J is "down" in vim, and K is "up", which
corresponds nicely to "next"/"previous". It also makes much more sense with
vertical tabs (e.g. `:set tabs position left`).
What's the difference between insert and passthrough mode?::
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
open an editor) while passthrough mode only has escape bound. It might also
be useful to rebind escape to something else in passthrough mode only, to be
able to send an escape keypress to the website.
Why takes it longer to open an URL in qutebrowser than in chromium?::
When opening an URL in an existing instance the normal qutebrowser
Python script is started and a few PyQt libraries need to be
loaded until it is detected that there is an instance running
where the URL is then passed to. This takes some time.
One workaround is to use this
https://github.com/qutebrowser/qutebrowser/blob/master/scripts/open_url_in_instance.sh[script]
and place it in your $PATH with the name "qutebrowser". This
script passes the URL via an unix socket to qutebrowser (if its
running already) using socat which is much faster and starts a new
qutebrowser if it is not running already. Also check if you want
to use webengine as backend in line 17 and change it to your
needs.
== Troubleshooting
Configuration not saved after modifying config.::
@@ -132,7 +192,7 @@ Configuration not saved after modifying config.::
Unable to view flash content.::
If you have flash installed for on your system, it's necessary to enable plugins
to use the flash plugin. Using the command `:set content allow-plugins true`
to use the flash plugin. Using the command `:set content.plugins true`
in qutebrowser will enable plugins. Packages for flash should
be provided for your platform or it can be obtained from
http://get.adobe.com/flashplayer/[Adobe].
@@ -144,25 +204,17 @@ Experiencing freezing on sites like duckduckgo and youtube.::
See https://github.com/qutebrowser/qutebrowser/issues/357[Issue #357]
for more details.
Experiencing segfaults (crashes) on Debian systems.::
For Debian it's highly recommended to install the `gstreamer0.10-plugins-base` package.
This is a workaround for a bug in Qt, it has been fixed upstream in Qt 5.4
More details can be found
https://bugs.webkit.org/show_bug.cgi?id=119951[here].
Segfaults on Facebook, Medium, Amazon, ...::
If you are on a Debian or Ubuntu based system, you might experience some crashes
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/qutebrowser/qutebrowser/blob/master/INSTALL.asciidoc#on-debian--ubuntu[INSTALL].
When using QtWebEngine, qutebrowser reports "Render Process Crashed" and the console prints a traceback on Gentoo Linux or another Source-Based Distro::
As stated in https://gcc.gnu.org/gcc-6/changes.html[GCC's Website] GCC 6 has introduced some optimizations that could break non-conforming codebases, like QtWebEngine. +
As a workaround, you can disable the nullpointer check optimization by adding the -fno-delete-null-pointer-checks flag while compiling. +
On gentoo, you just need to add it into your make.conf, like this: +
CFLAGS="... -fno-delete-null-pointer-checks"
CXXFLAGS="... -fno-delete-null-pointer-checks"
+
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
70 important bugs] have been fixed in QtWebKit. For Debian Jessie (using Qt 5.3.2)
it's still
https://bugreports.qt.io/browse/QTBUG-42417?jql=component%20%3D%20WebKit%20and%20resolution%20%3D%20Done%20and%20fixVersion%20in%20(5.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)[nearly
20 important bugs].
And then re-emerging qtwebengine with: +
emerge -1 qtwebengine
My issue is not listed.::
If you experience any segfaults or crashes, you can report the issue in

View File

@@ -1,5 +1,5 @@
// DO NOT EDIT THIS FILE DIRECTLY!
// It is autogenerated from docstrings by running:
// It is autogenerated by running:
// $ python3 scripts/dev/src2asciidoc.py
= Commands
@@ -31,6 +31,12 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|<<bookmark-load,bookmark-load>>|Load a bookmark.
|<<buffer,buffer>>|Select tab by index or url/title best match.
|<<close,close>>|Close the current window.
|<<config-clear,config-clear>>|Set all settings back to their default.
|<<config-cycle,config-cycle>>|Cycle an option between multiple values.
|<<config-edit,config-edit>>|Open the config.py file in the editor.
|<<config-source,config-source>>|Read a config.py file.
|<<config-unset,config-unset>>|Unset an option.
|<<config-write-py,config-write-py>>|Write the current configuration to a config.py file.
|<<download,download>>|Download a given URL, or current page if no URL given.
|<<download-cancel,download-cancel>>|Cancel the last/[count]th download.
|<<download-clear,download-clear>>|Remove all finished downloads from the list.
@@ -82,12 +88,13 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|<<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-pin,tab-pin>>|Pin/Unpin the current/[count]th tab.
|<<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).
|<<undo,undo>>|Re-open a closed tab.
|<<version,version>>|Show version information.
|<<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 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.
@@ -115,7 +122,7 @@ How many pages to go back.
[[bind]]
=== bind
Syntax: +:bind [*--mode* 'mode'] [*--force*] 'key' ['command']+
Syntax: +:bind [*--mode* 'mode'] [*--default*] 'key' ['command']+
Bind a key to a command.
@@ -125,9 +132,10 @@ Bind a key to a command.
==== optional arguments
* +*-m*+, +*--mode*+: A comma-separated list of modes to bind the key in (default: `normal`).
* +*-m*+, +*--mode*+: A comma-separated list of modes to bind the key in (default: `normal`). See `:help bindings.commands` for the
available modes.
* +*-f*+, +*--force*+: Rebind the key if it is already bound.
* +*-d*+, +*--default*+: If given, restore a default binding.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
@@ -183,20 +191,96 @@ Load a bookmark.
[[buffer]]
=== buffer
Syntax: +:buffer 'index'+
Syntax: +:buffer ['index']+
Select tab by index or url/title best match.
Focuses window if necessary.
Focuses window if necessary when index is given. If both index and count are given, use count.
==== positional arguments
* +'index'+: The [win_id/]index of the tab to focus. Or a substring in which case the closest match will be focused.
==== count
The tab index to focus, starting with 1.
[[close]]
=== close
Close the current window.
[[config-clear]]
=== config-clear
Syntax: +:config-clear [*--save*]+
Set all settings back to their default.
==== optional arguments
* +*-s*+, +*--save*+: If given, all configuration in autoconfig.yml is also removed.
[[config-cycle]]
=== config-cycle
Syntax: +:config-cycle [*--temp*] [*--print*] 'option' ['values' ['values' ...]]+
Cycle an option between multiple values.
==== positional arguments
* +'option'+: The name of the option.
* +'values'+: The values to cycle through.
==== optional arguments
* +*-t*+, +*--temp*+: Set value temporarily until qutebrowser is closed.
* +*-p*+, +*--print*+: Print the value after setting.
[[config-edit]]
=== config-edit
Syntax: +:config-edit [*--no-source*]+
Open the config.py file in the editor.
==== optional arguments
* +*-n*+, +*--no-source*+: Don't re-source the config file after editing.
[[config-source]]
=== config-source
Syntax: +:config-source [*--clear*] ['filename']+
Read a config.py file.
==== positional arguments
* +'filename'+: The file to load. If not given, loads the default config.py.
==== optional arguments
* +*-c*+, +*--clear*+: Clear current settings first.
[[config-unset]]
=== config-unset
Syntax: +:config-unset [*--temp*] 'option'+
Unset an option.
This sets an option back to its default and removes it from autoconfig.yml.
==== positional arguments
* +'option'+: The name of the option.
==== optional arguments
* +*-t*+, +*--temp*+: Don't touch autoconfig.yml.
[[config-write-py]]
=== config-write-py
Syntax: +:config-write-py [*--force*] [*--defaults*] ['filename']+
Write the current configuration to a config.py file.
==== positional arguments
* +'filename'+: The file to write to, or not given for the default config.py.
==== optional arguments
* +*-f*+, +*--force*+: Force overwriting existing files.
* +*-d*+, +*--defaults*+: Write the defaults instead of values configured via :set.
[[download]]
=== download
Syntax: +:download [*--mhtml*] [*--dest* 'dest'] ['url'] ['dest-old']+
@@ -280,7 +364,7 @@ Syntax: +:edit-url [*--bg*] [*--tab*] [*--window*] ['url']+
Navigate to a url formed in an external editor.
The editor which should be launched can be configured via the `general -> editor` config option.
The editor which should be launched can be configured via the `editor.command` config option.
==== positional arguments
* +'url'+: URL to edit; defaults to the current page url.
@@ -337,7 +421,7 @@ Show help about a command or setting.
* +'topic'+: The topic to show help for.
- :__command__ for commands.
- __section__\->__option__ for settings.
- __section__.__option__ for settings.
==== optional arguments
@@ -367,7 +451,7 @@ Start hinting.
- `normal`: Open the link.
- `current`: Open the link in the current tab.
- `tab`: Open the link in a new tab (honoring the
background-tabs setting).
`tabs.background_tabs` setting).
- `tab-fg`: Open the link in a new foreground tab.
- `tab-bg`: Open the link in a new background tab.
- `window`: Open the link in a new window.
@@ -401,13 +485,13 @@ Start hinting.
==== optional arguments
* +*-r*+, +*--rapid*+: Whether to do rapid hinting. This is only possible with targets `tab` (with background-tabs=true), `tab-bg`,
* +*-r*+, +*--rapid*+: Whether to do rapid hinting. This is only possible with targets `tab` (with `tabs.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.
- `letter`: Use the chars in the hints.chars setting.
- `word`: Use hint words based on the html elements and the
extra words.
@@ -544,7 +628,8 @@ For `increment` and `decrement`, the number to change the URL by. For `up`, the
[[open]]
=== open
Syntax: +:open [*--implicit*] [*--bg*] [*--tab*] [*--window*] ['url']+
Syntax: +:open [*--related*] [*--bg*] [*--tab*] [*--window*] [*--secure*] [*--private*]
['url']+
Open a URL in the current/[count]th tab.
@@ -554,11 +639,13 @@ If the URL contains newlines, each line gets opened in its own tab.
* +'url'+: The URL to open.
==== optional arguments
* +*-i*+, +*--implicit*+: If opening a new tab, treat the tab as implicit (like clicking on a link).
* +*-r*+, +*--related*+: If opening a new tab, position the tab as related to the current one (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.
* +*-s*+, +*--secure*+: Force HTTPS.
* +*-p*+, +*--private*+: Open a new window in private browsing mode.
==== count
The tab index to open the URL in.
@@ -628,8 +715,17 @@ Save the current page as a quickmark.
[[quit]]
=== quit
Syntax: +:quit [*--save*] ['session']+
Quit qutebrowser.
==== positional arguments
* +'session'+: The name of the session to save.
==== optional arguments
* +*-s*+, +*--save*+: When given, save the open windows even if auto_save.session is turned off.
[[record-macro]]
=== record-macro
Syntax: +:record-macro ['register']+
@@ -742,12 +838,13 @@ Load a session.
[[session-save]]
=== session-save
Syntax: +:session-save [*--current*] [*--quiet*] [*--force*] [*--only-active-window*]
[*--with-private*]
['name']+
Save a session.
==== positional arguments
* +'name'+: The name of the session. If not given, the session configured in general -> session-default-name is saved.
* +'name'+: The name of the session. If not given, the session configured in session_default_name is saved.
==== optional arguments
@@ -755,27 +852,27 @@ Save a session.
* +*-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.
* +*-p*+, +*--with-private*+: Include private windows.
[[set]]
=== set
Syntax: +:set [*--temp*] [*--print*] ['section'] ['option'] ['values' ['values' ...]]+
Syntax: +:set [*--temp*] [*--print*] ['option'] ['value']+
Set an option.
If the option name ends with '?', the value of the option is shown instead. If the option name ends with '!' and it is a boolean value, toggle it.
If the option name ends with '?', the value of the option is shown instead.
==== positional arguments
* +'section'+: The section where the option is in.
* +'option'+: The name of the option.
* +'values'+: The value to set, or the values to cycle through.
* +'value'+: The value to set.
==== optional arguments
* +*-t*+, +*--temp*+: Set value temporarily.
* +*-t*+, +*--temp*+: Set value temporarily until qutebrowser is closed.
* +*-p*+, +*--print*+: Print the value after setting.
[[set-cmd-text]]
=== set-cmd-text
Syntax: +:set-cmd-text [*--space*] [*--append*] 'text'+
Syntax: +:set-cmd-text [*--space*] [*--append*] [*--run-on-count*] 'text'+
Preset the statusbar to some text.
@@ -785,6 +882,11 @@ Preset the statusbar to some text.
==== optional arguments
* +*-s*+, +*--space*+: If given, a space is added to the end.
* +*-a*+, +*--append*+: If given, the text is appended to the current text.
* +*-r*+, +*--run-on-count*+: If given with a count, the command is run with the given count rather than setting the command text.
==== count
The count if given.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
@@ -830,15 +932,16 @@ Duplicate the current tab.
[[tab-close]]
=== tab-close
Syntax: +:tab-close [*--prev*] [*--next*] [*--opposite*]+
Syntax: +:tab-close [*--prev*] [*--next*] [*--opposite*] [*--force*]+
Close the current/[count]th tab.
==== optional arguments
* +*-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'.
* +*-o*+, +*--opposite*+: Force selecting the tab in the opposite direction of what's configured in 'tabs.select_on_remove'.
* +*-f*+, +*--force*+: Avoid confirmation for pinned tabs.
==== count
The tab index to close
@@ -891,13 +994,23 @@ How many tabs to switch forward.
[[tab-only]]
=== tab-only
Syntax: +:tab-only [*--prev*] [*--next*]+
Syntax: +:tab-only [*--prev*] [*--next*] [*--force*]+
Close all tabs except for the current one.
==== optional arguments
* +*-p*+, +*--prev*+: Keep tabs before the current.
* +*-n*+, +*--next*+: Keep tabs after the current.
* +*-f*+, +*--force*+: Avoid confirmation for pinned tabs.
[[tab-pin]]
=== tab-pin
Pin/Unpin the current/[count]th tab.
Pinning a tab shrinks it to the size of its title text. Attempting to close a pinned tab will cause a confirmation, unless --force is passed.
==== count
The tab index to pin or unpin
[[tab-prev]]
=== tab-prev
@@ -908,18 +1021,24 @@ How many tabs to switch back.
[[unbind]]
=== unbind
Syntax: +:unbind 'key' ['mode']+
Syntax: +:unbind [*--mode* 'mode'] 'key'+
Unbind a keychain.
==== positional arguments
* +'key'+: The keychain or special key (inside <...>) to unbind.
* +'mode'+: A comma-separated list of modes to unbind the key in (default: `normal`).
==== optional arguments
* +*-m*+, +*--mode*+: A mode to unbind the key in (default: `normal`). See `:help bindings.commands` for the available modes.
[[undo]]
=== undo
Re-open a closed tab (optionally skipping [count] closed tabs).
Re-open a closed tab.
[[version]]
=== version
Show version information.
[[view-source]]
=== view-source
@@ -929,15 +1048,6 @@ Show the source of the current page in a new tab.
=== window-only
Close all windows except for the current one.
[[wq]]
=== wq
Syntax: +:wq ['name']+
Save open pages and quit.
==== positional arguments
* +'name'+: The name of the session.
[[yank]]
=== yank
Syntax: +:yank [*--sel*] [*--keep*] ['what']+
@@ -995,6 +1105,7 @@ How many steps to zoom out.
|==============
|Command|Description
|<<clear-keychain,clear-keychain>>|Clear the currently entered key chain.
|<<clear-messages,clear-messages>>|Clear all message notifications.
|<<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.
@@ -1025,6 +1136,7 @@ How many steps to zoom out.
|<<move-to-start-of-line,move-to-start-of-line>>|Move the cursor or selection to the start of the line.
|<<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.
|<<nop,nop>>|Do nothing.
|<<open-editor,open-editor>>|Open an external editor with the currently selected form field.
|<<prompt-accept,prompt-accept>>|Accept the current prompt.
|<<prompt-item-focus,prompt-item-focus>>|Shift the focus of the prompt file completion menu to another item.
@@ -1048,8 +1160,8 @@ How many steps to zoom out.
|<<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.
|<<scroll-to-perc,scroll-to-perc>>|Scroll to a specific percentage of the page.
|<<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.
@@ -1059,6 +1171,10 @@ How many steps to zoom out.
=== clear-keychain
Clear the currently entered key chain.
[[clear-messages]]
=== clear-messages
Clear all message notifications.
[[click-element]]
=== click-element
Syntax: +:click-element [*--target* 'target'] [*--force-event*] 'filter' 'value'+
@@ -1268,11 +1384,15 @@ Move the cursor or selection to the start of previous block.
==== count
How many blocks to move.
[[nop]]
=== nop
Do nothing.
[[open-editor]]
=== open-editor
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.
The editor which should be launched can be configured via the `editor.command` config option.
[[prompt-accept]]
=== prompt-accept
@@ -1433,6 +1553,8 @@ Syntax: +:scroll 'direction'+
Scroll the current tab in the given direction.
Note you can use `:run-with-count` to have a keybinding with a bigger scroll increment.
==== positional arguments
* +'direction'+: In which direction to scroll (up/down/left/right/top/bottom).
@@ -1459,9 +1581,22 @@ Scroll the frame page-wise.
==== count
multiplier
[[scroll-perc]]
=== scroll-perc
Syntax: +:scroll-perc [*--horizontal*] ['perc']+
[[scroll-px]]
=== scroll-px
Syntax: +:scroll-px 'dx' 'dy'+
Scroll the current tab by 'count * dx/dy' pixels.
==== positional arguments
* +'dx'+: How much to scroll in x-direction.
* +'dy'+: How much to scroll in y-direction.
==== count
multiplier
[[scroll-to-perc]]
=== scroll-to-perc
Syntax: +:scroll-to-perc [*--horizontal*] ['perc']+
Scroll to a specific percentage of the page.
@@ -1476,19 +1611,6 @@ The percentage can be given either as argument or as count. If no percentage is
==== count
Percentage to scroll.
[[scroll-px]]
=== scroll-px
Syntax: +:scroll-px 'dx' 'dy'+
Scroll the current tab by 'count * dx/dy' pixels.
==== positional arguments
* +'dx'+: How much to scroll in x-direction.
* +'dy'+: How much to scroll in y-direction.
==== count
multiplier
[[search-next]]
=== search-next
Continue the search to the ([count]th) next term.
@@ -1529,6 +1651,7 @@ These commands are mainly intended for debugging. They are hidden if qutebrowser
|<<debug-clear-ssl-errors,debug-clear-ssl-errors>>|Clear remembered SSL error answers.
|<<debug-console,debug-console>>|Show the debugging console.
|<<debug-crash,debug-crash>>|Crash for debugging purposes.
|<<debug-dump-history,debug-dump-history>>|Dump the history to a file in the old pre-SQL format.
|<<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.
@@ -1563,6 +1686,15 @@ Crash for debugging purposes.
==== positional arguments
* +'typ'+: either 'exception' or 'segfault'.
[[debug-dump-history]]
=== debug-dump-history
Syntax: +:debug-dump-history 'dest'+
Dump the history to a file in the old pre-SQL format.
==== positional arguments
* +'dest'+: Where to write the file to.
[[debug-dump-page]]
=== debug-dump-page
Syntax: +:debug-dump-page [*--plain*] 'dest'+
@@ -1591,7 +1723,8 @@ Syntax: +:debug-log-filter 'filters'+
Change the log filter for console logging.
==== positional arguments
* +'filters'+: A comma separated list of logger names.
* +'filters'+: A comma separated list of logger names. Can also be "none" to clear any existing filters.
[[debug-log-level]]
=== debug-log-level
@@ -1646,7 +1779,7 @@ Syntax: +:debug-webaction 'action'+
Execute a webaction.
See http://doc.qt.io/qt-5/qwebpage.html#WebAction-enum for the available actions.
Available actions: http://doc.qt.io/archives/qt-5.5/qwebpage.html#WebAction-enum (WebKit) http://doc.qt.io/qt-5/qwebenginepage.html#WebAction-enum (WebEngine)
==== positional arguments
* +'action'+: The action to execute, e.g. MoveToNextChar.

View File

@@ -0,0 +1,369 @@
Configuring qutebrowser
=======================
IMPORTANT: qutebrowser's configuration system was completely rewritten in
September 2017. This information is not applicable to older releases, and older
information elsewhere might be outdated. **If you had an old configuration
around and upgraded, this page will automatically open once**. To view it at a
later time, use the `:help` command.
Migrating older configurations
------------------------------
qutebrowser does no automatic migration for the new configuration. However,
there's a special link:qute://configdiff/old[configdiff] page in qutebrowser,
which will show you the changes you did in your old configuration, compared to
the old defaults.
Other changes in default settings:
- `<Up>` and `<Down>` in the completion now navigate through command history
instead of selecting completion items. You can get back the old behavior by
doing:
+
----
:bind -f -m command <Up> completion-item-focus prev
:bind -f -m command <Down> completion-item-focus next
----
- The default for `completion.web_history_max_items` is now set to `-1`, showing
an unlimited number of items in the completion for `:open` as the new
sqlite-based completion is much faster. If the `:open` completion is too slow
on your machine, set an appropriate limit again.
Configuring qutebrowser via the user interface
----------------------------------------------
The easy (but less flexible) way to configure qutebrowser is using its user
interface or command line. Changes you make this way are immediately active
(with the exception of a few settings, where this is pointed out in the
documentation) and are persisted in an `autoconfig.yml` file.
The `autoconfig.yml` file is located in the "config" folder listed on the
link:qute://version[] page. On macOS, the "auto config" folder is used, which is
different from where hand-written config files are kept.
However, **do not** edit `autoconfig.yml` by hand. Instead, see the next
section.
If you want to customize many settings, you can open the link:qute://settings[]
page by running `:set` without any arguments, where all settings are listed and
customizable.
Using the link:commands.html#set[`:set`] command and command completion, you
can quickly set settings interactively, for example `:set tabs.position left`.
To get more help about a setting, use e.g. `:help tabs.position`.
To bind and unbind keys, you can use the link:commands.html#bind[`:bind`] and
link:commands.html#unbind[`:unbind`] commands:
- Binding the key chain `,v` to the `:spawn mpv {url}` command:
`:bind ,v spawn mpv {url}`
- Unbinding the same key chain: `:unbind ,v`
Key chains starting with a comma are ideal for custom bindings, as the comma key
will never be used in a default keybinding.
See the help pages linked above (or `:help :bind`, `:help :unbind`) for more
information.
Other useful commands for config manipulation are
link:commands.html#config-unset[`:config-unset`] to reset a value to its default,
link:commands.html#config-clear[`:config-clear`] to reset the entire configuration,
and link:commands.html#config-cycle[`:config-cycle`] to cycle a setting between
different values.
Configuring qutebrowser via config.py
-------------------------------------
For more powerful configuration possibilities, you can create a `config.py`
file. Since it's a Python file, you have much more flexibility for
configuration. Note that qutebrowser will never touch this file - this means
you'll be responsible for updating it when upgrading to a newer qutebrowser
version.
You can run `:config-edit` inside qutebrowser to open the file in your editor,
`:config-source` to reload the file (`:config-edit` does this automatically), or
`:config-write-py --defaults` to write a template file to work with.
The file should be located in the "config" location listed on
link:qute://version[], which is typically `~/.config/qutebrowser/config.py` on
Linux, `~/.qutebrowser/config.py` on macOS, and
`%APPDATA%/qutebrowser/config.py` on Windows.
Two global objects are pre-defined when running `config.py`: `c` and `config`.
Changing settings
~~~~~~~~~~~~~~~~~
While you can set settings using the `config.set()` method (which is explained
in the next section), it's easier to use the `c` shorthand object to easily set
settings like this:
.config.py:
[source,python]
----
c.tabs.position = "left"
c.completion.shrink = True
----
Note that qutebrowser does some Python magic so it's able to warn you about
mistyped config settings. As an example, if you do `c.tabs.possition = "left"`,
you'll get an error when starting.
See the link:settings.html[settings help page] for all available settings. The
accepted values depend on the type of the option. Commonly used are:
- Strings: `c.tabs.position = "left"`
- Booleans: `c.completion.shrink = True`
- Integers: `c.messages.timeout = 5000`
- Dictionaries:
* `c.headers.custom = {'X-Hello': 'World', 'X-Awesome': 'yes'}` to override
any other values in the dictionary.
* `c.aliases['foo'] = 'message-info foo'` to add a single value.
- Lists:
* `c.url.start_pages = ["https://www.qutebrowser.org/"]` to override any
previous elements.
* `c.url.start_pages.append("https://www.python.org/")` to add a new value.
Any other config types (e.g. a color) are specified as a string. The only
exception is the `Regex` type, which can take either a string (with an `r`
prefix to preserve backslashes) or a Python regex object:
- `c.hints.next_regexes.append(r'\bvor\b')`
- `c.hints.prev_regexes.append(re.compile(r'\bzurück\b'))`
If you want to read a setting, you can use the `c` object to do so as well:
`c.colors.tabs.even.bg = c.colors.tabs.odd.bg`.
Using strings for setting names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to set settings based on their name as a string, use the
`config.set` method:
.config.py:
[source,python]
----
# Equivalent to:
# c.content.javascript.enabled = False
config.set('content.javascript.enabled', False)
----
To read a setting, use the `config.get` method:
[source,python]
----
# Equivalent to:
# color = c.colors.completion.fg
color = config.get('colors.completion.fg')
----
Binding keys
~~~~~~~~~~~~
While it's possible to change the `bindings.commands` setting to bind keys, it's
preferred to use the `config.bind` command. Doing so ensures the commands are
valid and normalizes different expressions which map to the same key.
For details on how to specify keys and the available modes, see the
link:settings.html#bindings.commands[documentation] for the `bindings.commands`
setting.
To bind a key:
.config.py:
[source,python]
----
config.bind('<Ctrl-v>', 'spawn mpv {url}')
----
To bind a key in a mode other than `'normal'`, add a `mode` argument:
[source,python]
----
config.bind('<Ctrl-y>', 'prompt-yes', mode='prompt')
----
To unbind a key (either a key which has been bound before, or a default binding):
[source,python]
----
config.unbind('<Ctrl-v>', mode='normal')
----
To bind keys without modifiers, specify a key chain to bind as a string. Key
chains starting with a comma are ideal for custom bindings, as the comma key
will never be used in a default keybinding.
[source,python]
----
config.bind(',v', 'spawn mpv {url}')
----
To suppress loading of any default keybindings, you can set
`c.bindings.default = {}`.
Loading `autoconfig.yml`
~~~~~~~~~~~~~~~~~~~~~~~~
By default, all customization done via `:set`, `:bind` and `:unbind` is
temporary as soon as a `config.py` exists. The settings done that way are always
saved in the `autoconfig.yml` file, but you'll need to explicitly load it in
your `config.py` by doing:
.config.py:
[source,python]
----
config.load_autoconfig()
----
If you do so at the top of your file, your `config.py` settings will take
precedence as they overwrite the settings done in `autoconfig.yml`.
Importing other modules
~~~~~~~~~~~~~~~~~~~~~~~
You can import any module from the
https://docs.python.org/3/library/index.html[Python standard library] (e.g.
`import os.path`), as well as any module installed in the environment
qutebrowser is run with.
If you have an `utils.py` file in your qutebrowser config folder, you can import
that via `import utils` as well.
While it's in some cases possible to import code from the qutebrowser
installation, doing so is unsupported and discouraged.
Getting the config directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you need to get the qutebrowser config directory, you can do so by reading
`config.configdir`. Similarily, you can get the qutebrowser data directory via
`config.datadir`.
This gives you a https://docs.python.org/3/library/pathlib.html[`pathlib.Path`
object], on which you can use `/` to add more directory parts, or `str(...)` to
get a string:
.config.py:
[source,python]
----
print(str(config.configdir / 'config.py')
----
Handling errors
~~~~~~~~~~~~~~~
If there are errors in your `config.py`, qutebrowser will try to apply as much
of it as possible, and show an error dialog before starting.
qutebrowser tries to display errors which are easy to understand even for people
who are not used to writing Python. If you see a config error which you find
confusing or you think qutebrowser could handle better, please
https://github.com/qutebrowser/qutebrowser/issues[open an issue]!
Recipes
~~~~~~~
Reading a YAML file
^^^^^^^^^^^^^^^^^^^
To read a YAML config like this:
.config.yml:
----
tabs.position: left
tabs.show: switching
----
You can use:
.config.py:
[source,python]
----
import yaml
with (config.configdir / 'config.yml').open() as f:
yaml_data = yaml.load(f)
for k, v in yaml_data.items():
config.set(k, v)
----
Reading a nested YAML file
^^^^^^^^^^^^^^^^^^^^^^^^^^
To read a YAML file with nested values like this:
.colors.yml:
----
colors:
statusbar:
normal:
bg: lime
fg: black
url:
fg: red
----
You can use:
.config.py:
[source,python]
----
import yaml
with (config.configdir / 'colors.yml').open() as f:
yaml_data = yaml.load(f)
def dict_attrs(obj, path=''):
if isinstance(obj, dict):
for k, v in obj.items():
yield from dict_attrs(v, '{}.{}'.format(path, k) if path else k)
else:
yield path, obj
for k, v in dict_attrs(yaml_data):
config.set(k, v)
----
Note that this won't work for values which are dictionaries.
Binding chained commands
^^^^^^^^^^^^^^^^^^^^^^^^
If you have a lot of chained commands you want to bind, you can write a helper
to do so:
[source,python]
----
def bind_chained(key, *commands):
config.bind(key, ' ;; '.join(commands))
bind_chained('<Escape>', 'clear-keychain', 'search')
----
Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^
If you use an editor with flake8 integration which complains about `c` and `config` being undefined, you can use:
[source,python]
----
c = c # noqa: F821
config = config # noqa: F821
----
For type annotation support (note that those imports aren't guaranteed to be
stable across qutebrowser versions):
[source,python]
----
from qutebrowser.config.configfiles import ConfigAPI # noqa: F401
from qutebrowser.config.config import ConfigContainer # noqa: F401
config = config # type: ConfigAPI # noqa: F821
c = c # type: ConfigContainer # noqa: F821
----

View File

@@ -7,12 +7,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:../faq.html[Frequently asked questions]
* link:../changelog.html[Change Log]
* link:commands.html[Documentation of commands]
* link:configuring.html[Configuring qutebrowser]
* link:settings.html[Documentation of settings]
* link:../userscripts.html[How to write userscripts]
* link:../../CONTRIBUTING.html[Contributing to qutebrowser]
* link:../contributing.html[Contributing to qutebrowser]
Getting help
------------

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 46 KiB

380
doc/install.asciidoc Normal file
View File

@@ -0,0 +1,380 @@
Installing qutebrowser
======================
toc::[]
NOTE: qutebrowser recently had some bigger dependency changes for v1.0.0, which
means those instructions might be out of date in some places.
https://github.com/qutebrowser/qutebrowser/blob/master/doc/contributing.asciidoc[Please help]
updating them if you notice something being broken!
On Debian / Ubuntu
------------------
How to install qutebrowser depends a lot on the version of Debian/Ubuntu you're
running.
Debian Jessie / Ubuntu 14.04 LTS / Linux Mint < 18
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Those distributions only have Python 3.4 and a too old Qt version available,
while qutebrowser requires Python 3.5 and Qt 5.7.1 or newer.
It should be possible to install Python 3.5 e.g. from the
https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa[deadsnakes PPA] or via_ipca
https://github.com/pyenv/pyenv[pyenv], but nobody tried that yet.
If you get qutebrowser running on those distributions, please
https://github.com/qutebrowser/qutebrowser/blob/master/doc/contributing.asciidoc[contribute]
to update this documentation!
Ubuntu 16.04 LTS / Linux Mint 18
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ubuntu 16.04 doesn't come with an up-to-date engine (a new enough QtWebKit, or
QtWebEngine). However, it comes with Python 3.5, so you can
<<tox,install qutebrowser via tox>>.
Debian Stretch / Ubuntu 17.04 and newer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Those versions come with QtWebEngine in the repositories. This makes it possible
to install qutebrowser via the Debian package.
Install the dependencies via apt-get:
----
# apt install python-tox python3-{lxml,pyqt5,sip,jinja2,pygments,yaml,attr} python3-pyqt5.qt{webengine,quick,opengl,sql} libqt5sql5-sqlite
----
Get the qutebrowser package from the
https://github.com/qutebrowser/qutebrowser/releases[release page] and download
the https://qutebrowser.org/python3-pypeg2_2.15.2-1_all.deb[PyPEG2 package].
Install the packages:
----
# dpkg -i python3-pypeg2_*_all.deb
# dpkg -i qutebrowser_*_all.deb
----
Some additional hints:
- Alternatively, you can <<tox,install qutebrowser via tox>> to get a newer
QtWebEngine version.
- If running from git, run the following to generate the documentation for the
`:help` command:
+
----
# apt-get install --no-install-recommends asciidoc source-highlight
$ python3 scripts/asciidoc2html.py
----
- If you prefer using QtWebKit, there's an up-to-date version available in
Debian experimental, or from http://repo.paretje.be/unstable/[this repository]
for Debian Stretch.
- If video or sound don't work with QtWebKit, try installing the gstreamer plugins:
+
----
# apt-get install gstreamer1.0-plugins-{bad,base,good,ugly}
----
On Fedora
---------
qutebrowser is available in the official repositories for Fedora 22 and newer.
----
# dnf install qutebrowser
----
It's also recommended to install `python3-qt5-webengine` and start with `--backend
webengine` to use the new backend. v1.0.0 (which is not in the Fedora repos
currently) uses QtWebEngine by default.
On Archlinux
------------
qutebrowser is available in the official [community] repository.
----
# pacman -S qutebrowser
----
There is also a -git version available in the AUR:
https://aur.archlinux.org/packages/qutebrowser-git/[qutebrowser-git].
You can install it using `makepkg` like this:
----
$ git clone https://aur.archlinux.org/qutebrowser-git.git
$ cd qutebrowser-git
$ makepkg -si
$ cd ..
$ rm -r qutebrowser-git
----
or you could use an AUR helper, e.g. `yaourt -S qutebrowser-git`.
If video or sound don't work with QtWebKit, try installing the gstreamer plugins:
----
# pacman -S gst-plugins-{base,good,bad,ugly} gst-libav
----
On Gentoo
---------
The Gentoo packages (even the live version) are lagging behind a lot and are
effectively unmaintained. If you want to create and maintain an official
qutebrowser overlay for Gentoo, please mailto:mail@qutebrowser.org[get in
touch.]
It's recommended to <<tox,install qutebrowser via tox>> instead.
To get an up-to-date QtWebKit, you can use
https://gist.github.com/annulen/309569fb61e5d64a703c055c1e726f71[this ebuild].
If video or sound don't work with QtWebKit, try installing the gstreamer
plugins:
----
# emerge -av gst-plugins-{base,good,bad,ugly,libav}
----
To be able to play videos with proprietary codecs with QtWebEngine, you will
need to turn off the `bindist` flag for `dev-qt/qtwebengine`.
See the https://wiki.gentoo.org/wiki/Qutebrowser#USE_flags[Gentoo Wiki] for
more information.
On Void Linux
-------------
qutebrowser is available in the official repositories and can be installed
with:
----
# xbps-install qutebrowser
----
It's currently recommended to install `python3-PyQt5-webengine` and
`python3-PyQt5-opengl`, then start with `--backend webengine` to use the new
backend.
Since the v1.0 release, qutebrowser uses QtWebEngine by default.
On NixOS
--------
Nixpkgs collection contains `pkgs.qutebrowser` since June 2015. You can install
it with:
----
$ nix-env -i qutebrowser
----
It's recommended to install `qt5.qtwebengine` and start with
`--backend webengine` to use the new backend.
Since the v1.0 release, qutebrowser uses QtWebEngine by default.
On openSUSE
-----------
There are prebuilt RPMs available at https://software.opensuse.org/download.html?project=network&package=qutebrowser[OBS].
To use the QtWebEngine backend, install `libqt5-qtwebengine`.
On OpenBSD
----------
qutebrowser is in http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/www/qutebrowser/[OpenBSD ports].
Install the package:
----
# pkg_add qutebrowser
----
Or alternatively, use the ports system :
----
# cd /usr/ports/www/qutebrowser
# make install
----
On Windows
----------
There are different ways to install qutebrowser on Windows:
Prebuilt binaries
~~~~~~~~~~~~~~~~~
Prebuilt standalone packages and installers
https://github.com/qutebrowser/qutebrowser/releases[are built] for every
release.
Note that you'll need to upgrade to new versions manually (subscribe to the
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[qutebrowser-announce
mailinglist] to get notified on new releases). You can install a newer version
without uninstalling the older one.
https://chocolatey.org/packages/qutebrowser[Chocolatey package]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* PackageManagement PowerShell module
----
PS C:\> Install-Package qutebrowser
----
* Chocolatey's client
----
C:\> choco install qutebrowser
----
Manual install
~~~~~~~~~~~~~~
* Use the installer from http://www.python.org/downloads[python.org] to get
Python 3 (be sure to install pip).
* Install https://testrun.org/tox/latest/index.html[tox] via
https://pip.pypa.io/en/latest/[pip]:
----
$ pip install tox
----
Then <<tox,install qutebrowser via tox>>.
On macOS
--------
Prebuilt binary
~~~~~~~~~~~~~~~
The easiest way to install qutebrowser on macOS is to use the prebuilt `.app`
files from the
https://github.com/qutebrowser/qutebrowser/releases[release page].
Note that you'll need to upgrade to new versions manually (subscribe to the
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[qutebrowser-announce
mailinglist] to get notified on new releases).
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.
==== Homebrew
----
$ brew install qt5
$ pip3 install qutebrowser
----
Since the v1.0 release, qutebrowser uses QtWebEngine by default.
Homebrew's builds of Qt and PyQt don't come with QtWebKit (and `--with-qtwebkit`
uses an old version of QtWebKit which qutebrowser doesn't support anymore). If
you want QtWebKit support, you'll need to build an up-to-date QtWebKit
https://github.com/annulen/webkit/wiki/Building-QtWebKit-on-OS-X[manually].
Packagers
---------
There are example .desktop and icon files provided. They would go in the
standard location for your distro (`/usr/share/applications` and
`/usr/share/pixmaps` for example).
The normal `setup.py install` doesn't install these files, so you'll have to do
it as part of the packaging process.
[[tox]]
Installing qutebrowser with tox
-------------------------------
Getting the repository
~~~~~~~~~~~~~~~~~~~~~~
First of all, clone the repository using http://git-scm.org/[git] and switch
into the repository folder:
----
$ git clone https://github.com/qutebrowser/qutebrowser.git
$ cd qutebrowser
----
Installing depdendencies (including Qt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Then run tox inside the qutebrowser repository to set up a
https://docs.python.org/3/library/venv.html[virtual environment]:
----
$ tox -e mkvenv-pypi
----
This installs all needed Python dependencies in a `.venv` subfolder.
This comes with an up-to-date Qt/PyQt including QtWebEngine, but has a few
caveats:
- Make sure your `python3` is Python 3.5 or newer, otherwise you'll get a "No
matching distribution found" error. Note that qutebrowser itself also requires
this.
- It only works on 64-bit x86 systems, with other architectures you'll get the
same error.
- If your distribution uses OpenSSL 1.1 (like Debian Stretch or Archlinux),
you'll need to set `LD_LIBRARY_PATH` to the OpenSSL 1.0 directory
(`export LD_LIBRARY_PATH=/usr/lib/openssl-1.0` on Archlinux) before starting
qutebrowser if you want SSL to work in certain downloads (e.g. for
`:adblock-update` or `:download`).
- It comes with a QtWebEngine compiled without proprietary codec support (such
as h.264).
See the next section for an alternative.
Installing dependencies (system-wide Qt)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, you can use `tox -e mkvenv` (without `-pypi`) to symlink your
local Qt install instead of installing PyQt in the virtualenv. However, unless
you have a new QtWebKit or QtWebEngine available, qutebrowser will not work. It
also typically means you'll be using an older release of QtWebEngine.
On Windows, run `tox -e 'mkvenv-win' instead, however make sure that ONLY
Python3 is in your PATH before running tox.
Creating a wrapper script
~~~~~~~~~~~~~~~~~~~~~~~~~
You can then create a simple wrapper script to start qutebrowser somewhere in
your `$PATH` (e.g. `/usr/local/bin/qutebrowser` or `~/bin/qutebrowser`):
----
#!/bin/bash
~/path/to/qutebrowser/.venv/bin/python3 -m qutebrowser "$@"
----
Updating
~~~~~~~~
When you updated your local copy of the code (e.g. by pulling the git repo, or
extracting a new version), the virtualenv should automatically use the updated
code. However, if dependencies got added, this won't be reflected in the
virtualenv. Thus it's recommended to run the following command to recreate the
virtualenv:
----
$ tox -r -e mkvenv-pypi
----

196
doc/notes
View File

@@ -1,196 +0,0 @@
henk's thoughts
===============
1. Power to the user! Protect privacy!
Things the browser should only do with explicit consent from the user, if
applicable the user should be able to choose which protocol/host/port triplets
to white/blacklist:
- load/run executable code, like js, flash, java applets, ... (think NoScript)
- requests to other domains, ports or using a different protocol than what the
user requested (think RequestPolicy)
- accept cookies
- storing/saving/caching things, e.g. open tabs ("session"), cookies, page
contents, browsing/download history, form data, ...
- send referrer
- disclose any (presence, type, version, settings, capabilities, etc.)
information about OS, browser, installed fonts, plugins, addons, etc.
2. Be efficient!
I tend to leave a lot of tabs open and nobody can deny that some websites
simply suck, so the browser should, unless told otherwise by the user:
- load tabs only when needed
- run code in tabs only when needed, i.e. when the tab is currently being
used/viewed (background tabs doing some JS magic even when they are not being
used can create a lot of unnecessary load on the machine)
- finish requests to the domain the user requested (e.g. www.example.org)
before doing any requests to other subdomains (e.g. images.example.org) and
finish those before doing requests to thirdparty domains (e.g. example.com)
3. Be stable!
- one site should not make the complete browser crash, only that site's tab
Upstream Bugs
=============
- Web inspector is blank unless .hide()/.show() is called.
Asked on SO: http://stackoverflow.com/q/23499159/2085149
TODO: Report to PyQt/Qt
- Report some other crashes
/u/angelic_sedition's thoughts
==============================
Well support for greasemonkey scripts and bookmarklets/js (which was mentioned
in the arch forum post) would be a big addition. What I've usually missed when
using other vim-like browsers is things that allow for different settings and
key bindings for different contexts. With that implemented I think I could
switch to a lightweight browser (and believe me, I'd like to) for the most part
and only use firefox when I needed downthemall or something.
For example, I have different bindings based on tab position that are reloaded
with a pentadactyl autocmd so that <space><homerow keys> will take me to tab
1-10 if I'm in that range or 2-20 if I'm in that range. I have an autocmd that
will run on completed downloads that passes the file path to a script that will
open ranger in a floating window with that file cut (this is basically like
using ranger to save files instead of the crappy gui popup).
I also have a few bindings based on tabgroups. Tabgroups are a firefox feature,
but I find them very useful for sorting things by topic so that only the tabs
I'm interested at the moment are visible.
Pentadactyl has a feature it calls groups. You can create a group that will
activate for sites/urls that match a pattern with some regex support. This
allows me, for example, to set up different (more convenient) bindings for
zooming only on images. I'll never need use the equivalent of vim n (next text
search match), so I can bind that to zoom. This allows setting up custom
quickmarks/gotos using the same keys for different websites. For example, on
reddit I have different g(some key) bindings to go to different subreddits.
This can also be used to pass certain keys directly to the site (e.g. for use
with RES). For sites that don't have modifiable bindings, I can use this with
pentadactyl's feedkeys or xdotool to create my own custom bindings. I even have
a binding that will call out to bash script with different arguments depending
on the site to download an image or an image gallery depending on the site (in
some cases passing the url to some cli program).
I've also noticed the lack of completion. For example, on "o" pentadactyl will
show sites (e.g. from history) that can be completed. I think I've been spoiled
by pentadactyl having completion for just about everything.
suckless surf ML post
=====================
From: Ben Woolley <tautolog_AT_gmail.com>
Date: Wed, 7 Jan 2015 18:29:25 -0800
Hi all,
This patch is a bit of a beast for surf. It is intended to be applied after
the disk cache patch. It breaks some internal interfaces, so it could
conflict with other patches.
I have been wanting a browser to implement a complete same-origin policy,
and have been investigating how to do this in various browsers for many
months. When I saw how surf opened new windows in a separate process, and
was so simple, I knew I could do it quickly. Over the last two weeks, I
have been developing this implementation on surf.
The basic idea is to prevent browser-based tracking as you browse from site
to site, or origin to origin. By "origin" domain, I mean the "first-party"
domain, the domain normally in the location bar (of the typical browser
interface). Each origin domain effectively gets its own browser profile,
and a browser process only ever deals with one origin domain at a time.
This isolates origins vertically, preventing cookies, disk cache, memory
cache, and window.name vulnerabilities. Basically, all known
vulnerabilities that google and Mozilla cite as counter-examples when they
explain why they haven't disabled third-party cookies yet.
When you are on msnbc.com, the tracking pixels will be stored in a cookie
file for msnbc.com. When you go to cnn.com, the tracking pixels will be
stored in a cookie file for cnn.com. You will not be tracked between them.
However, third-party cookies, and the caching of third party resources will
still work, but they will be isolated between origin domains. Instead of
blocking cookies and cache entries, they are "double-keyed", or *also*
keyed by origin.
There is a unidirectional communication channel, however, from one origin
to the next, through navigation from one origin to the next. That is, the
query string is passed from one origin to the next, and may embed
identifiers. One example is an affiliate link that identifies where the
lead came from. I have implemented what I call "horizontal isolation", in
the form of an "Origin Crossing Gate".
Whenever you follow a link to a new domain, or even are just redirected to
a new domain, a new window/tab is opened, and passed the referring origin
via -R. The page passed to -O, for example -O originprompt.html, is an HTML
page that is loaded in the new origin's context. That page tells you the
origin you were on, the new origin, and the full link, and you can decide
to go just to the new origin, or go to the full URL, after reviewing it for
tracking data.
Also, you may click links that store your trust of that relationship with
various expiration times, the same way you would trust geolocation requests
for a particular origin for a period of time. The database used is actually
the new origin's cookie file. Since the origin prompt is loaded in the new
origin's context, I can set a cookie on behalf of the new origin. The
expiration time of the trust is the expiration time of the cookie. The
cookie implementation in webkit automatically expires the trust as part of
how cookies work. Each time you cross an origin, the origin crossing page
checks the cookie to see if trust is still established. If so, it will use
window.location.replace() to continue on automatically. The initial page
renders blank until the trust is invalidated, in which case the content of
the gate is made visible.
However, the new origin is technically able to mess with those cookies, so
a website could set trust for an origin crossing. I have addressed that by
hashing the key with a salt, and setting the real expiration time as the
value, along with an HMAC to verify the contents of the value. If the
cookie is messed with in any way, the trust will be disabled, and the
prompt will appear again. So it has a fail-safe function.
I know it seems a bit convoluted, but it just started out as a nice little
rabbit hole, and I just wanted to get something workable. At first I
thought using the cookie expiration time was convenient, but then when I
realized that I needed to protect the cookie, things got a bit hairy. But
it works.
Each profile is, by default, stored in ~/.surf/origins/$origin/
The interesting side effect is that if there is a problem where a website
relies on the cross-site cookie vulnerability to make a connection, you can
simply make a symbolic link from one origin folder to another, and they
will share the same profile. And if you want to delete cookies and/or cache
for a particular origin, you just rm -rf the origin's profile folder, and
don't have to interfere with your other sites that are working just fine.
One thing I don't handle are cross-origins POSTs. They just end up as GET
requests right now. I intend to do something about that, but I haven't
figured that out yet.
I have only been using this functionality for a few days myself, so I have
absolutely no feedback yet. I wanted to provide the first implementation of
the management of identity as a system resource the same way that things
like geolocation, camera, and microphone resources are managed in browsers
and mobile apps.
Currently, Mozilla and Tor have are working on third-party tracking issues
in Firefox.
https://blog.mozilla.org/privacy/2014/11/10/introducing-polaris-privacy-initiative-to-accelerate-user-focused-privacy-online/
Up to this point, Tor has provided a patch that double-keys cookies with
the origin domain, but no other progress is visible. I have seen no
discussion of how horizontal isolation is supposed to happen, and I wanted
to show people that it can be done, and this is one way it can be done, and
to compel the other browser makers to catch up, and hopefully the community
can work toward a standard *without* the tracking loopholes, by showing
people what a *complete* solution looks like.
Thank you,
Ben Woolley
Patch: http://lists.suckless.org/dev/att-25070/0005-same-origin-policy.patch

View File

@@ -31,7 +31,7 @@ image:http://qutebrowser.org/img/cheatsheet-small.png["qutebrowser key binding c
* 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. (Currently not available with the QtWebEngine backend and on the OS X build - use the `:set` command instead)
* 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] or
https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce[the announce-only mailinglist].

View File

@@ -17,7 +17,7 @@ qutebrowser - a keyboard-driven, vim-like browser based on PyQt5.
== DESCRIPTION
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 Qt5 and is free software, licensed under the GPL.
It was inspired by other browsers/addons like dwb and Vimperator/Pentadactyl.
@@ -44,7 +44,7 @@ show it.
*-V*, *--version*::
Show version and quit.
*-s* 'SECTION' 'OPTION' 'VALUE', *--set* 'SECTION' 'OPTION' 'VALUE'::
*-s* 'OPTION' 'VALUE', *--set* 'OPTION' 'VALUE'::
Set a temporary setting for this session.
*-r* 'SESSION', *--restore* 'SESSION'::
@@ -57,7 +57,7 @@ show it.
How URLs should be opened if there is already a qutebrowser instance running.
*--backend* '{webkit,webengine}'::
Which backend to use (webengine backend is EXPERIMENTAL!).
Which backend to use.
*--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.
@@ -84,21 +84,9 @@ show it.
*--force-color*::
Force colored logging
*--harfbuzz* '{old,new,system,auto}'::
HarfBuzz engine version to use. Default: auto.
*--relaxed-config*::
Silently remove unknown config options.
*--nowindow*::
Don't show the main window.
*--debug-exit*::
Turn on debugging of late exit.
*--pdb-postmortem*::
Drop into pdb on exceptions.
*--temp-basedir*::
Use a temporary basedir.
@@ -110,13 +98,16 @@ show it.
*--qt-flag* 'QT_FLAG'::
Pass an argument to Qt as flag.
*--debug-flag* 'DEBUG_FLAGS'::
Pass name of debugging feature to be turned on.
// QUTE_OPTIONS_END
== FILES
- '~/.config/qutebrowser/qutebrowser.conf': Main config file.
- '~/.config/qutebrowser/config.py': Configuration file.
- '~/.config/qutebrowser/autoconfig.yml': Configuration done via the GUI.
- '~/.config/qutebrowser/quickmarks': Saved quickmarks.
- '~/.config/qutebrowser/keys.conf': Defined key bindings.
- '~/.local/share/qutebrowser/': Various state information.
- '~/.cache/qutebrowser/': Temporary data.

View File

@@ -60,7 +60,7 @@ Sending commands
Normal qutebrowser commands can be written to `$QUTE_FIFO` and will be
executed.
On Unix/OS X, this is a named pipe and commands written to it will get executed
On Unix/macOS, this is a named pipe and commands written to it will get executed
immediately.
On Windows, this is a regular file, and the commands in it will be executed as
@@ -78,3 +78,11 @@ Opening the currently selected word on http://www.dict.cc/[dict.cc]:
echo "open -t http://www.dict.cc/?s=$QUTE_SELECTED_TEXT" >> "$QUTE_FIFO"
----
Libraries
---------
Some third-party libraries are available to make writing userscripts easier:
- Python: https://github.com/hiway/python-qutescript[python-qutescript]
- Node.js: https://www.npmjs.com/package/qutejs[qutejs]

77
misc/qutebrowser.nsi Normal file
View File

@@ -0,0 +1,77 @@
Name "qutebrowser"
Unicode true
RequestExecutionLevel admin
SetCompressor /solid lzma
!ifdef X64
OutFile "..\dist\qutebrowser-${VERSION}-amd64.exe"
InstallDir "$ProgramFiles64\qutebrowser"
!else
OutFile "..\dist\qutebrowser-${VERSION}-win32.exe"
InstallDir "$ProgramFiles\qutebrowser"
!endif
;Default installation folder
!include "MUI2.nsh"
;!include "MultiUser.nsh"
!define MUI_ABORTWARNING
;!define MULTIUSER_MUI
;!define MULTIUSER_INSTALLMODE_COMMANDLINE
!define MUI_ICON "../icons/qutebrowser.ico"
!define MUI_UNICON "../icons/qutebrowser.ico"
!insertmacro MUI_PAGE_LICENSE "..\LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
; depends on admin status
;SetShellVarContext current
Section "Install"
; Uninstall old versions
ExecWait 'MsiExec.exe /quiet /qn /norestart /X{633F41F9-FE9B-42D1-9CC4-718CBD01EE11}'
ExecWait 'MsiExec.exe /quiet /qn /norestart /X{9331D947-AC86-4542-A755-A833429C6E69}'
SetOutPath "$INSTDIR"
!ifdef X64
file /r "..\dist\qutebrowser-${VERSION}-x64\*.*"
!else
file /r "..\dist\qutebrowser-${VERSION}-x86\*.*"
!endif
SetShellVarContext all
CreateShortCut "$SMPROGRAMS\qutebrowser.lnk" "$INSTDIR\qutebrowser.exe"
;Create uninstaller
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "DisplayName" "qutebrowser"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "UninstallString" '"$INSTDIR\uninst.exe"'
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser" "QuietUninstallString" '"$INSTDIR\uninst.exe" /S'
SectionEnd
;--------------------------------
;Uninstaller Section
Section "Uninstall"
SetShellVarContext all
Delete "$SMPROGRAMS\qutebrowser.lnk"
RMDir /r "$INSTDIR\*.*"
RMDir "$INSTDIR"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qutebrowser"
SectionEnd

View File

@@ -15,13 +15,14 @@ def get_data_files():
('../qutebrowser/img', 'img'),
('../qutebrowser/javascript', 'javascript'),
('../qutebrowser/html/doc', 'html/doc'),
('../qutebrowser/git-commit-id', '')
('../qutebrowser/git-commit-id', ''),
('../qutebrowser/config/configdata.yml', 'config'),
]
if os.path.exists(os.path.join('qutebrowser', '3rdparty', 'pdfjs')):
data_files.append(('../qutebrowser/3rdparty/pdfjs', '3rdparty/pdfjs'))
else:
print("Warning: excluding pdfjs as it's not present!")
# if os.path.exists(os.path.join('qutebrowser', '3rdparty', 'pdfjs')):
# data_files.append(('../qutebrowser/3rdparty/pdfjs', '3rdparty/pdfjs'))
# else:
# print("Warning: excluding pdfjs as it's not present!")
return data_files
@@ -41,10 +42,10 @@ a = Analysis(['../qutebrowser/__main__.py'],
pathex=['misc'],
binaries=None,
datas=get_data_files(),
hiddenimports=[],
hiddenimports=['PyQt5.QtOpenGL', 'PyQt5._QOpenGLFunctions_2_0'],
hookspath=[],
runtime_hooks=[],
excludes=[],
excludes=['tkinter'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
@@ -70,9 +71,5 @@ coll = COLLECT(exe,
app = BUNDLE(coll,
name='qutebrowser.app',
icon=icon,
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,5 +1,9 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
codecov==2.0.5
coverage==4.3.4
requests==2.13.0
certifi==2017.7.27.1
chardet==3.0.4
codecov==2.0.9
coverage==4.4.1
idna==2.6
requests==2.18.4
urllib3==1.22

View File

@@ -1,5 +0,0 @@
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

@@ -3,18 +3,21 @@
flake8==2.6.2 # rq.filter: < 3.0.0
flake8-copyright==0.2.0
flake8-debugger==1.4.0 # rq.filter: != 2.0.0
flake8-deprecated==1.1
flake8-docstrings==1.0.3
flake8-deprecated==1.2.1
flake8-docstrings==1.0.3 # rq.filter: < 1.1.0
flake8-future-import==0.4.3
flake8-mock==0.3
flake8-pep3101==1.0
flake8-pep3101==1.0 # rq.filter: < 1.1
flake8-polyfill==1.0.1
flake8-putty==0.4.0
flake8-string-format==0.2.3
flake8-tidy-imports==1.0.5
flake8-tuple==0.2.12
flake8-tidy-imports==1.1.0
flake8-tuple==0.2.13
mccabe==0.6.1
packaging==16.8
pep8-naming==0.4.1
pycodestyle==2.3.1
pydocstyle==1.1.1
pyflakes==1.5.0
pydocstyle==1.1.1 # rq.filter: < 2.0.0
pyflakes==1.6.0
pyparsing==2.2.0
six==1.11.0

View File

@@ -2,16 +2,16 @@ flake8<3.0.0
flake8-copyright
flake8-debugger!=2.0.0
flake8-deprecated
flake8-docstrings
flake8-docstrings<1.1.0
flake8-future-import
flake8-mock
flake8-pep3101
flake8-pep3101<1.1
flake8-putty
flake8-string-format
flake8-tidy-imports
flake8-tuple
pep8-naming
pydocstyle
pydocstyle<2.0.0
pyflakes
# Pinned to 2.0.0 otherwise
@@ -21,6 +21,9 @@ mccabe==0.6.1
# Waiting until flake8-putty updated
#@ filter: flake8 < 3.0.0
#@ filter: pydocstyle < 2.0.0
#@ filter: flake8-docstrings < 1.1.0
#@ filter: flake8-pep3101 < 1.1
# https://github.com/JBKahn/flake8-debugger/issues/5
#@ filter: flake8-debugger != 2.0.0

View File

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

View File

@@ -1,5 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
altgraph==0.14
future==0.16.0
macholib==1.8
pefile==2017.9.3
-e git+https://github.com/pyinstaller/pyinstaller.git@develop#egg=PyInstaller
PyQt5==5.8
sip==4.19.1

View File

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

View File

@@ -1,11 +1,18 @@
# 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
certifi==2017.7.27.1
chardet==3.0.4
github3.py==0.9.6
idna==2.6
isort==4.2.15
lazy-object-proxy==1.3.1
mccabe==0.6.1
-e git+https://github.com/PyCQA/pylint.git#egg=pylint
./scripts/dev/pylint_checkers
requests==2.13.0
wrapt==1.10.8
requests==2.18.4
six==1.11.0
uritemplate==3.0.0
uritemplate.py==3.0.2
urllib3==1.22
wrapt==1.10.11

View File

@@ -2,6 +2,7 @@
-e git+https://github.com/PyCQA/pylint.git#egg=pylint
./scripts/dev/pylint_checkers
requests
github3.py
# remove @commit-id for scm installs
#@ replace: @.*# #

View File

@@ -1,13 +1,18 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
astroid==1.4.9
astroid==1.5.3
certifi==2017.7.27.1
chardet==3.0.4
github3.py==0.9.6
isort==4.2.5
lazy-object-proxy==1.2.2
idna==2.6
isort==4.2.15
lazy-object-proxy==1.3.1
mccabe==0.6.1
pylint==1.6.5
pylint==1.7.4
./scripts/dev/pylint_checkers
requests==2.13.0
requests==2.18.4
six==1.11.0
uritemplate==3.0.0
uritemplate.py==3.0.2
wrapt==1.10.8
urllib3==1.22
wrapt==1.10.11

View File

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

View File

@@ -0,0 +1 @@
PyQt5

View File

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

View File

@@ -4,3 +4,4 @@ pyPEG2
PyYAML
colorama
cssutils
attrs

View File

@@ -4,7 +4,6 @@ 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
@@ -27,7 +26,6 @@ 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
@@ -42,6 +40,7 @@ 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
git+https://github.com/python-attrs/attrs.git
# Fails to build:
# gcc: error: ext/_yaml.c: No such file or directory

View File

@@ -1,36 +1,39 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
beautifulsoup4==4.5.3
cheroot==5.1.0
attrs==17.2.0
beautifulsoup4==4.6.0
cheroot==5.8.3
click==6.7
coverage==4.3.4
decorator==4.0.11
# colorama==0.3.9
coverage==4.4.1
EasyProcess==0.2.3
Flask==0.12
glob2==0.5
httpbin==0.5.0
hypothesis==3.6.1
fields==5.0.0
Flask==0.12.2
glob2==0.6
hunter==2.0.1
hypothesis==3.32.0
itsdangerous==0.24
# Jinja2==2.9.5
Mako==1.0.6
# MarkupSafe==0.23
parse==1.6.6
parse-type==0.3.4
py==1.4.32
pytest==3.0.6
pytest-bdd==2.18.1
pytest-benchmark==3.0.0
# Jinja2==2.9.6
Mako==1.0.7
# MarkupSafe==1.0
parse==1.8.2
parse-type==0.4.2
py==1.4.34
py-cpuinfo==3.3.0
pytest==3.2.3
pytest-bdd==2.18.2
pytest-benchmark==3.1.1
pytest-catchlog==1.2.2
pytest-cov==2.4.0
pytest-cov==2.5.1
pytest-faulthandler==1.3.1
pytest-instafail==0.3.0
pytest-mock==1.5.0
pytest-qt==2.1.0
pytest-mock==1.6.3
pytest-qt==2.2.1
pytest-repeat==0.4.1
pytest-rerunfailures==2.1.0
pytest-rerunfailures==3.1
pytest-travis-fold==1.2.0
pytest-warnings==0.2.0
pytest-xvfb==1.0.0
PyVirtualDisplay==0.2.1
vulture==0.12
Werkzeug==0.11.15
six==1.11.0
vulture==0.26
Werkzeug==0.12.2

View File

@@ -2,7 +2,7 @@ beautifulsoup4
cheroot
coverage
Flask
httpbin
hunter
hypothesis
pytest
pytest-bdd
@@ -16,8 +16,7 @@ pytest-qt
pytest-repeat
pytest-rerunfailures
pytest-travis-fold
pytest-warnings
pytest-xvfb
vulture
#@ ignore: Jinja2, MarkupSafe
#@ ignore: Jinja2, MarkupSafe, colorama

View File

@@ -1,6 +1,6 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
pluggy==0.4.0
py==1.4.32
tox==2.6.0
pluggy==0.5.2
py==1.4.34
tox==2.9.1
virtualenv==15.1.0

View File

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

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env bash
# Copyright 2015 Zach-Button <zachrey.button@gmail.com>
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,7 +23,7 @@
# If run from qutebrowser as a userscript, it runs :open on the URL
# If not, it opens a new qutebrowser window at the URL
#
# Ideal for use with tabs-are-windows. Set a hotkey to launch this script, then:
# Ideal for use with tabs_are_windows. Set a hotkey to launch this script, then:
# :bind o spawn --userscript dmenu_qutebrowser
#
# Use the hotkey to open in new tab/window, press 'o' to open URL in current tab/window

47
misc/userscripts/format_json Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
#
# Behavior:
# Userscript for qutebrowser which will take the raw JSON text of the current
# page, format it using `jq`, will add syntax highlighting using `pygments`,
# and open the syntax highlighted pretty printed html in a new tab. If the file
# is larger than 10MB then this script will only indent the json and will forego
# syntax highlighting using pygments.
#
# In order to use this script, just start it using `spawn --userscript` from
# qutebrowser. I recommend using an alias, e.g. put this in the
# [alias]-section of qutebrowser.conf:
#
# json = spawn --userscript /path/to/json_format
#
# Note that the color style defaults to monokai, but a different pygments style
# can be passed as the first parameter to the script. A full list of the pygments
# styles can be found at: https://help.farbox.com/pygments.html
#
# Bryan Gilbert, 2017
# default style to monokai if none is provided
STYLE=${1:-monokai}
# format json using jq
FORMATTED_JSON="$(cat "$QUTE_TEXT" | jq '.')"
# if jq command failed or formatted json is empty, assume failure and terminate
if [ $? -ne 0 ] || [ -z "$FORMATTED_JSON" ]; then
echo "Invalid json, aborting..."
exit 1
fi
# calculate the filesize of the json document
FILE_SIZE=$(ls -s --block-size=1048576 "$QUTE_TEXT" | cut -d' ' -f1)
# use pygments to pretty-up the json (syntax highlight) if file is less than 10MB
if [ "$FILE_SIZE" -lt "10" ]; then
FORMATTED_JSON="$(echo "$FORMATTED_JSON" | pygmentize -l json -f html -O full,style=$STYLE)"
fi
# create a temp file and write the formatted json to that file
TEMP_FILE="$(mktemp --suffix '.html')"
echo "$FORMATTED_JSON" > $TEMP_FILE
# send the command to qutebrowser to open the new file containing the formatted json
echo "open -t file://$TEMP_FILE" >> "$QUTE_FIFO"

View File

@@ -12,7 +12,7 @@
# - rofi (in a recent version)
# - xdg-open and xdg-mime
# - You should configure qutebrowser to download files to a single directory
# - It comes in handy if you enable remove-finished-downloads. If you want to
# - It comes in handy if you enable downloads.remove_finished. If you want to
# see the recent downloads, just press "sd".
#
# Thorsten Wißmann, 2015 (thorsten` on freenode)

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright 2015 jnphilipp <me@jnphilipp.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -20,7 +21,7 @@
# Opens all links to feeds defined in the head of a site
#
# Ideal for use with tabs-are-windows. Set a hotkey to launch this script, then:
# Ideal for use with tabs_are_windows. Set a hotkey to launch this script, then:
# :bind gF spawn --userscript openfeeds
#
# Use the hotkey to open the feeds in new tab/window, press 'gF' to open

View File

@@ -9,7 +9,7 @@ directly ask me via IRC (nickname thorsten\`) in #qutebrowser on freenode.
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
WARNING: the passwords are stored in qutebrowser's
debug log reachable via the url qute:log
debug log reachable via the url qute://log
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
Usage: run as a userscript form qutebrowser, e.g.:
@@ -189,7 +189,7 @@ choose_entry_rofi() {
}
choose_entry_zenity() {
MENU_COMMAND=( zenity --list --title "Qutebrowser password fill"
MENU_COMMAND=( zenity --list --title "qutebrowser password fill"
--text "Pick the password entry:"
--column "Name" )
choose_entry_menu || true
@@ -199,7 +199,7 @@ choose_entry_zenity_radio() {
zenity_helper() {
awk '{ print $0 ; print $0 }' \
| zenity --list --radiolist \
--title "Qutebrowser password fill" \
--title "qutebrowser password fill" \
--text "Pick the password entry:" \
--column " " --column "Name"
}
@@ -327,6 +327,17 @@ open_entry "$file"
js() {
cat <<EOF
function isVisible(elem) {
var style = elem.ownerDocument.defaultView.getComputedStyle(elem, null);
if (style.getPropertyValue("visibility") !== "visible" ||
style.getPropertyValue("display") === "none" ||
style.getPropertyValue("opacity") === "0") {
return false;
}
return elem.offsetWidth > 0 && elem.offsetHeight > 0;
};
function hasPasswordField(form) {
var inputs = form.getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++) {
@@ -341,7 +352,7 @@ cat <<EOF
var inputs = form.getElementsByTagName("input");
for (var j = 0; j < inputs.length; j++) {
var input = inputs[j];
if (input.type == "text" || input.type == "email") {
if (isVisible(input) && (input.type == "text" || input.type == "email")) {
input.focus();
input.value = "$(javascript_escape "${username}")";
input.blur();

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env bash
# Copyright 2015 Zach-Button <zachrey.button@gmail.com>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,21 +1,33 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Executes python-readability on current page and opens the summary as new tab.
#
# Depends on the python-readability package, or its fork:
#
# - https://github.com/buriy/python-readability
# - https://github.com/bookieio/breadability
#
# 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())
data = source.read()
try:
from breadability.readable import Article as reader
doc = reader(data)
content = doc.readable
except ImportError:
from readability import Document
doc = Document(data)
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" />')

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Adds DuckDuckGo bang as searchengine.
#
@@ -8,14 +8,21 @@
# Example:
# :spawn --userscript ripbang amazon maps
#
import os, re, requests, sys, urllib
from __future__ import print_function
import os, re, requests, sys
try:
from urllib.parse import unquote
except ImportError:
from urllib import unquote
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 = unquote(re.search("url=[^']+", r.text).group(0))
searchengine = searchengine.replace('url=', '')
searchengine = searchengine.replace('/l/?kh=-1&uddg=', '')
searchengine = searchengine.replace('SEARCHTEXT', '{}')
@@ -24,4 +31,4 @@ for argument in sys.argv[1:]:
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
fifo.write('set searchengines %s %s' % (bang, searchengine))
else:
print '%s %s' % (bang, searchengine)
print('%s %s' % (bang, searchengine))

View File

@@ -49,7 +49,7 @@ msg() {
MPV_COMMAND=${MPV_COMMAND:-mpv}
# Warning: spaces in single flags are not supported
MPV_FLAGS=${MPV_FLAGS:- --force-window --no-terminal --keep-open=yes --ytdl }
MPV_FLAGS=${MPV_FLAGS:- --force-window --no-terminal --keep-open=yes --ytdl --ytdl-raw-options=yes-playlist=}
video_command=( "$MPV_COMMAND" $MPV_FLAGS )
js() {
@@ -140,4 +140,4 @@ printjs() {
echo "jseval -q $(printjs)" >> "$QUTE_FIFO"
msg info "Opening $QUTE_URL with mpv"
"${video_command[@]}" "$QUTE_URL"
"${video_command[@]}" "$@" "$QUTE_URL"

View File

@@ -1,12 +1,13 @@
[pytest]
addopts = --strict -rfEw --faulthandler-timeout=70 --instafail --pythonwarnings error
addopts = --strict -rfEw --faulthandler-timeout=90 --instafail --pythonwarnings error --benchmark-columns=Min,Max,Median
testpaths = tests
markers =
gui: Tests using the GUI (e.g. spawning widgets)
posix: Tests which only can run on a POSIX OS.
windows: Tests which only can run on Windows.
linux: Tests which only can run on Linux.
osx: Tests which only can run on OS X.
not_osx: Tests which can not run on OS X.
mac: Tests which only can run on macOS.
not_mac: Tests which can not run on macOS.
not_frozen: Tests which can't be run if sys.frozen is True.
no_xvfb: Tests which can't be run with Xvfb.
frozen: Tests which can only be run if sys.frozen is True.
@@ -14,21 +15,22 @@ 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.
no_ci: Tests which should not run on CI.
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
qtwebengine_mac_xfail: Tests which fail on macOS 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
issue2478: Tests which are broken on Windows with QtWebEngine, https://github.com/qutebrowser/qutebrowser/issues/2478
fake_os: Fake utils.is_* to a fake operating system
qt_log_level_fail = WARNING
qt_log_ignore =
^SpellCheck: .*
^SetProcessDpiAwareness failed: .*
^QWindowsWindow::setGeometryDp: Unable to set geometry .*
^QWindowsWindow::setGeometry(Dp)?: Unable to set geometry .*
^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"
@@ -42,13 +44,15 @@ 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 .*
^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
^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
^QSslSocket: cannot resolve *
^Incompatible version of OpenSSL
^QQuickWidget::invalidateRenderControl could not make context current
^libpng warning: iCCP: known incorrect sRGB profile
^inotify_add_watch(".*") failed: "No space left on device"
xfail_strict = true

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,11 +22,11 @@
import os.path
__author__ = "Florian Bruhin"
__copyright__ = "Copyright 2014-2016 Florian Bruhin (The Compiler)"
__copyright__ = "Copyright 2014-2017 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version_info__ = (0, 10, 0)
__version_info__ = (1, 0, 2)
__version__ = '.'.join(str(e) for e in __version_info__)
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -17,12 +17,29 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Initialization of qutebrowser and application-wide things."""
"""Initialization of qutebrowser and application-wide things.
The run() function will get called once early initialization (in
qutebrowser.py/earlyinit.py) is done. See the qutebrowser.py docstring for
details about early initialization.
As we need to access the config before the QApplication is created, we
initialize everything the config needs before the QApplication is created, and
then leave it in a partially initialized state (no saving, no config errors
shown yet).
We then set up the QApplication object and initialize a few more low-level
things.
After that, init() and _init_modules() take over and initialize the rest.
After all initialization is done, the qt_mainloop() function is called, which
blocks and spins the Qt mainloop.
"""
import os
import sys
import subprocess
import configparser
import functools
import json
import shutil
@@ -42,9 +59,10 @@ except ImportError:
import qutebrowser
import qutebrowser.resources
from qutebrowser.completion.models import instances as completionmodels
from qutebrowser.completion import completiondelegate
from qutebrowser.completion.models import miscmodels
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, config, websettings, configexc
from qutebrowser.config import config, websettings, configfiles, configinit
from qutebrowser.browser import (urlmarks, adblock, history, browsertab,
downloads)
from qutebrowser.browser.network import proxy
@@ -53,11 +71,15 @@ 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)
# We import utilcmds to run the cmdutils.register decorators.
crashsignal, earlyinit, sql, cmdhistory,
backendproblem)
from qutebrowser.utils import (log, version, message, utils, urlutils, objreg,
usertypes, standarddir, error)
# pylint: disable=unused-import
# We import those to run the cmdutils.register decorators.
from qutebrowser.mainwindow.statusbar import command
from qutebrowser.misc import utilcmds
# pylint: enable=unused-import
qApp = None
@@ -71,6 +93,12 @@ def run(args):
quitter = Quitter(args)
objreg.register('quitter', quitter)
log.init.debug("Initializing directories...")
standarddir.init(args)
log.init.debug("Initializing config...")
configinit.early_init(args)
global qApp
qApp = Application(args)
qApp.setOrganizationName("qutebrowser")
@@ -78,9 +106,6 @@ 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)
@@ -133,33 +158,29 @@ def init(args, crash_handler):
log.init.debug("Starting init...")
qApp.setQuitOnLastWindowClosed(False)
_init_icon()
utils.actute_warning()
try:
_init_modules(args, crash_handler)
except (OSError, UnicodeDecodeError) as e:
except (OSError, UnicodeDecodeError, browsertab.WebTabError) as e:
error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init)
QTimer.singleShot(0, functools.partial(_process_args, args))
QTimer.singleShot(10, functools.partial(_init_late_modules, args))
log.init.debug("Initializing eventfilter...")
event_filter = EventFilter(qApp)
qApp.installEventFilter(event_filter)
objreg.register('event-filter', event_filter)
log.init.debug("Connecting signals...")
config_obj = objreg.get('config')
config_obj.style_changed.connect(style.get_stylesheet.cache_clear)
qApp.focusChanged.connect(on_focus_changed)
_process_args(args)
QDesktopServices.setUrlHandler('http', open_desktopservices_url)
QDesktopServices.setUrlHandler('https', open_desktopservices_url)
QDesktopServices.setUrlHandler('qute', open_desktopservices_url)
macros.init()
objreg.get('web-history').import_txt()
log.init.debug("Init done!")
crash_handler.raise_crashdlg()
@@ -172,36 +193,32 @@ def _init_icon():
for size in [16, 24, 32, 48, 64, 96, 128, 256, 512]:
filename = ':/icons/qutebrowser-{}x{}.png'.format(size, size)
pixmap = QPixmap(filename)
qtutils.ensure_not_null(pixmap)
fallback_icon.addPixmap(pixmap)
qtutils.ensure_not_null(fallback_icon)
if pixmap.isNull():
log.init.warning("Failed to load {}".format(filename))
else:
fallback_icon.addPixmap(pixmap)
icon = QIcon.fromTheme('qutebrowser', fallback_icon)
qtutils.ensure_not_null(icon)
qApp.setWindowIcon(icon)
if icon.isNull():
log.init.warning("Failed to load icon")
else:
qApp.setWindowIcon(icon)
def _process_args(args):
"""Open startpage etc. and process commandline args."""
config_obj = objreg.get('config')
for sect, opt, val in args.temp_settings:
try:
config_obj.set('temp', sect, opt, val)
except (configexc.Error, configparser.Error) as e:
message.error("set: {} - {}".format(e.__class__.__name__, e))
if not args.override_restore:
_load_session(args.session)
session_manager = objreg.get('session-manager')
if not session_manager.did_load:
log.init.debug("Initializing main window...")
window = mainwindow.MainWindow()
window = mainwindow.MainWindow(private=None)
if not args.nowindow:
window.show()
qApp.setActiveWindow(window)
process_pos_args(args.command)
_open_startpage()
_open_quickstart(args)
_open_special_pages(args)
delta = datetime.datetime.now() - earlyinit.START_TIME
log.init.debug("Init finished after {}s".format(delta.total_seconds()))
@@ -213,13 +230,12 @@ def _load_session(name):
Args:
name: The name of the session to load, or None to read state file.
"""
state_config = objreg.get('state-config')
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']
name = configfiles.state['general']['session']
except KeyError:
# No session given as argument and none in the session file ->
# start without loading a session
@@ -232,7 +248,7 @@ def _load_session(name):
except sessions.SessionError as e:
message.error("Failed to load session {}: {}".format(name, e))
try:
del state_config['general']['session']
del configfiles.state['general']['session']
except KeyError:
pass
# If this was a _restart session, delete it.
@@ -264,7 +280,7 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
win_id = mainwindow.get_window(via_ipc, force_tab=True)
log.init.debug("Startup cmd {!r}".format(cmd))
commandrunner = runners.CommandRunner(win_id)
commandrunner.run_safely_init(cmd[1:])
commandrunner.run_safely(cmd[1:])
elif not cmd:
log.init.debug("Empty argument")
win_id = mainwindow.get_window(via_ipc, force_window=True)
@@ -272,11 +288,7 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
if via_ipc and target_arg and target_arg != 'auto':
open_target = target_arg
else:
open_target = config.get('general', 'new-instance-open-target')
win_id = mainwindow.get_window(via_ipc, force_target=open_target)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
log.init.debug("Startup URL {}".format(cmd))
open_target = None
if not cwd: # could also be an empty string due to the PyQt signal
cwd = None
try:
@@ -285,9 +297,30 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
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,
explicit=True)
win_id = open_url(url, target=open_target, via_ipc=via_ipc)
def open_url(url, target=None, no_raise=False, via_ipc=True):
"""Open an URL in new window/tab.
Args:
url: An URL to open.
target: same as new_instance_open_target (used as a default).
no_raise: suppress target window raising.
via_ipc: Whether the arguments were transmitted over IPC.
Return:
ID of a window that was used to open URL
"""
target = target or config.val.new_instance_open_target
background = target in {'tab-bg', 'tab-bg-silent'}
win_id = mainwindow.get_window(via_ipc, force_target=target,
no_raise=no_raise)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
log.init.debug("About to open URL: {}".format(url.toDisplayString()))
tabbed_browser.tabopen(url, background=background, related=False)
return win_id
def _open_startpage(win_id=None):
@@ -303,47 +336,52 @@ def _open_startpage(win_id=None):
window_ids = [win_id]
else:
window_ids = objreg.window_registry
for cur_win_id in window_ids:
for cur_win_id in list(window_ids): # Copying as the dict could change
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=cur_win_id)
if tabbed_browser.count() == 0:
log.init.debug("Opening startpage")
for urlstr in config.get('general', 'startpage'):
try:
url = urlutils.fuzzy_url(urlstr, do_search=False)
except urlutils.InvalidUrlError as e:
message.error("Error when opening startpage: {}".format(e))
tabbed_browser.tabopen(QUrl('about:blank'))
else:
tabbed_browser.tabopen(url)
log.init.debug("Opening start pages")
for url in config.val.url.start_pages:
tabbed_browser.tabopen(url)
def _open_quickstart(args):
"""Open quickstart if it's the first start.
def _open_special_pages(args):
"""Open special notification pages which are only shown once.
Currently this is:
- Quickstart page if it's the first start.
- Legacy QtWebKit warning if needed.
Args:
args: The argparse namespace.
"""
if args.basedir is not None:
# With --basedir given, don't open quickstart.
# With --basedir given, don't open anything.
return
state_config = objreg.get('state-config')
try:
quickstart_done = state_config['general']['quickstart-done'] == '1'
except KeyError:
quickstart_done = False
general_sect = configfiles.state['general']
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
# Quickstart page
quickstart_done = general_sect.get('quickstart-done') == '1'
if not quickstart_done:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
tabbed_browser.tabopen(
QUrl('https://www.qutebrowser.org/quickstart.html'))
state_config['general']['quickstart-done'] = '1'
general_sect['quickstart-done'] = '1'
# Setting migration page
def _save_version():
"""Save the current version to the state config."""
state_config = objreg.get('state-config')
state_config['general']['version'] = qutebrowser.__version__
needs_migration = os.path.exists(
os.path.join(standarddir.config(), 'qutebrowser.conf'))
migration_shown = general_sect.get('config-migration-shown') == '1'
if needs_migration and not migration_shown:
tabbed_browser.tabopen(QUrl('qute://help/configuring.html'),
background=False)
general_sect['config-migration-shown'] = '1'
def on_focus_changed(_old, new):
@@ -380,32 +418,46 @@ 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)
configinit.late_init(save_manager)
log.init.debug("Checking backend requirements...")
backendproblem.init()
log.init.debug("Initializing prompts...")
prompt.init()
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 proxy...")
proxy.init()
log.init.debug("Initializing readline-bridge...")
readline_bridge = readline.ReadlineBridge()
objreg.register('readline-bridge', readline_bridge)
log.init.debug("Initializing config...")
config.init(qApp)
save_manager.init_autosave()
try:
log.init.debug("Initializing sql...")
sql.init(os.path.join(standarddir.data(), 'history.sqlite'))
log.init.debug("Initializing web history...")
history.init(qApp)
log.init.debug("Initializing web history...")
history.init(qApp)
except sql.SqlError as e:
if e.environmental:
error.handle_fatal_exc(e, args, 'Error initializing SQL',
pre_text='Error initializing SQL')
sys.exit(usertypes.Exit.err_init)
else:
raise
log.init.debug("Initializing completion...")
completiondelegate.init()
log.init.debug("Initializing command history...")
cmdhistory.init()
log.init.debug("Initializing crashlog...")
if not args.no_err_windows:
@@ -440,35 +492,12 @@ def _init_modules(args, crash_handler):
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)
macros.init()
# Init backend-specific stuff
browsertab.init()
def _init_late_modules(args):
"""Initialize modules which can be inited after the window is shown."""
log.init.debug("Reading web history...")
reader = objreg.get('web-history').async_read()
with debug.log_time(log.init, 'Reading history'):
while True:
QApplication.processEvents()
try:
next(reader)
except StopIteration:
break
except (OSError, UnicodeDecodeError) as e:
error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init)
class Quitter:
"""Utility class to quit/restart the QApplication.
@@ -511,12 +540,13 @@ class Quitter:
with tokenize.open(os.path.join(dirpath, fn)) as f:
compile(f.read(), fn, 'exec')
def _get_restart_args(self, pages=(), session=None):
def _get_restart_args(self, pages=(), session=None, override_args=None):
"""Get the current working directory and args to relaunch qutebrowser.
Args:
pages: The pages to re-open.
session: The session to load, or None.
override_args: Argument overrides as a dict.
Return:
An (args, cwd) tuple.
@@ -567,6 +597,9 @@ class Quitter:
argdict['temp_basedir'] = False
argdict['temp_basedir_restarted'] = True
if override_args is not None:
argdict.update(override_args)
# Dump the data
data = json.dumps(argdict)
args += ['--json-args', data]
@@ -591,7 +624,7 @@ class Quitter:
if ok:
self.shutdown(restart=True)
def restart(self, pages=(), session=None):
def restart(self, pages=(), session=None, override_args=None):
"""Inner logic to restart qutebrowser.
The "better" way to restart is to pass a session (_restart usually) as
@@ -604,6 +637,7 @@ class Quitter:
Args:
pages: A list of URLs to open.
session: The session to load, or None.
override_args: Argument overrides as a dict.
Return:
True if the restart succeeded, False otherwise.
@@ -613,13 +647,19 @@ class Quitter:
log.destroy.debug("sys.path: {}".format(sys.path))
log.destroy.debug("sys.argv: {}".format(sys.argv))
log.destroy.debug("frozen: {}".format(hasattr(sys, 'frozen')))
# Save the session if one is given.
if session is not None:
session_manager = objreg.get('session-manager')
session_manager.save(session)
session_manager.save(session, with_private=True)
# Make sure we're not accepting a connection from the new process
# before we fully exited.
ipc.server.shutdown()
# Open a new process and immediately shutdown the existing one
try:
args, cwd = self._get_restart_args(pages, session)
args, cwd = self._get_restart_args(pages, session, override_args)
if cwd is None:
subprocess.Popen(args)
else:
@@ -630,8 +670,25 @@ class Quitter:
else:
return True
@cmdutils.register(instance='quitter', name=['quit', 'q'],
ignore_args=True)
@cmdutils.register(instance='quitter', name='quit')
@cmdutils.argument('session', completion=miscmodels.session)
def quit(self, save=False, session=None):
"""Quit qutebrowser.
Args:
save: When given, save the open windows even if auto_save.session
is turned off.
session: The name of the session to save.
"""
if session is not None and not save:
raise cmdexc.CommandError("Session name given without --save!")
if save:
if session is None:
session = sessions.default
self.shutdown(session=session)
else:
self.shutdown()
def shutdown(self, status=0, session=None, last_window=False,
restart=False):
"""Quit qutebrowser.
@@ -648,14 +705,14 @@ class Quitter:
self._shutting_down = True
log.destroy.debug("Shutting down with status {}, session {}...".format(
status, session))
session_manager = objreg.get('session-manager')
if session is not None:
session_manager.save(session, last_window=last_window,
load_next_time=True)
elif config.get('general', 'save-session'):
session_manager.save(sessions.default, last_window=last_window,
load_next_time=True)
session_manager = objreg.get('session-manager', None)
if session_manager is not None:
if session is not None:
session_manager.save(session, last_window=last_window,
load_next_time=True)
elif config.val.auto_save.session:
session_manager.save(sessions.default, last_window=last_window,
load_next_time=True)
if prompt.prompt_queue.shutdown():
# If shutdown was called while we were asking a question, we're in
@@ -672,7 +729,7 @@ class Quitter:
# event loop, so we can shut down immediately.
self._shutdown(status, restart=restart)
def _shutdown(self, status, restart):
def _shutdown(self, status, restart): # noqa
"""Second stage of shutdown."""
log.destroy.debug("Stage 2 of shutting down...")
if qApp is None:
@@ -681,14 +738,16 @@ class Quitter:
# Remove eventfilter
try:
log.destroy.debug("Removing eventfilter...")
qApp.removeEventFilter(objreg.get('event-filter'))
event_filter = objreg.get('event-filter', None)
if event_filter is not None:
qApp.removeEventFilter(event_filter)
except AttributeError:
pass
# Close all windows
QApplication.closeAllWindows()
# Shut down IPC
try:
objreg.get('ipc-server').shutdown()
ipc.server.shutdown()
except KeyError:
pass
# Save everything
@@ -723,21 +782,13 @@ class Quitter:
# Now we can hopefully quit without segfaults
log.destroy.debug("Deferring QApplication::exit...")
objreg.get('signal-handler').deactivate()
objreg.get('session-manager').delete_autosave()
session_manager = objreg.get('session-manager', None)
if session_manager is not None:
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))
@cmdutils.register(instance='quitter', name='wq')
@cmdutils.argument('name', completion=usertypes.Completion.sessions)
def save_and_quit(self, name=sessions.default):
"""Save open pages and quit.
Args:
name: The name of the session.
"""
self.shutdown(session=name)
class Application(QApplication):
@@ -758,7 +809,7 @@ class Application(QApplication):
"""
self._last_focus_object = None
qt_args = qtutils.get_args(args)
qt_args = configinit.qt_args(args)
log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args))
super().__init__(qt_args)
@@ -779,13 +830,22 @@ class Application(QApplication):
log.misc.debug("Focus object changed: {}".format(output))
self._last_focus_object = output
def event(self, e):
"""Handle macOS FileOpen events."""
if e.type() == QEvent.FileOpen:
open_url(e.url(), no_raise=True)
else:
return super().event(e)
return True
def __repr__(self):
return utils.get_repr(self)
def exit(self, status):
"""Extend QApplication::exit to log the event."""
log.destroy.debug("Now calling QApplication::exit.")
if self._args.debug_exit:
if 'debug-exit' in self._args.debug_flags:
if hunter is None:
print("Not logging late shutdown because hunter could not be "
"imported!", file=sys.stderr)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -58,7 +58,7 @@ def get_fileobj(byte_io):
byte_io = zf.open(filename, mode='r')
else:
byte_io.seek(0) # rewind what zipfile.is_zipfile did
return io.TextIOWrapper(byte_io, encoding='utf-8')
return byte_io
def is_whitelisted_host(host):
@@ -67,11 +67,7 @@ def is_whitelisted_host(host):
Args:
host: The host of the request as string.
"""
whitelist = config.get('content', 'host-blocking-whitelist')
if whitelist is None:
return False
for pattern in whitelist:
for pattern in config.val.content.host_blocking.whitelist:
if fnmatch.fnmatch(host, pattern.lower()):
return True
return False
@@ -114,16 +110,16 @@ class HostBlocker:
data_dir = standarddir.data()
self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
self.on_config_changed()
self._update_files()
config_dir = standarddir.config()
self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')
objreg.get('config').changed.connect(self.on_config_changed)
config.instance.changed.connect(self._update_files)
def is_blocked(self, url):
"""Check if the given URL (as QUrl) is blocked."""
if not config.get('content', 'host-blocking-enabled'):
if not config.val.content.host_blocking.enabled:
return False
host = url.host()
return ((host in self._blocked_hosts or
@@ -147,7 +143,7 @@ class HostBlocker:
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
target.add(line.strip())
except OSError:
except (OSError, UnicodeDecodeError):
log.misc.exception("Failed to read host blocklist!")
return True
@@ -164,8 +160,9 @@ class HostBlocker:
if not found:
args = objreg.get('args')
if (config.get('content', 'host-block-lists') is not None and
args.basedir is None):
if (config.val.content.host_blocking.lists and
args.basedir is None and
config.val.content.host_blocking.enabled):
message.info("Run :adblock-update to get adblock lists.")
@cmdutils.register(instance='host-blocker')
@@ -179,18 +176,16 @@ class HostBlocker:
self._config_blocked_hosts)
self._blocked_hosts = set()
self._done_count = 0
urls = config.get('content', 'host-block-lists')
download_manager = objreg.get('qtnetwork-download-manager',
scope='window', window='last-focused')
if urls is None:
return
for url in urls:
for url in config.val.content.host_blocking.lists:
if url.scheme() == 'file':
filename = url.toLocalFile()
try:
fileobj = open(url.path(), 'rb')
fileobj = open(filename, 'rb')
except OSError as e:
message.error("adblock: Error while reading {}: {}".format(
url.path(), e.strerror))
filename, e.strerror))
continue
download = FakeDownload(fileobj)
self._in_progress.append(download)
@@ -205,6 +200,54 @@ class HostBlocker:
download.finished.connect(
functools.partial(self.on_download_finished, download))
def _parse_line(self, line):
"""Parse a line from a host file.
Args:
line: The bytes object to parse.
Returns:
True if parsing succeeded, False otherwise.
"""
if line.startswith(b'#'):
# Ignoring comments early so we don't have to care about
# encoding errors in them.
return True
try:
line = line.decode('utf-8')
except UnicodeDecodeError:
log.misc.error("Failed to decode: {!r}".format(line))
return False
# Remove comments
try:
hash_idx = line.index('#')
line = line[:hash_idx]
except ValueError:
pass
line = line.strip()
# Skip empty lines
if not line:
return True
parts = line.split()
if len(parts) == 1:
# "one host per line" format
host = parts[0]
elif len(parts) == 2:
# /etc/hosts format
host = parts[1]
else:
log.misc.error("Failed to parse: {!r}".format(line))
return False
if host not in self.WHITELISTED:
self._blocked_hosts.add(host)
return True
def _merge_file(self, byte_io):
"""Read and merge host files.
@@ -218,35 +261,18 @@ class HostBlocker:
line_count = 0
try:
f = get_fileobj(byte_io)
except (OSError, UnicodeDecodeError, zipfile.BadZipFile,
zipfile.LargeZipFile, LookupError) as e:
except (OSError, zipfile.BadZipFile, 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
# Remove comments
try:
hash_idx = line.index('#')
line = line[:hash_idx]
except ValueError:
pass
line = line.strip()
# Skip empty lines
if not line:
continue
parts = line.split()
if len(parts) == 1:
# "one host per line" format
host = parts[0]
elif len(parts) == 2:
# /etc/hosts format
host = parts[1]
else:
ok = self._parse_line(line)
if not ok:
error_count += 1
continue
if host not in self.WHITELISTED:
self._blocked_hosts.add(host)
log.misc.debug("{}: read {} lines".format(byte_io.name, line_count))
if error_count > 0:
message.error("adblock: {} read errors for {}".format(
@@ -260,11 +286,10 @@ class HostBlocker:
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):
@config.change_filter('content.host_blocking.lists')
def _update_files(self):
"""Update files when the config changed."""
urls = config.get('content', 'host-block-lists')
if urls is None:
if not config.val.content.host_blocking.lists:
try:
os.remove(self._local_hosts_file)
except FileNotFoundError:

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -21,7 +21,8 @@
import itertools
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF
import attr
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QApplication
@@ -35,11 +36,12 @@ from qutebrowser.browser import mouse, hints
tab_id_gen = itertools.count(0)
def create(win_id, parent=None):
def create(win_id, private, parent=None):
"""Get a QtWebKit/QtWebEngine tab object.
Args:
win_id: The window ID where the tab will be shown.
private: Whether the tab is a private/off the record tab.
parent: The Qt parent to set.
"""
# Importing modules here so we don't depend on QtWebEngine without the
@@ -51,7 +53,8 @@ def create(win_id, parent=None):
else:
from qutebrowser.browser.webkit import webkittab
tab_class = webkittab.WebKitTab
return tab_class(win_id=win_id, mode_manager=mode_manager, parent=parent)
return tab_class(win_id=win_id, mode_manager=mode_manager, private=private,
parent=parent)
def init():
@@ -59,9 +62,6 @@ def init():
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):
@@ -83,6 +83,7 @@ TerminationStatus = usertypes.enum('TerminationStatus', [
])
@attr.s
class TabData:
"""A simple namespace with a fixed set of attributes.
@@ -94,18 +95,29 @@ class TabData:
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.
pinned: Flag to pin the tab.
fullscreen: Whether the tab has a video shown fullscreen currently.
"""
def __init__(self):
self.keep_icon = False
self.viewing_source = False
self.inspector = None
self.override_target = None
keep_icon = attr.ib(False)
viewing_source = attr.ib(False)
inspector = attr.ib(None)
override_target = attr.ib(None)
pinned = attr.ib(False)
fullscreen = attr.ib(False)
class AbstractAction:
"""Attribute of AbstractTab for Qt WebActions."""
"""Attribute of AbstractTab for Qt WebActions.
Class attributes (overridden by subclasses):
action_class: The class actions are defined on (QWeb{Engine,}Page)
action_base: The type of the actions (QWeb{Engine,}Page.WebAction)
"""
action_class = None
action_base = None
def __init__(self):
self._widget = None
@@ -118,6 +130,13 @@ class AbstractAction:
"""Save the current page."""
raise NotImplementedError
def run_string(self, name):
"""Run a webaction based on its name."""
member = getattr(self.action_class, name, None)
if not isinstance(member, self.action_base):
raise WebTabError("{} is not a valid web action!".format(name))
self._widget.triggerPageAction(member)
class AbstractPrinting:
@@ -155,6 +174,8 @@ class AbstractSearch(QObject):
Attributes:
text: The last thing this view was searched for.
search_displayed: Whether we're currently displaying search results in
this view.
_flags: The flags of the last search (needs to be set by subclasses).
_widget: The underlying WebView widget.
"""
@@ -163,14 +184,30 @@ class AbstractSearch(QObject):
super().__init__(parent)
self._widget = None
self.text = None
self.search_displayed = False
def search(self, text, *, ignore_case=False, reverse=False,
def _is_case_sensitive(self, ignore_case):
"""Check if case-sensitivity should be used.
This assumes self.text is already set properly.
Arguments:
ignore_case: The ignore_case value from the config.
"""
mapping = {
'smart': not self.text.islower(),
'never': True,
'always': False,
}
return mapping[ignore_case]
def search(self, text, *, ignore_case='never', reverse=False,
result_cb=None):
"""Find the given text on the page.
Args:
text: The text to search for.
ignore_case: Search case-insensitively. (True/False/'smart')
ignore_case: Search case-insensitively. ('always'/'never/'smart')
reverse: Reverse search direction.
result_cb: Called with a bool indicating whether a match was found.
"""
@@ -212,7 +249,8 @@ class AbstractZoom(QObject):
self._win_id = win_id
self._default_zoom_changed = False
self._init_neighborlist()
objreg.get('config').changed.connect(self._on_config_changed)
config.instance.changed.connect(self._on_config_changed)
self._zoom_factor = float(config.val.zoom.default) / 100
# # FIXME:qtwebengine is this needed?
# # For some reason, this signal doesn't get disconnected automatically
@@ -221,21 +259,20 @@ class AbstractZoom(QObject):
# self.destroyed.connect(functools.partial(
# cfg.changed.disconnect, self.init_neighborlist))
@pyqtSlot(str, str)
def _on_config_changed(self, section, option):
if section == 'ui' and option in ['zoom-levels', 'default-zoom']:
@pyqtSlot(str)
def _on_config_changed(self, option):
if option in ['zoom.levels', 'zoom.default']:
if not self._default_zoom_changed:
factor = float(config.get('ui', 'default-zoom')) / 100
self._set_factor_internal(factor)
self._default_zoom_changed = False
factor = float(config.val.zoom.default) / 100
self.set_factor(factor)
self._init_neighborlist()
def _init_neighborlist(self):
"""Initialize self._neighborlist."""
levels = config.get('ui', 'zoom-levels')
levels = config.val.zoom.levels
self._neighborlist = usertypes.NeighborList(
levels, mode=usertypes.NeighborList.Modes.edge)
self._neighborlist.fuzzyval = config.get('ui', 'default-zoom')
self._neighborlist.fuzzyval = config.val.zoom.default
def offset(self, offset):
"""Increase/Decrease the zoom level by the given offset.
@@ -264,15 +301,21 @@ class AbstractZoom(QObject):
self._neighborlist.fuzzyval = int(factor * 100)
if factor < 0:
raise ValueError("Can't zoom to factor {}!".format(factor))
self._default_zoom_changed = True
default_zoom_factor = float(config.val.zoom.default) / 100
self._default_zoom_changed = (factor != default_zoom_factor)
self._zoom_factor = factor
self._set_factor_internal(factor)
def factor(self):
raise NotImplementedError
return self._zoom_factor
def set_default(self):
default_zoom = config.get('ui', 'default-zoom')
self._set_factor_internal(float(default_zoom) / 100)
self._set_factor_internal(float(config.val.zoom.default) / 100)
def set_current(self):
self._set_factor_internal(self._zoom_factor)
class AbstractCaret(QObject):
@@ -441,11 +484,21 @@ class AbstractHistory:
def current_idx(self):
raise NotImplementedError
def back(self):
raise NotImplementedError
def back(self, count=1):
idx = self.current_idx() - count
if idx >= 0:
self._go_to_item(self._item_at(idx))
else:
self._go_to_item(self._item_at(0))
raise WebTabError("At beginning of history.")
def forward(self):
raise NotImplementedError
def forward(self, count=1):
idx = self.current_idx() + count
if idx < len(self):
self._go_to_item(self._item_at(idx))
else:
self._go_to_item(self._item_at(len(self) - 1))
raise WebTabError("At end of history.")
def can_go_back(self):
raise NotImplementedError
@@ -453,6 +506,12 @@ class AbstractHistory:
def can_go_forward(self):
raise NotImplementedError
def _item_at(self, i):
raise NotImplementedError
def _go_to_item(self, item):
raise NotImplementedError
def serialize(self):
"""Serialize into an opaque format understood by self.deserialize."""
raise NotImplementedError
@@ -524,6 +583,7 @@ class AbstractTab(QWidget):
Attributes:
history: The AbstractHistory for the current tab.
registry: The ObjectRegistry associated with this tab.
private: Whether private browsing is turned on for this tab.
_load_status: loading status of this page
Accessible via load_status() method.
@@ -563,7 +623,8 @@ class AbstractTab(QWidget):
fullscreen_requested = pyqtSignal(bool)
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
def __init__(self, win_id, mode_manager, parent=None):
def __init__(self, *, win_id, mode_manager, private, parent=None):
self.private = private
self.win_id = win_id
self.tab_id = next(tab_id_gen)
super().__init__(parent)
@@ -662,9 +723,9 @@ 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:
def handle_auto_insert_mode(self, ok):
"""Handle `input.insert_mode.auto_load` after loading finished."""
if not config.val.input.insert_mode.auto_load or not ok:
return
cur_mode = self._mode_manager.mode
@@ -699,7 +760,8 @@ 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)
self.zoom.set_current()
@pyqtSlot()
def _on_history_trigger(self):
@@ -740,6 +802,10 @@ class AbstractTab(QWidget):
def clear_ssl_errors(self):
raise NotImplementedError
def key_press(self, key, modifier=Qt.NoModifier):
"""Send a fake key event to this tab."""
raise NotImplementedError
def dump_async(self, callback, *, plain=False):
"""Dump the current page to a file ascync.
@@ -771,7 +837,7 @@ class AbstractTab(QWidget):
def icon(self):
raise NotImplementedError
def set_html(self, html, base_url):
def set_html(self, html, base_url=QUrl()):
raise NotImplementedError
def networkaccessmanager(self):
@@ -794,6 +860,6 @@ class AbstractTab(QWidget):
try:
url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode),
100)
except AttributeError:
url = '<AttributeError>'
except (AttributeError, RuntimeError) as exc:
url = '<{}>'.format(exc.__class__.__name__)
return utils.get_repr(self, tab_id=self.tab_id, url=url)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -23,33 +23,27 @@ import os
import os.path
import shlex
import functools
import typing
from PyQt5.QtWidgets import QApplication, QTabBar
from PyQt5.QtWidgets import QApplication, QTabBar, QDialog
from PyQt5.QtCore import Qt, QUrl, QEvent, QUrlQuery
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
try:
from PyQt5.QtWebKitWidgets import QWebPage
except ImportError:
QWebPage = None
try:
from PyQt5.QtWebEngineWidgets import QWebEnginePage
except ImportError:
QWebEnginePage = None
import pygments
import pygments.lexers
import pygments.formatters
from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners
from qutebrowser.config import config, configexc
from qutebrowser.config import config, configdata
from qutebrowser.browser import (urlmarks, browsertab, inspector, navigate,
webelem, downloads)
from qutebrowser.keyinput import modeman
from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils,
objreg, utils, typing)
objreg, utils, debug)
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.misc import editor, guiprocess
from qutebrowser.completion.models import instances, sortfilter
from qutebrowser.completion.models import urlmodel, miscmodels
from qutebrowser.mainwindow import mainwindow
class CommandDispatcher:
@@ -75,10 +69,9 @@ class CommandDispatcher:
def __repr__(self):
return utils.get_repr(self)
def _new_tabbed_browser(self):
def _new_tabbed_browser(self, private):
"""Get a tabbed-browser from a new window."""
from qutebrowser.mainwindow import mainwindow
new_window = mainwindow.MainWindow()
new_window = mainwindow.MainWindow(private=private)
new_window.show()
return new_window.tabbed_browser
@@ -118,7 +111,7 @@ class CommandDispatcher:
return widget
def _open(self, url, tab=False, background=False, window=False,
explicit=True):
related=False, private=None):
"""Helper function to open a page.
Args:
@@ -126,17 +119,22 @@ class CommandDispatcher:
tab: Whether to open in a new tab.
background: Whether to open in the background.
window: Whether to open in a new window
private: If opening a new window, open it in private browsing mode.
If not given, inherit the current window's mode.
"""
urlutils.raise_cmdexc_if_invalid(url)
tabbed_browser = self._tabbed_browser
cmdutils.check_exclusive((tab, background, window), 'tbw')
if window:
tabbed_browser = self._new_tabbed_browser()
cmdutils.check_exclusive((tab, background, window, private), 'tbwp')
if window and private is None:
private = self._tabbed_browser.private
if window or private:
tabbed_browser = self._new_tabbed_browser(private)
tabbed_browser.tabopen(url)
elif tab:
tabbed_browser.tabopen(url, background=False, explicit=explicit)
tabbed_browser.tabopen(url, background=False, related=related)
elif background:
tabbed_browser.tabopen(url, background=True, explicit=explicit)
tabbed_browser.tabopen(url, background=True, related=related)
else:
widget = self._current_widget()
widget.openurl(url)
@@ -160,12 +158,14 @@ class CommandDispatcher:
else:
return None
def _tab_focus_last(self):
def _tab_focus_last(self, *, show_error=True):
"""Select the tab which was last focused."""
try:
tab = objreg.get('last-focused-tab', scope='window',
window=self._win_id)
except KeyError:
if not show_error:
return
raise cmdexc.CommandError("No last focused tab!")
idx = self._tabbed_browser.indexOf(tab)
if idx == -1:
@@ -179,7 +179,7 @@ class CommandDispatcher:
prev: Force selecting the tab before the current tab.
next_: Force selecting the tab after the current tab.
opposite: Force selecting the tab in the opposite direction of
what's configured in 'tabs->select-on-remove'.
what's configured in 'tabs.select_on_remove'.
Return:
QTabBar.SelectLeftTab, QTabBar.SelectRightTab, or None if no change
@@ -191,38 +191,35 @@ class CommandDispatcher:
elif next_:
return QTabBar.SelectRightTab
elif opposite:
conf_selection = config.get('tabs', 'select-on-remove')
conf_selection = config.val.tabs.select_on_remove
if conf_selection == QTabBar.SelectLeftTab:
return QTabBar.SelectRightTab
elif conf_selection == QTabBar.SelectRightTab:
return QTabBar.SelectLeftTab
elif conf_selection == QTabBar.SelectPreviousTab:
raise cmdexc.CommandError(
"-o is not supported with 'tabs->select-on-remove' set to "
"-o is not supported with 'tabs.select_on_remove' set to "
"'last-used'!")
else: # pragma: no cover
raise ValueError("Invalid select-on-remove value "
raise ValueError("Invalid select_on_remove value "
"{!r}!".format(conf_selection))
return None
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
def tab_close(self, prev=False, next_=False, opposite=False, count=None):
"""Close the current/[count]th tab.
def _tab_close(self, tab, prev=False, next_=False, opposite=False):
"""Helper function for tab_close be able to handle message.async.
Args:
tab: Tab object to select be closed.
prev: Force selecting the tab before the current tab.
next_: Force selecting the tab after the current tab.
opposite: Force selecting the tab in the opposite direction of
what's configured in 'tabs->select-on-remove'.
what's configured in 'tabs.select_on_remove'.
count: The tab index to close, or None
"""
tab = self._cntwidget(count)
if tab is None:
return
tabbar = self._tabbed_browser.tabBar()
selection_override = self._get_selection_override(prev, next_,
opposite)
if selection_override is None:
self._tabbed_browser.close_tab(tab)
else:
@@ -231,12 +228,55 @@ class CommandDispatcher:
self._tabbed_browser.close_tab(tab)
tabbar.setSelectionBehaviorOnRemove(old_selection_behavior)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
def tab_close(self, prev=False, next_=False, opposite=False,
force=False, count=None):
"""Close the current/[count]th tab.
Args:
prev: Force selecting the tab before the current tab.
next_: Force selecting the tab after the current tab.
opposite: Force selecting the tab in the opposite direction of
what's configured in 'tabs.select_on_remove'.
force: Avoid confirmation for pinned tabs.
count: The tab index to close, or None
"""
tab = self._cntwidget(count)
if tab is None:
return
close = functools.partial(self._tab_close, tab, prev,
next_, opposite)
self._tabbed_browser.tab_close_prompt_if_pinned(tab, force, close)
@cmdutils.register(instance='command-dispatcher', scope='window',
name='tab-pin')
@cmdutils.argument('count', count=True)
def tab_pin(self, count=None):
"""Pin/Unpin the current/[count]th tab.
Pinning a tab shrinks it to the size of its title text.
Attempting to close a pinned tab will cause a confirmation,
unless --force is passed.
Args:
count: The tab index to pin or unpin, or None
"""
tab = self._cntwidget(count)
if tab is None:
return
to_pin = not tab.data.pinned
self._tabbed_browser.set_tab_pinned(tab, to_pin)
@cmdutils.register(instance='command-dispatcher', name='open',
maxsplit=0, scope='window')
@cmdutils.argument('url', completion=usertypes.Completion.url)
@cmdutils.argument('url', completion=urlmodel.url)
@cmdutils.argument('count', count=True)
def openurl(self, url=None, implicit=False,
bg=False, tab=False, window=False, count=None):
def openurl(self, url=None, related=False,
bg=False, tab=False, window=False, count=None, secure=False,
private=False):
"""Open a URL in the current/[count]th tab.
If the URL contains newlines, each line gets opened in its own tab.
@@ -246,21 +286,27 @@ class CommandDispatcher:
bg: Open in a new background tab.
tab: Open in a new tab.
window: Open in a new window.
implicit: If opening a new tab, treat the tab as implicit (like
clicking on a link).
related: If opening a new tab, position the tab as related to the
current one (like clicking on a link).
count: The tab index to open the URL in, or None.
secure: Force HTTPS.
private: Open a new window in private browsing mode.
"""
if url is None:
urls = [config.get('general', 'default-page')]
urls = [config.val.url.default_page]
else:
urls = self._parse_url_input(url)
for i, cur_url in enumerate(urls):
if secure:
cur_url.setScheme('https')
if not window and i > 0:
tab = False
bg = True
if tab or bg or window:
self._open(cur_url, tab, bg, window, not implicit)
if tab or bg or window or private:
self._open(cur_url, tab, bg, window, related=related,
private=private)
else:
curtab = self._cntwidget(count)
if curtab is None:
@@ -271,6 +317,8 @@ class CommandDispatcher:
else:
# Explicit count with a tab that doesn't exist.
return
elif curtab.data.pinned:
message.info("Tab is pinned!")
else:
curtab.openurl(cur_url)
@@ -350,7 +398,7 @@ class CommandDispatcher:
message.error("Printing failed!")
tab.printing.check_preview_support()
diag = QPrintPreviewDialog()
diag = QPrintPreviewDialog(tab)
diag.setAttribute(Qt.WA_DeleteOnClose)
diag.setWindowFlags(diag.windowFlags() | Qt.WindowMaximizeButtonHint |
Qt.WindowMinimizeButtonHint)
@@ -376,9 +424,18 @@ class CommandDispatcher:
message.error("Printing failed!")
diag.deleteLater()
diag = QPrintDialog()
diag.open(lambda: tab.printing.to_printer(diag.printer(),
print_callback))
def do_print():
"""Called when the dialog was closed."""
tab.printing.to_printer(diag.printer(), print_callback)
diag = QPrintDialog(tab)
if utils.is_mac:
# For some reason we get a segfault when using open() on macOS
ret = diag.exec_()
if ret == QDialog.Accepted:
do_print()
else:
diag.open(do_print)
@cmdutils.register(instance='command-dispatcher', name='print',
scope='window')
@@ -433,25 +490,27 @@ class CommandDispatcher:
raise cmdexc.CommandError(e)
# The new tab could be in a new tabbed_browser (e.g. because of
# tabs-are-windows being set)
# tabs.tabs_are_windows being set)
if window:
new_tabbed_browser = self._new_tabbed_browser()
new_tabbed_browser = self._new_tabbed_browser(
private=self._tabbed_browser.private)
else:
new_tabbed_browser = self._tabbed_browser
newtab = new_tabbed_browser.tabopen(background=bg, explicit=True)
newtab = new_tabbed_browser.tabopen(background=bg)
new_tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=newtab.win_id)
idx = new_tabbed_browser.indexOf(newtab)
new_tabbed_browser.set_page_title(idx, cur_title)
if config.get('tabs', 'show-favicons'):
if config.val.tabs.favicons.show:
new_tabbed_browser.setTabIcon(idx, curtab.icon())
if config.get('tabs', 'tabs-are-windows'):
if config.val.tabs.tabs_are_windows:
new_tabbed_browser.window().setWindowIcon(curtab.icon())
newtab.data.keep_icon = True
newtab.history.deserialize(history)
newtab.zoom.set_factor(curtab.zoom.factor())
new_tabbed_browser.set_tab_pinned(newtab, curtab.data.pinned)
return newtab
@cmdutils.register(instance='command-dispatcher', scope='window')
@@ -478,15 +537,13 @@ class CommandDispatcher:
else:
widget = self._current_widget()
for _ in range(count):
try:
if forward:
if not widget.history.can_go_forward():
raise cmdexc.CommandError("At end of history.")
widget.history.forward()
widget.history.forward(count)
else:
if not widget.history.can_go_back():
raise cmdexc.CommandError("At beginning of history.")
widget.history.back()
widget.history.back(count)
except browsertab.WebTabError as e:
raise cmdexc.CommandError(e)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
@@ -565,7 +622,7 @@ class CommandDispatcher:
tab=tab, background=bg, window=window)
elif where in ['up', 'increment', 'decrement']:
new_url = handlers[where](url, count)
self._open(new_url, tab, bg, window)
self._open(new_url, tab, bg, window, related=True)
else: # pragma: no cover
raise ValueError("Got called with invalid value {} for "
"`where'.".format(where))
@@ -595,6 +652,9 @@ class CommandDispatcher:
def scroll(self, direction: typing.Union[str, int], count=1):
"""Scroll the current tab in the given direction.
Note you can use `:run-with-count` to have a keybinding with a bigger
scroll increment.
Args:
direction: In which direction to scroll
(up/down/left/right/top/bottom).
@@ -628,7 +688,7 @@ class CommandDispatcher:
scope='window')
@cmdutils.argument('count', count=True)
@cmdutils.argument('horizontal', flag='x')
def scroll_perc(self, perc: float=None, horizontal=False, count=None):
def scroll_to_perc(self, perc: float = None, horizontal=False, count=None):
"""Scroll to a specific percentage of the page.
The percentage can be given either as argument or as count.
@@ -664,7 +724,7 @@ class CommandDispatcher:
@cmdutils.argument('bottom_navigate', metavar='ACTION',
choices=('next', 'increment'))
def scroll_page(self, x: float, y: float, *,
top_navigate: str=None, bottom_navigate: str=None,
top_navigate: str = None, bottom_navigate: str = None,
count=1):
"""Scroll the frame page-wise.
@@ -711,7 +771,7 @@ class CommandDispatcher:
url_query.setQueryDelimiters('=', ';')
url_query.setQuery(url_query_str)
for key in dict(url_query.queryItems()):
if key in config.get('general', 'yank-ignored-url-parameters'):
if key in config.val.url.yank_ignored_parameters:
url_query.removeQueryItem(key)
url.setQuery(url_query)
return url.toString(flags)
@@ -782,7 +842,7 @@ class CommandDispatcher:
perc = tab.zoom.offset(count)
except ValueError as e:
raise cmdexc.CommandError(e)
message.info("Zoom level: {}%".format(perc), replace=True)
message.info("Zoom level: {}%".format(int(perc)), replace=True)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
@@ -797,11 +857,11 @@ class CommandDispatcher:
perc = tab.zoom.offset(-count)
except ValueError as e:
raise cmdexc.CommandError(e)
message.info("Zoom level: {}%".format(perc), replace=True)
message.info("Zoom level: {}%".format(int(perc)), replace=True)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
def zoom(self, zoom: int=None, count=None):
def zoom(self, zoom=None, count=None):
"""Set the zoom level for the current tab.
The zoom can be given as argument or as [count]. If neither is
@@ -812,39 +872,61 @@ class CommandDispatcher:
zoom: The zoom percentage to set.
count: The zoom percentage to set.
"""
if zoom is not None:
try:
zoom = int(zoom.rstrip('%'))
except ValueError:
raise cmdexc.CommandError("zoom: Invalid int value {}"
.format(zoom))
level = count if count is not None else zoom
if level is None:
level = config.get('ui', 'default-zoom')
level = config.val.zoom.default
tab = self._current_widget()
try:
tab.zoom.set_factor(float(level) / 100)
except ValueError:
raise cmdexc.CommandError("Can't zoom {}%!".format(level))
message.info("Zoom level: {}%".format(level), replace=True)
message.info("Zoom level: {}%".format(int(level)), replace=True)
@cmdutils.register(instance='command-dispatcher', scope='window')
def tab_only(self, prev=False, next_=False):
def tab_only(self, prev=False, next_=False, force=False):
"""Close all tabs except for the current one.
Args:
prev: Keep tabs before the current.
next_: Keep tabs after the current.
force: Avoid confirmation for pinned tabs.
"""
cmdutils.check_exclusive((prev, next_), 'pn')
cur_idx = self._tabbed_browser.currentIndex()
assert cur_idx != -1
def _to_close(i):
"""Helper method to check if a tab should be closed or not."""
return not (i == cur_idx or
(prev and i < cur_idx) or
(next_ and i > cur_idx))
# Check to see if we are closing any pinned tabs
if not force:
for i, tab in enumerate(self._tabbed_browser.widgets()):
if _to_close(i) and tab.data.pinned:
self._tabbed_browser.tab_close_prompt_if_pinned(
tab,
force,
lambda: self.tab_only(
prev=prev, next_=next_, force=True))
return
for i, tab in enumerate(self._tabbed_browser.widgets()):
if (i == cur_idx or (prev and i < cur_idx) or
(next_ and i > cur_idx)):
continue
else:
if _to_close(i):
self._tabbed_browser.close_tab(tab)
@cmdutils.register(instance='command-dispatcher', scope='window')
def undo(self):
"""Re-open a closed tab (optionally skipping [count] closed tabs)."""
"""Re-open a closed tab."""
try:
self._tabbed_browser.undo()
except IndexError:
@@ -865,7 +947,7 @@ class CommandDispatcher:
newidx = self._current_index() - count
if newidx >= 0:
self._set_current_index(newidx)
elif config.get('tabs', 'wrap'):
elif config.val.tabs.wrap:
self._set_current_index(newidx % self._count())
else:
raise cmdexc.CommandError("First tab")
@@ -885,7 +967,7 @@ class CommandDispatcher:
newidx = self._current_index() + count
if newidx < self._count():
self._set_current_index(newidx)
elif config.get('tabs', 'wrap'):
elif config.val.tabs.wrap:
self._set_current_index(newidx % self._count())
else:
raise cmdexc.CommandError("Last tab")
@@ -928,31 +1010,39 @@ class CommandDispatcher:
self._open(url, tab, bg, window)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('index', completion=usertypes.Completion.tab)
def buffer(self, index):
@cmdutils.argument('index', completion=miscmodels.buffer)
@cmdutils.argument('count', count=True)
def buffer(self, index=None, count=None):
"""Select tab by index or url/title best match.
Focuses window if necessary.
Focuses window if necessary when index is given. If both index and
count are given, use count.
Args:
index: The [win_id/]index of the tab to focus. Or a substring
in which case the closest match will be focused.
count: The tab index to focus, starting with 1.
"""
index_parts = index.split('/', 1)
if count is not None:
index_parts = [count]
elif index is None:
raise cmdexc.CommandError("buffer: Either a count or the argument "
"index must be specified.")
else:
index_parts = index.split('/', 1)
try:
for part in index_parts:
int(part)
except ValueError:
model = instances.get(usertypes.Completion.tab)
sf = sortfilter.CompletionFilterModel(source=model)
sf.set_pattern(index)
if sf.count() > 0:
index = sf.data(sf.first_item())
index_parts = index.split('/', 1)
else:
raise cmdexc.CommandError(
"No matching tab for: {}".format(index))
try:
for part in index_parts:
int(part)
except ValueError:
model = miscmodels.buffer()
model.set_pattern(index)
if model.count() > 0:
index = model.data(model.first_item())
index_parts = index.split('/', 1)
else:
raise cmdexc.CommandError(
"No matching tab for: {}".format(index))
if len(index_parts) == 2:
win_id = int(index_parts[0])
@@ -984,7 +1074,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('index', choices=['last'])
@cmdutils.argument('count', count=True)
def tab_focus(self, index: typing.Union[str, int]=None, count=None):
def tab_focus(self, index: typing.Union[str, int] = None, count=None):
"""Select the tab given as argument/[count].
If neither count nor index are given, it behaves like tab-next.
@@ -997,12 +1087,15 @@ class CommandDispatcher:
last tab.
count: The tab index to focus, starting with 1.
"""
index = count if count is not None else index
if index == 'last':
self._tab_focus_last()
return
index = count if count is not None else index
if index is None:
elif index == self._current_index() + 1:
self._tab_focus_last(show_error=False)
return
elif index is None:
self.tab_next()
return
@@ -1018,7 +1111,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('index', choices=['+', '-'])
@cmdutils.argument('count', count=True)
def tab_move(self, index: typing.Union[str, int]=None, count=None):
def tab_move(self, index: typing.Union[str, int] = None, count=None):
"""Move the current tab according to the argument and [count].
If neither is given, move it to the first position.
@@ -1040,7 +1133,7 @@ class CommandDispatcher:
elif index == '+': # pragma: no branch
new_idx += delta
if config.get('tabs', 'wrap'):
if config.val.tabs.wrap:
new_idx %= self._count()
else:
# absolute moving
@@ -1076,6 +1169,7 @@ class CommandDispatcher:
detach: Whether the command should be detached from qutebrowser.
cmdline: The commandline to execute.
"""
cmdutils.check_exclusive((userscript, detach), 'ud')
try:
cmd, *args = shlex.split(cmdline)
except ValueError as e:
@@ -1101,7 +1195,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
def home(self):
"""Open main startpage in current tab."""
self.openurl(config.get('general', 'startpage')[0])
self._current_widget().openurl(config.val.url.start_pages[0])
def _run_userscript(self, cmd, *args, verbose=False):
"""Run a userscript given as argument.
@@ -1150,8 +1244,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0)
@cmdutils.argument('name',
completion=usertypes.Completion.quickmark_by_name)
@cmdutils.argument('name', completion=miscmodels.quickmark)
def quickmark_load(self, name, tab=False, bg=False, window=False):
"""Load a quickmark.
@@ -1169,8 +1262,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0)
@cmdutils.argument('name',
completion=usertypes.Completion.quickmark_by_name)
@cmdutils.argument('name', completion=miscmodels.quickmark)
def quickmark_del(self, name=None):
"""Delete a quickmark.
@@ -1227,12 +1319,12 @@ class CommandDispatcher:
except urlmarks.Error as e:
raise cmdexc.CommandError(str(e))
else:
msg = "Bookmarked {}!" if was_added else "Removed bookmark {}!"
msg = "Bookmarked {}" if was_added else "Removed bookmark {}"
message.info(msg.format(url.toDisplayString()))
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0)
@cmdutils.argument('url', completion=usertypes.Completion.bookmark_by_url)
@cmdutils.argument('url', completion=miscmodels.bookmark)
def bookmark_load(self, url, tab=False, bg=False, window=False,
delete=False):
"""Load a bookmark.
@@ -1254,7 +1346,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0)
@cmdutils.argument('url', completion=usertypes.Completion.bookmark_by_url)
@cmdutils.argument('url', completion=miscmodels.bookmark)
def bookmark_del(self, url=None):
"""Delete a bookmark.
@@ -1331,6 +1423,9 @@ class CommandDispatcher:
scope='window', window=self._win_id)
target = None
if dest is not None:
dest = downloads.transform_path(dest)
if dest is None:
raise cmdexc.CommandError("Invalid target filename")
target = downloads.FileDownloadTarget(dest)
tab = self._current_widget()
@@ -1356,8 +1451,18 @@ class CommandDispatcher:
download_manager.get_mhtml(tab, target)
else:
qnam = tab.networkaccessmanager()
download_manager.get(self._current_url(), user_agent=user_agent,
qnam=qnam, target=target)
suggested_fn = downloads.suggested_fn_from_title(
self._current_url().path(), tab.title()
)
download_manager.get(
self._current_url(),
user_agent=user_agent,
qnam=qnam,
target=target,
suggested_fn=suggested_fn
)
@cmdutils.register(instance='command-dispatcher', scope='window')
def view_source(self):
@@ -1368,19 +1473,22 @@ class CommandDispatcher:
if tab.data.viewing_source:
raise cmdexc.CommandError("Already viewing source!")
try:
current_url = self._current_url()
except cmdexc.CommandError as e:
message.error(str(e))
return
def show_source_cb(source):
"""Show source as soon as it's ready."""
lexer = pygments.lexers.HtmlLexer()
formatter = pygments.formatters.HtmlFormatter(full=True,
linenos='table')
formatter = pygments.formatters.HtmlFormatter(
full=True, linenos='table',
title='Source for {}'.format(current_url.toDisplayString()))
highlighted = pygments.highlight(source, lexer, formatter)
try:
current_url = self._current_url()
except cmdexc.CommandError as e:
message.error(str(e))
return
new_tab = self._tabbed_browser.tabopen(explicit=True)
new_tab.set_html(highlighted, current_url)
new_tab = self._tabbed_browser.tabopen()
new_tab.set_html(highlighted)
new_tab.data.viewing_source = True
tab.dump_async(show_source_cb)
@@ -1422,7 +1530,7 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', name='help',
scope='window')
@cmdutils.argument('topic', completion=usertypes.Completion.helptopic)
@cmdutils.argument('topic', completion=miscmodels.helptopic)
def show_help(self, tab=False, bg=False, window=False, topic=None):
r"""Show help about a command or setting.
@@ -1433,7 +1541,7 @@ class CommandDispatcher:
topic: The topic to show help for.
- :__command__ for commands.
- __section__\->__option__ for settings.
- __section__.__option__ for settings.
"""
if topic is None:
path = 'index.html'
@@ -1443,27 +1551,15 @@ class CommandDispatcher:
raise cmdexc.CommandError("Invalid command {}!".format(
command))
path = 'commands.html#{}'.format(command)
elif '->' in topic:
parts = topic.split('->')
if len(parts) != 2:
raise cmdexc.CommandError("Invalid help topic {}!".format(
topic))
try:
config.get(*parts)
except configexc.NoSectionError:
raise cmdexc.CommandError("Invalid section {}!".format(
parts[0]))
except configexc.NoOptionError:
raise cmdexc.CommandError("Invalid option {}!".format(
parts[1]))
path = 'settings.html#{}'.format(topic.replace('->', '-'))
elif topic in configdata.DATA:
path = 'settings.html#{}'.format(topic)
else:
raise cmdexc.CommandError("Invalid help topic {}!".format(topic))
url = QUrl('qute://help/{}'.format(path))
self._open(url, tab, bg, window)
@cmdutils.register(instance='command-dispatcher', scope='window')
def messages(self, level='error', plain=False, tab=False, bg=False,
def messages(self, level='info', plain=False, tab=False, bg=False,
window=False):
"""Show a log of past messages.
@@ -1496,6 +1592,7 @@ class CommandDispatcher:
if text is None:
message.error("Could not get text from the focused element.")
return
assert isinstance(text, str), text
ed = editor.ExternalEditor(self._tabbed_browser)
ed.editing_finished.connect(functools.partial(
@@ -1508,7 +1605,7 @@ class CommandDispatcher:
"""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.
`editor.command` config option.
"""
tab = self._current_widget()
tab.elements.find_focused(self._open_editor_cb)
@@ -1533,10 +1630,7 @@ class CommandDispatcher:
backend=usertypes.Backend.QtWebKit)
def paste_primary(self):
"""Paste the primary selection at cursor position."""
try:
self.insert_text(utils.get_clipboard(selection=True))
except utils.SelectionUnsupportedError:
self.insert_text(utils.get_clipboard())
self.insert_text(utils.get_clipboard(selection=True, fallback=True))
@cmdutils.register(instance='command-dispatcher', maxsplit=0,
scope='window')
@@ -1564,7 +1658,7 @@ class CommandDispatcher:
hide=True)
@cmdutils.argument('filter_', choices=['id'])
def click_element(self, filter_: str, value, *,
target: usertypes.ClickTarget=
target: usertypes.ClickTarget =
usertypes.ClickTarget.normal,
force_event=False):
"""Click the element matching the given filter.
@@ -1645,23 +1739,25 @@ class CommandDispatcher:
"""
self.set_mark("'")
tab = self._current_widget()
tab.search.clear()
if tab.search.search_displayed:
tab.search.clear()
if not text:
return
options = {
'ignore_case': config.get('general', 'ignore-case'),
'ignore_case': config.val.ignore_case,
'reverse': reverse,
}
self._tabbed_browser.search_text = text
self._tabbed_browser.search_options = dict(options)
if text:
cb = functools.partial(self._search_cb, tab=tab,
old_scroll_pos=tab.scroller.pos_px(),
options=options, text=text, prev=False)
else:
cb = None
cb = functools.partial(self._search_cb, tab=tab,
old_scroll_pos=tab.scroller.pos_px(),
options=options, text=text, prev=False)
options['result_cb'] = cb
tab.search.search(text, **options)
@cmdutils.register(instance='command-dispatcher', hide=True,
@@ -1897,38 +1993,25 @@ class CommandDispatcher:
def debug_webaction(self, action, count=1):
"""Execute a webaction.
See http://doc.qt.io/qt-5/qwebpage.html#WebAction-enum for the
available actions.
Available actions:
http://doc.qt.io/archives/qt-5.5/qwebpage.html#WebAction-enum (WebKit)
http://doc.qt.io/qt-5/qwebenginepage.html#WebAction-enum (WebEngine)
Args:
action: The action to execute, e.g. MoveToNextChar.
count: How many times to repeat the action.
"""
tab = self._current_widget()
if tab.backend == usertypes.Backend.QtWebKit:
assert QWebPage is not None
member = getattr(QWebPage, action, None)
base = QWebPage.WebAction
elif tab.backend == usertypes.Backend.QtWebEngine:
assert QWebEnginePage is not None
member = getattr(QWebEnginePage, action, None)
base = QWebEnginePage.WebAction
if not isinstance(member, base):
raise cmdexc.CommandError("{} is not a valid web action!".format(
action))
for _ in range(count):
# This whole command is backend-specific anyways, so it makes no
# sense to introduce some API for this.
# pylint: disable=protected-access
tab._widget.triggerPageAction(member)
try:
tab.action.run_string(action)
except browsertab.WebTabError as e:
raise cmdexc.CommandError(str(e))
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0, no_cmd_split=True)
def jseval(self, js_code, file=False, quiet=False, *,
world: typing.Union[usertypes.JsWorld, int]=None):
world: typing.Union[usertypes.JsWorld, int] = None):
"""Evaluate a JavaScript string.
Args:
@@ -1962,8 +2045,9 @@ class CommandDispatcher:
message.info(out)
if file:
path = os.path.expanduser(js_code)
try:
with open(js_code, 'r', encoding='utf-8') as f:
with open(path, 'r', encoding='utf-8') as f:
js_code = f.read()
except OSError as e:
raise cmdexc.CommandError(str(e))
@@ -2016,7 +2100,7 @@ class CommandDispatcher:
"""Navigate to a url formed in an external editor.
The editor which should be launched can be configured via the
`general -> editor` config option.
`editor.command` config option.
Args:
url: URL to edit; defaults to the current page url.
@@ -2088,6 +2172,10 @@ class CommandDispatcher:
window = self._tabbed_browser.window()
if window.isFullScreen():
window.showNormal()
window.setWindowState(
window.state_before_fullscreen & ~Qt.WindowFullScreen)
else:
window.state_before_fullscreen = window.windowState()
window.showFullScreen()
log.misc.debug('state before fullscreen: {}'.format(
debug.qflags_key(Qt, window.state_before_fullscreen)))

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -19,11 +19,13 @@
"""Shared QtWebKit/QtWebEngine code for downloads."""
import re
import sys
import html
import os.path
import collections
import functools
import pathlib
import tempfile
import sip
@@ -67,15 +69,22 @@ class UnsupportedOperationError(Exception):
def download_dir():
"""Get the download directory to use."""
directory = config.get('storage', 'download-directory')
remember_dir = config.get('storage', 'remember-download-directory')
directory = config.val.downloads.location.directory
remember_dir = config.val.downloads.location.remember
if remember_dir and last_used_directory is not None:
return last_used_directory
ddir = last_used_directory
elif directory is None:
return standarddir.download()
ddir = standarddir.download()
else:
return directory
ddir = directory
try:
os.makedirs(ddir)
except FileExistsError:
pass
return ddir
def immediate_download_path(prompt_download_directory=None):
@@ -86,11 +95,10 @@ def immediate_download_path(prompt_download_directory=None):
Args:
prompt_download_directory: If this is something else than None, it
will overwrite the
storage->prompt-download-directory setting.
downloads.location.prompt setting.
"""
if prompt_download_directory is None:
prompt_download_directory = config.get('storage',
'prompt-download-directory')
prompt_download_directory = config.val.downloads.location.prompt
if not prompt_download_directory:
return download_dir()
@@ -102,7 +110,7 @@ def _path_suggestion(filename):
Args:
filename: The filename to use if included in the suggestion.
"""
suggestion = config.get('completion', 'download-path-suggestion')
suggestion = config.val.downloads.location.suggestion
if suggestion == 'path':
# add trailing '/' if not present
return os.path.join(download_dir(), '')
@@ -161,6 +169,47 @@ def get_filename_question(*, suggested_filename, url, parent=None):
return q
def transform_path(path):
r"""Do platform-specific transformations, like changing E: to E:\.
Returns None if the path is invalid on the current platform.
"""
if not utils.is_windows:
return path
path = utils.expand_windows_drive(path)
# Drive dependent working directories are not supported, e.g.
# E:filename is invalid
if re.match(r'[A-Z]:[^\\]', path, re.IGNORECASE):
return None
# Paths like COM1, ...
# See https://github.com/qutebrowser/qutebrowser/issues/82
if pathlib.Path(path).is_reserved():
return None
return path
def suggested_fn_from_title(url_path, title=None):
"""Suggest a filename depending on the URL extension and page title.
Args:
url_path: a string with the URL path
title: the page title string
Return:
The download filename based on the title, or None if the extension is
not found in the whitelist (or if there is no page title).
"""
ext_whitelist = [".html", ".htm", ".php", ""]
_, ext = os.path.splitext(url_path)
if ext.lower() in ext_whitelist and title:
suggested_fn = utils.sanitize_filename(title)
if not suggested_fn.lower().endswith((".html", ".htm")):
suggested_fn += ".html"
else:
suggested_fn = None
return suggested_fn
class NoFilenameError(Exception):
"""Raised when we can't find out a filename in DownloadTarget."""
@@ -451,13 +500,13 @@ class AbstractDownloadItem(QObject):
Args:
position: The color type requested, can be 'fg' or 'bg'.
"""
# pylint: disable=bad-config-call
# WORKAROUND for https://bitbucket.org/logilab/astroid/issue/104/
assert position in ["fg", "bg"]
start = config.get('colors', 'downloads.{}.start'.format(position))
stop = config.get('colors', 'downloads.{}.stop'.format(position))
system = config.get('colors', 'downloads.{}.system'.format(position))
error = config.get('colors', 'downloads.{}.error'.format(position))
# pylint: disable=bad-config-option
start = getattr(config.val.colors.downloads.start, position)
stop = getattr(config.val.colors.downloads.stop, position)
system = getattr(config.val.colors.downloads.system, position)
error = getattr(config.val.colors.downloads.error, position)
# pylint: enable=bad-config-option
if self.error_msg is not None:
assert not self.successful
return error
@@ -507,6 +556,14 @@ class AbstractDownloadItem(QObject):
"""Retry a failed download."""
raise NotImplementedError
@pyqtSlot()
def try_retry(self):
"""Try to retry a download and show an error if it's unsupported."""
try:
self.retry()
except UnsupportedOperationError as e:
message.error(str(e))
def _get_open_filename(self):
"""Get the filename to open a download.
@@ -521,7 +578,7 @@ class AbstractDownloadItem(QObject):
Args:
cmdline: The command to use as string. A `{}` is expanded to the
filename. None means to use the system's default
application or `default-open-dispatcher` if set. If no
application or `downloads.open_dispatcher` if set. If no
`{}` is found, the filename is appended to the cmdline.
"""
assert self.successful
@@ -529,7 +586,11 @@ class AbstractDownloadItem(QObject):
if filename is None: # pragma: no cover
log.downloads.error("No filename to open the download!")
return
utils.open_file(filename, cmdline)
# By using a singleshot timer, we ensure that we return fast. This
# is important on systems where process creation takes long, as
# otherwise the prompt might hang around and cause bugs
# (see issue #2296)
QTimer.singleShot(0, lambda: utils.open_file(filename, cmdline))
def _ensure_can_set_filename(self, filename):
"""Make sure we can still set a filename."""
@@ -702,7 +763,7 @@ class AbstractDownloadManager(QObject):
download.remove_requested.connect(functools.partial(
self._remove_item, download))
delay = config.get('ui', 'remove-finished-downloads')
delay = config.val.downloads.remove_finished
if delay > -1:
download.finished.connect(
lambda: QTimer.singleShot(delay, download.remove))
@@ -919,7 +980,7 @@ class DownloadModel(QAbstractListModel):
@cmdutils.register(instance='download-model', scope='window', maxsplit=0)
@cmdutils.argument('count', count=True)
def download_open(self, cmdline: str=None, count=0):
def download_open(self, cmdline: str = None, count=0):
"""Open the last/[count]th download.
If no specific command is given, this will use the system's default
@@ -964,7 +1025,7 @@ class DownloadModel(QAbstractListModel):
raise cmdexc.CommandError("No failed downloads!")
else:
download = to_retry[0]
download.retry()
download.try_retry()
def can_clear(self):
"""Check if there are finished downloads to clear."""

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -23,10 +23,10 @@ import functools
import sip
from PyQt5.QtCore import pyqtSlot, QSize, Qt, QTimer
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu, QStyleFactory
from qutebrowser.browser import downloads
from qutebrowser.config import style
from qutebrowser.config import config
from qutebrowser.utils import qtutils, utils, objreg
@@ -64,8 +64,8 @@ class DownloadView(QListView):
STYLESHEET = """
QListView {
background-color: {{ color['downloads.bg.bar'] }};
font: {{ font['downloads'] }};
background-color: {{ conf.colors.downloads.bar.bg }};
font: {{ conf.fonts.downloads }};
}
QListView::item {
@@ -75,7 +75,8 @@ class DownloadView(QListView):
def __init__(self, win_id, parent=None):
super().__init__(parent)
style.set_register_stylesheet(self)
self.setStyle(QStyleFactory.create('Fusion'))
config.set_register_stylesheet(self)
self.setResizeMode(QListView.Adjust)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
@@ -134,7 +135,7 @@ class DownloadView(QListView):
if item.successful:
actions.append(("Open", item.open_file))
else:
actions.append(("Retry", item.retry))
actions.append(("Retry", item.try_retry))
actions.append(("Remove", item.remove))
else:
actions.append(("Cancel", item.cancel))

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -26,10 +26,11 @@ import re
import html
from string import ascii_lowercase
import attr
from PyQt5.QtCore import pyqtSlot, QObject, Qt, QUrl
from PyQt5.QtWidgets import QLabel
from qutebrowser.config import config, style
from qutebrowser.config import config
from qutebrowser.keyinput import modeman, modeparsers
from qutebrowser.browser import webelem
from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners
@@ -65,10 +66,10 @@ class HintLabel(QLabel):
STYLESHEET = """
QLabel {
background-color: {{ color['hints.bg'] }};
color: {{ color['hints.fg'] }};
font: {{ font['hints'] }};
border: {{ config.get('hints', 'border') }};
background-color: {{ conf.colors.hints.bg }};
color: {{ conf.colors.hints.fg }};
font: {{ conf.fonts.hints }};
border: {{ conf.hints.border }};
padding-left: -3px;
padding-right: -3px;
}
@@ -80,7 +81,7 @@ class HintLabel(QLabel):
self.elem = elem
self.setAttribute(Qt.WA_StyledBackground, True)
style.set_register_stylesheet(self)
config.set_register_stylesheet(self)
self._context.tab.contents_size_changed.connect(self._move_to_elem)
self._move_to_elem()
@@ -100,7 +101,7 @@ class HintLabel(QLabel):
matched: The part of the text which was typed.
unmatched: The part of the text which was not typed yet.
"""
if (config.get('hints', 'uppercase') and
if (config.val.hints.uppercase and
self._context.hint_mode in ['letter', 'word']):
matched = html.escape(matched.upper())
unmatched = html.escape(unmatched.upper())
@@ -108,7 +109,7 @@ class HintLabel(QLabel):
matched = html.escape(matched)
unmatched = html.escape(unmatched)
match_color = html.escape(config.get('colors', 'hints.fg.match'))
match_color = html.escape(config.val.colors.hints.match.fg)
self.setText('<font color="{}">{}</font>{}'.format(
match_color, matched, unmatched))
self.adjustSize()
@@ -121,7 +122,7 @@ class HintLabel(QLabel):
log.hints.debug("Frame for {!r} vanished!".format(self))
self.hide()
return
no_js = config.get('hints', 'find-implementation') != 'javascript'
no_js = config.val.hints.find_implementation != 'javascript'
rect = self.elem.rect_on_view(no_js=no_js)
self.move(rect.x(), rect.y())
@@ -131,6 +132,7 @@ class HintLabel(QLabel):
self.deleteLater()
@attr.s
class HintContext:
"""Context namespace used for hinting.
@@ -158,19 +160,18 @@ class HintContext:
group: The group of web elements to hint.
"""
def __init__(self):
self.all_labels = []
self.labels = {}
self.target = None
self.baseurl = None
self.to_follow = None
self.rapid = False
self.add_history = False
self.filterstr = None
self.args = []
self.tab = None
self.group = None
self.hint_mode = None
all_labels = attr.ib(attr.Factory(list))
labels = attr.ib(attr.Factory(dict))
target = attr.ib(None)
baseurl = attr.ib(None)
to_follow = attr.ib(None)
rapid = attr.ib(False)
add_history = attr.ib(False)
filterstr = attr.ib(None)
args = attr.ib(attr.Factory(list))
tab = attr.ib(None)
group = attr.ib(None)
hint_mode = attr.ib(None)
def get_args(self, urlstr):
"""Get the arguments, with {hint-url} replaced by the given URL."""
@@ -203,7 +204,7 @@ class HintActions:
Target.window: usertypes.ClickTarget.window,
Target.hover: usertypes.ClickTarget.normal,
}
if config.get('tabs', 'background-tabs'):
if config.val.tabs.background:
target_mapping[Target.tab] = usertypes.ClickTarget.tab_bg
else:
target_mapping[Target.tab] = usertypes.ClickTarget.tab
@@ -389,6 +390,7 @@ class HintManager(QObject):
def _cleanup(self):
"""Clean up after hinting."""
# pylint: disable=not-an-iterable
for label in self._context.all_labels:
label.cleanup()
@@ -421,9 +423,9 @@ class HintManager(QObject):
if hint_mode == 'number':
chars = '0123456789'
else:
chars = config.get('hints', 'chars')
min_chars = config.get('hints', 'min-chars')
if config.get('hints', 'scatter') and hint_mode != 'number':
chars = config.val.hints.chars
min_chars = config.val.hints.min_chars
if config.val.hints.scatter and hint_mode != 'number':
return self._hint_scattered(min_chars, chars, elems)
else:
return self._hint_linear(min_chars, chars, elems)
@@ -579,12 +581,10 @@ class HintManager(QObject):
if elems is None:
message.error("There was an error while getting hint elements")
return
filterfunc = webelem.FILTERS.get(self._context.group, lambda e: True)
elems = [e for e in elems if filterfunc(e)]
if not elems:
message.error("No elements found.")
return
strings = self._hint_strings(elems)
log.hints.debug("hints: {}".format(', '.join(strings)))
@@ -605,7 +605,7 @@ class HintManager(QObject):
modeman.enter(self._win_id, usertypes.KeyMode.hint,
'HintManager.start')
# to make auto-follow == 'always' work
# to make auto_follow == 'always' work
self._handle_auto_follow()
@cmdutils.register(instance='hintmanager', scope='tab', name='hint',
@@ -617,7 +617,7 @@ class HintManager(QObject):
Args:
rapid: Whether to do rapid hinting. This is only possible with
targets `tab` (with background-tabs=true), `tab-bg`,
targets `tab` (with `tabs.background_tabs=true`), `tab-bg`,
`window`, `run`, `hover`, `userscript` and `spawn`.
add_history: Whether to add the spawned or yanked link to the
browsing history.
@@ -633,7 +633,7 @@ class HintManager(QObject):
- `normal`: Open the link.
- `current`: Open the link in the current tab.
- `tab`: Open the link in a new tab (honoring the
background-tabs setting).
`tabs.background_tabs` setting).
- `tab-fg`: Open the link in a new foreground tab.
- `tab-bg`: Open the link in a new background tab.
- `window`: Open the link in a new window.
@@ -651,7 +651,7 @@ class HintManager(QObject):
mode: The hinting mode to use.
- `number`: Use numeric hints.
- `letter`: Use the chars in the hints->chars settings.
- `letter`: Use the chars in the hints.chars setting.
- `word`: Use hint words based on the html elements and the
extra words.
@@ -686,8 +686,7 @@ class HintManager(QObject):
Target.hover, Target.userscript, Target.spawn,
Target.download, Target.normal, Target.current]:
pass
elif (target == Target.tab and
config.get('tabs', 'background-tabs')):
elif target == Target.tab and config.val.tabs.background:
pass
else:
name = target.name.replace('_', '-')
@@ -695,7 +694,7 @@ class HintManager(QObject):
"target {}!".format(name))
if mode is None:
mode = config.get('hints', 'mode')
mode = config.val.hints.mode
self._check_args(target, *args)
self._context = HintContext()
@@ -722,7 +721,7 @@ class HintManager(QObject):
return self._context.hint_mode
def _handle_auto_follow(self, keystr="", filterstr="", visible=None):
"""Handle the auto-follow option."""
"""Handle the auto_follow option."""
if visible is None:
visible = {string: label
for string, label in self._context.labels.items()
@@ -731,7 +730,7 @@ class HintManager(QObject):
if len(visible) != 1:
return
auto_follow = config.get('hints', 'auto-follow')
auto_follow = config.val.hints.auto_follow
if auto_follow == "always":
follow = True
@@ -748,8 +747,8 @@ class HintManager(QObject):
self._context.to_follow = list(visible.keys())[0]
if follow:
# apply auto-follow-timeout
timeout = config.get('hints', 'auto-follow-timeout')
# apply auto_follow_timeout
timeout = config.val.hints.auto_follow_timeout
keyparsers = objreg.get('keyparsers', scope='window',
window=self._win_id)
normal_parser = keyparsers[usertypes.KeyMode.normal]
@@ -773,9 +772,9 @@ class HintManager(QObject):
label.show()
else:
# element doesn't match anymore -> hide it, unless in rapid
# mode and hide-unmatched-rapid-hints is false (see #1799)
# mode and hide_unmatched_rapid_hints is false (see #1799)
if (not self._context.rapid or
config.get('hints', 'hide-unmatched-rapid-hints')):
config.val.hints.hide_unmatched_rapid_hints):
label.hide()
except webelem.Error:
pass
@@ -795,7 +794,10 @@ class HintManager(QObject):
else:
self._context.filterstr = filterstr
log.hints.debug("Filtering hints on {!r}".format(filterstr))
visible = []
# pylint: disable=not-an-iterable
for label in self._context.all_labels:
try:
if self._filter_matches(filterstr, str(label.elem)):
@@ -940,7 +942,7 @@ class WordHinter:
def ensure_initialized(self):
"""Generate the used words if yet uninitialized."""
dictionary = config.get("hints", "dictionary")
dictionary = config.val.hints.dictionary
if not self.words or self.dictionary != dictionary:
self.words.clear()
self.dictionary = dictionary

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -19,215 +19,110 @@
"""Simple history which gets written to disk."""
import os
import time
import collections
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject
from PyQt5.QtCore import pyqtSlot, QUrl, QTimer
from qutebrowser.commands import cmdutils
from qutebrowser.utils import (utils, objreg, standarddir, log, qtutils,
usertypes, message)
from qutebrowser.config import config
from qutebrowser.misc import lineparser, objects
from qutebrowser.commands import cmdutils, cmdexc
from qutebrowser.utils import (utils, objreg, log, usertypes, message,
debug, standarddir, qtutils)
from qutebrowser.misc import objects, sql
class Entry:
"""A single entry in the web history.
Attributes:
atime: The time the page was accessed.
url: The URL which was accessed as QUrl.
redirect: If True, don't save this entry to disk
"""
def __init__(self, atime, url, title, redirect=False):
self.atime = float(atime)
self.url = url
self.title = title
self.redirect = redirect
qtutils.ensure_valid(url)
def __repr__(self):
return utils.get_repr(self, constructor=True, atime=self.atime,
url=self.url_str(), title=self.title,
redirect=self.redirect)
def __str__(self):
atime = str(int(self.atime))
if self.redirect:
atime += '-r' # redirect flag
elems = [atime, self.url_str()]
if self.title:
elems.append(self.title)
return ' '.join(elems)
def __eq__(self, other):
return (self.atime == other.atime and
self.title == other.title and
self.url == other.url and
self.redirect == other.redirect)
def url_str(self):
"""Get the URL as a lossless string."""
return self.url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
@classmethod
def from_str(cls, line):
"""Parse a history line like '12345 http://example.com title'."""
data = line.split(maxsplit=2)
if len(data) == 2:
atime, url = data
title = ""
elif len(data) == 3:
atime, url, title = data
else:
raise ValueError("2 or 3 fields expected")
url = QUrl(url)
if not url.isValid():
raise ValueError("Invalid URL: {}".format(url.errorString()))
# https://github.com/qutebrowser/qutebrowser/issues/670
atime = atime.lstrip('\0')
if '-' in atime:
atime, flags = atime.split('-')
else:
flags = ''
if not set(flags).issubset('r'):
raise ValueError("Invalid flags {!r}".format(flags))
redirect = 'r' in flags
return cls(atime, url, title, redirect=redirect)
# increment to indicate that HistoryCompletion must be regenerated
_USER_VERSION = 1
class WebHistory(QObject):
class CompletionHistory(sql.SqlTable):
"""The global history of visited pages.
"""History which only has the newest entry for each URL."""
This is a little more complex as you'd expect so the history can be read
from disk async while new history is already arriving.
def __init__(self, parent=None):
super().__init__("CompletionHistory", ['url', 'title', 'last_atime'],
constraints={'url': 'PRIMARY KEY',
'title': 'NOT NULL',
'last_atime': 'NOT NULL'},
parent=parent)
self.create_index('CompletionHistoryAtimeIndex', 'last_atime')
self.history_dict is the main place where the history is stored, in an
OrderedDict (sorted by time) of URL strings mapped to Entry objects.
While reading from disk is still ongoing, the history is saved in
self._temp_history instead, and then appended to self.history_dict once
that's fully populated.
class WebHistory(sql.SqlTable):
All history which is new in this session (rather than read from disk from a
previous browsing session) is also stored in self._new_history.
self._saved_count tracks how many of those entries were already written to
disk, so we can always append to the existing data.
"""The global history of visited pages."""
Attributes:
history_dict: An OrderedDict of URLs read from the on-disk history.
_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.
_initial_read_started: Whether async_read was called.
_initial_read_done: Whether async_read has completed.
_temp_history: OrderedDict of temporary history entries before
async_read was called.
def __init__(self, parent=None):
super().__init__("History", ['url', 'title', 'atime', 'redirect'],
constraints={'url': 'NOT NULL',
'title': 'NOT NULL',
'atime': 'NOT NULL',
'redirect': 'NOT NULL'},
parent=parent)
self.completion = CompletionHistory(parent=self)
if sql.Query('pragma user_version').run().value() < _USER_VERSION:
self.completion.delete_all()
if not self.completion:
# either the table is out-of-date or the user wiped it manually
self._rebuild_completion()
self.create_index('HistoryIndex', 'url')
self.create_index('HistoryAtimeIndex', 'atime')
self._contains_query = self.contains_query('url')
self._between_query = sql.Query('SELECT * FROM History '
'where not redirect '
'and not url like "qute://%" '
'and atime > :earliest '
'and atime <= :latest '
'ORDER BY atime desc')
Signals:
add_completion_item: Emitted before a new Entry is added.
Used to sync with the completion.
arg: The new Entry.
item_added: Emitted after a new Entry is added.
Used to tell the savemanager that the history is dirty.
arg: The new Entry.
cleared: Emitted after the history is cleared.
"""
add_completion_item = pyqtSignal(Entry)
item_added = pyqtSignal(Entry)
cleared = pyqtSignal()
async_read_done = pyqtSignal()
def __init__(self, hist_dir, hist_name, parent=None):
super().__init__(parent)
self._initial_read_started = False
self._initial_read_done = False
self._lineparser = lineparser.AppendLineParser(hist_dir, hist_name,
parent=self)
self.history_dict = collections.OrderedDict()
self._temp_history = collections.OrderedDict()
self._new_history = []
self._saved_count = 0
objreg.get('save-manager').add_saveable(
'history', self.save, self.item_added)
self._before_query = sql.Query('SELECT * FROM History '
'where not redirect '
'and not url like "qute://%" '
'and atime <= :latest '
'ORDER BY atime desc '
'limit :limit offset :offset')
def __repr__(self):
return utils.get_repr(self, length=len(self))
def __iter__(self):
return iter(self.history_dict.values())
def __contains__(self, url):
return self._contains_query.run(val=url).value()
def __len__(self):
return len(self.history_dict)
def async_read(self):
"""Read the initial history."""
if self._initial_read_started:
log.init.debug("Ignoring async_read() because reading is started.")
return
self._initial_read_started = True
with self._lineparser.open():
for line in self._lineparser:
yield
line = line.rstrip()
if not line:
continue
try:
entry = Entry.from_str(line)
except ValueError as e:
log.init.warning("Invalid history entry {!r}: {}!".format(
line, e))
continue
# This de-duplicates history entries; only the latest
# entry for each URL is kept. If you want to keep
# information about previous hits change the items in
# old_urls to be lists or change Entry to have a
# list of atimes.
self._add_entry(entry)
self._initial_read_done = True
self.async_read_done.emit()
for entry in self._temp_history.values():
self._add_entry(entry)
self._new_history.append(entry)
if not entry.redirect:
self.add_completion_item.emit(entry)
self._temp_history.clear()
def _add_entry(self, entry, target=None):
"""Add an entry to self.history_dict or another given OrderedDict."""
if target is None:
target = self.history_dict
url_str = entry.url_str()
target[url_str] = entry
target.move_to_end(url_str)
def _rebuild_completion(self):
data = {'url': [], 'title': [], 'last_atime': []}
# select the latest entry for each url
q = sql.Query('SELECT url, title, max(atime) AS atime FROM History '
'WHERE NOT redirect GROUP BY url ORDER BY atime asc')
for entry in q.run():
data['url'].append(self._format_completion_url(QUrl(entry.url)))
data['title'].append(entry.title)
data['last_atime'].append(entry.atime)
self.completion.insert_batch(data, replace=True)
sql.Query('pragma user_version = {}'.format(_USER_VERSION)).run()
def get_recent(self):
"""Get the most recent history entries."""
old = self._lineparser.get_recent()
return old + [str(e) for e in self._new_history]
return self.select(sort_by='atime', sort_order='desc', limit=100)
def save(self):
"""Save the history to disk."""
new = (str(e) for e in self._new_history[self._saved_count:])
self._lineparser.new_data = new
self._lineparser.save()
self._saved_count = len(self._new_history)
def entries_between(self, earliest, latest):
"""Iterate non-redirect, non-qute entries between two timestamps.
Args:
earliest: Omit timestamps earlier than this.
latest: Omit timestamps later than this.
"""
self._between_query.run(earliest=earliest, latest=latest)
return iter(self._between_query)
def entries_before(self, latest, limit, offset):
"""Iterate non-redirect, non-qute entries occurring before a timestamp.
Args:
latest: Omit timestamps more recent than this.
limit: Max number of entries to include.
offset: Number of entries to skip.
"""
self._before_query.run(latest=latest, limit=limit, offset=offset)
return iter(self._before_query)
@cmdutils.register(name='history-clear', instance='web-history')
def clear(self, force=False):
@@ -244,19 +139,32 @@ class WebHistory(QObject):
self._do_clear()
else:
message.confirm_async(self._do_clear, title="Clear all browsing "
"history?")
"history?")
def _do_clear(self):
self._lineparser.clear()
self.history_dict.clear()
self._temp_history.clear()
self._new_history.clear()
self._saved_count = 0
self.cleared.emit()
self.delete_all()
self.completion.delete_all()
def delete_url(self, url):
"""Remove all history entries with the given url.
Args:
url: URL string to delete.
"""
qurl = QUrl(url)
qtutils.ensure_valid(qurl)
self.delete('url', self._format_url(qurl))
self.completion.delete('url', self._format_completion_url(qurl))
@pyqtSlot(QUrl, QUrl, str)
def add_from_tab(self, url, requested_url, title):
"""Add a new history entry as slot, called from a BrowserTab."""
if url.scheme() == 'data' or requested_url.scheme() == 'data':
return
if url.isEmpty():
# things set via setHtml
return
no_formatting = QUrl.UrlFormattingOption(0)
if (requested_url.isValid() and
not requested_url.matches(url, no_formatting)):
@@ -274,23 +182,158 @@ class WebHistory(QObject):
(hidden in completion)
atime: Override the atime used to add the entry
"""
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)
if self._initial_read_done:
self._add_entry(entry)
self._new_history.append(entry)
self.item_added.emit(entry)
if not entry.redirect:
self.add_completion_item.emit(entry)
if 'no-sql-history' in objreg.get('args').debug_flags:
return
atime = int(atime) if (atime is not None) else int(time.time())
try:
self.insert({'url': self._format_url(url),
'title': title,
'atime': atime,
'redirect': redirect})
if not redirect:
self.completion.insert({
'url': self._format_completion_url(url),
'title': title,
'last_atime': atime
}, replace=True)
except sql.SqlError as e:
if e.environmental:
message.error("Failed to write history: {}".format(e.text()))
else:
raise
def _parse_entry(self, line):
"""Parse a history line like '12345 http://example.com title'."""
if not line or line.startswith('#'):
return None
data = line.split(maxsplit=2)
if len(data) == 2:
atime, url = data
title = ""
elif len(data) == 3:
atime, url, title = data
else:
self._add_entry(entry, target=self._temp_history)
raise ValueError("2 or 3 fields expected")
# http://xn--pple-43d.com/ with
# https://bugreports.qt.io/browse/QTBUG-60364
if url in ['http://.com/', 'https://.com/',
'http://www..com/', 'https://www..com/']:
return None
url = QUrl(url)
if not url.isValid():
raise ValueError("Invalid URL: {}".format(url.errorString()))
# https://github.com/qutebrowser/qutebrowser/issues/2646
if url.scheme() == 'data':
return None
# https://github.com/qutebrowser/qutebrowser/issues/670
atime = atime.lstrip('\0')
if '-' in atime:
atime, flags = atime.split('-')
else:
flags = ''
if not set(flags).issubset('r'):
raise ValueError("Invalid flags {!r}".format(flags))
redirect = 'r' in flags
return (url, title, int(atime), redirect)
def import_txt(self):
"""Import a history text file into sqlite if it exists.
In older versions of qutebrowser, history was stored in a text format.
This converts that file into the new sqlite format and moves it to a
backup location.
"""
path = os.path.join(standarddir.data(), 'history')
if not os.path.isfile(path):
return
def action():
with debug.log_time(log.init, 'Import old history file to sqlite'):
try:
self._read(path)
except ValueError as ex:
message.error('Failed to import history: {}'.format(ex))
else:
self._write_backup(path)
# delay to give message time to appear before locking down for import
message.info('Converting {} to sqlite...'.format(path))
QTimer.singleShot(100, action)
def _read(self, path):
"""Import a text file into the sql database."""
with open(path, 'r', encoding='utf-8') as f:
data = {'url': [], 'title': [], 'atime': [], 'redirect': []}
completion_data = {'url': [], 'title': [], 'last_atime': []}
for (i, line) in enumerate(f):
try:
parsed = self._parse_entry(line.strip())
if parsed is None:
continue
url, title, atime, redirect = parsed
data['url'].append(self._format_url(url))
data['title'].append(title)
data['atime'].append(atime)
data['redirect'].append(redirect)
if not redirect:
completion_data['url'].append(
self._format_completion_url(url))
completion_data['title'].append(title)
completion_data['last_atime'].append(atime)
except ValueError as ex:
raise ValueError('Failed to parse line #{} of {}: "{}"'
.format(i, path, ex))
self.insert_batch(data)
self.completion.insert_batch(completion_data, replace=True)
def _write_backup(self, path):
bak = path + '.bak'
message.info('History import complete. Appending {} to {}'
.format(path, bak))
with open(path, 'r', encoding='utf-8') as infile:
with open(bak, 'a', encoding='utf-8') as outfile:
for line in infile:
outfile.write('\n' + line)
os.remove(path)
def _format_url(self, url):
return url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
def _format_completion_url(self, url):
return url.toString(QUrl.RemovePassword)
@cmdutils.register(instance='web-history', debug=True)
def debug_dump_history(self, dest):
"""Dump the history to a file in the old pre-SQL format.
Args:
dest: Where to write the file to.
"""
dest = os.path.expanduser(dest)
lines = ('{}{} {} {}'
.format(int(x.atime), '-r' * x.redirect, x.url, x.title)
for x in self.select(sort_by='atime', sort_order='asc'))
try:
with open(dest, 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
message.info("Dumped history to {}".format(dest))
except OSError as e:
raise cmdexc.CommandError('Could not write history: {}', e)
def init(parent=None):
@@ -299,10 +342,9 @@ def init(parent=None):
Args:
parent: The parent to use for WebHistory.
"""
history = WebHistory(hist_dir=standarddir.data(), hist_name='history',
parent=parent)
history = WebHistory(parent=parent)
objreg.register('web-history', history)
if objects.backend == usertypes.Backend.QtWebKit:
if objects.backend == usertypes.Backend.QtWebKit: # pragma: no cover
from qutebrowser.browser.webkit import webkithistory
webkithistory.init(history)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -24,7 +24,8 @@ import binascii
from PyQt5.QtWidgets import QWidget
from qutebrowser.utils import log, objreg, usertypes
from qutebrowser.config import configfiles
from qutebrowser.utils import log, usertypes
from qutebrowser.misc import miscwidgets, objects
@@ -67,9 +68,8 @@ class AbstractWebInspector(QWidget):
def _load_state_geometry(self):
"""Load the geometry from the state file."""
state_config = objreg.get('state-config')
try:
data = state_config['geometry']['inspector']
data = configfiles.state['geometry']['inspector']
geom = base64.b64decode(data, validate=True)
except KeyError:
# First start
@@ -84,10 +84,9 @@ class AbstractWebInspector(QWidget):
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
configfiles.state['geometry']['inspector'] = geom
super().closeEvent(e)
def inspect(self, page):

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -85,7 +85,7 @@ class MouseEventFilter(QObject):
def _handle_mouse_press(self, e):
"""Handle pressing of a mouse button."""
is_rocker_gesture = (config.get('input', 'rocker-gestures') and
is_rocker_gesture = (config.val.input.rocker_gestures and
e.buttons() == Qt.LeftButton | Qt.RightButton)
if e.button() in [Qt.XButton1, Qt.XButton2] or is_rocker_gesture:
@@ -119,7 +119,7 @@ class MouseEventFilter(QObject):
return True
if e.modifiers() & Qt.ControlModifier:
divider = config.get('input', 'mouse-zoom-divider')
divider = config.val.zoom.mouse_divider
if divider == 0:
return False
factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider)
@@ -139,7 +139,7 @@ class MouseEventFilter(QObject):
def _handle_context_menu(self, _e):
"""Suppress context menus if rocker gestures are turned on."""
return config.get('input', 'rocker-gestures')
return config.val.input.rocker_gestures
def _mousepress_insertmode_cb(self, elem):
"""Check if the clicked element is editable."""
@@ -157,7 +157,7 @@ class MouseEventFilter(QObject):
'click', only_if_normal=True)
else:
log.mouse.debug("Clicked non-editable element!")
if config.get('input', 'auto-leave-insert-mode'):
if config.val.input.insert_mode.auto_leave:
modeman.leave(self._tab.win_id, usertypes.KeyMode.insert,
'click', maybe=True)
@@ -179,7 +179,7 @@ class MouseEventFilter(QObject):
'click-delayed', only_if_normal=True)
else:
log.mouse.debug("Clicked non-editable element (delayed)!")
if config.get('input', 'auto-leave-insert-mode'):
if config.val.input.insert_mode.auto_leave:
modeman.leave(self._tab.win_id, usertypes.KeyMode.insert,
'click-delayed', maybe=True)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -24,6 +24,7 @@ import posixpath
from qutebrowser.browser import webelem
from qutebrowser.config import config
from qutebrowser.utils import objreg, urlutils, log, message, qtutils
from qutebrowser.mainwindow import mainwindow
class Error(Exception):
@@ -42,7 +43,7 @@ def incdec(url, count, inc_or_dec):
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'))
segments = set(config.val.url.incdec_segments)
try:
new_url = urlutils.incdec_number(url, inc_or_dec, count,
segments=segments)
@@ -79,12 +80,14 @@ def _find_prevnext(prev, elems):
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'
elems = [e for e in elems if e.tag_name() != 'link']
option = 'prev_regexes' if prev else 'next_regexes'
if not elems:
return None
for regex in config.get('hints', option):
# pylint: disable=bad-config-option
for regex in getattr(config.val.hints, option):
# pylint: enable=bad-config-option
log.hints.vdebug("== Checking regex '{}'.".format(regex.pattern))
for e in elems:
text = str(e)
@@ -128,20 +131,20 @@ def prevnext(*, browsertab, win_id, baseurl, prev=False,
return
qtutils.ensure_valid(url)
cur_tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
if window:
from qutebrowser.mainwindow import mainwindow
new_window = mainwindow.MainWindow()
new_window = mainwindow.MainWindow(
private=cur_tabbed_browser.private)
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)
cur_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)
browsertab.elements.find_css(webelem.SELECTORS[webelem.Group.links],
_prevnext_cb)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,7 +22,7 @@
import sys
import functools
from PyQt5.QtCore import (QObject, pyqtSignal, pyqtSlot)
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, QUrl
from PyQt5.QtNetwork import (QNetworkProxy, QNetworkRequest, QHostInfo,
QNetworkReply, QNetworkAccessManager,
QHostAddress)
@@ -155,7 +155,7 @@ class PACResolver:
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":
elif config[0] in ["SOCKS", "SOCKS5"]:
if len(config) != 2:
raise ParseProxyError("Invalid number of parameters for SOCKS")
host, port = PACResolver._parse_proxy_host(config[1])
@@ -199,16 +199,24 @@ class PACResolver:
err = "Cannot resolve FindProxyForURL function, got '{}' instead"
raise EvalProxyError(err.format(self._resolver.toString()))
def resolve(self, query):
def resolve(self, query, from_file=False):
"""Resolve a proxy via PAC.
Args:
query: QNetworkProxyQuery.
from_file: Whether the proxy info is coming from a file.
Return:
A list of QNetworkProxy objects in order of preference.
"""
result = self._resolver.call([query.url().toString(),
if from_file:
string_flags = QUrl.PrettyDecoded
else:
string_flags = QUrl.RemoveUserInfo
if query.url().scheme() == 'https':
string_flags |= QUrl.RemovePath | QUrl.RemoveQuery
result = self._resolver.call([query.url().toString(string_flags),
query.peerHostName()])
result_str = result.toString()
if not result.isString():
@@ -236,12 +244,24 @@ class PACFetcher(QObject):
assert url.scheme().startswith(pac_prefix)
url.setScheme(url.scheme()[len(pac_prefix):])
self._pac_url = url
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
self._reply = None
def __eq__(self, other):
# pylint: disable=protected-access
return self._pac_url == other._pac_url
def __repr__(self):
return utils.get_repr(self, url=self._pac_url, constructor=True)
def fetch(self):
"""Fetch the proxy from the remote URL."""
self._reply = self._manager.get(QNetworkRequest(self._pac_url))
self._reply.finished.connect(self._finish)
@pyqtSlot()
def _finish(self):
@@ -292,8 +312,9 @@ class PACFetcher(QObject):
Return a list of QNetworkProxy objects in order of preference.
"""
self._wait()
from_file = self._pac_url.scheme() == 'file'
try:
return self._pac.resolve(query)
return self._pac.resolve(query, from_file=from_file)
except (EvalProxyError, ParseProxyError) as e:
log.network.exception("Error in PAC resolution: {}.".format(e))
# .invalid is guaranteed to be inaccessible in RFC 6761.
@@ -302,4 +323,4 @@ class PACFetcher(QObject):
# 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)
return [QNetworkProxy(QNetworkProxy.HttpProxy, error_host, 9)]

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -44,7 +44,7 @@ class ProxyFactory(QNetworkProxyFactory):
Return:
None if proxy is correct, otherwise an error message.
"""
proxy = config.get('network', 'proxy')
proxy = config.val.content.proxy
if isinstance(proxy, pac.PACFetcher):
return proxy.fetch_error()
else:
@@ -59,7 +59,7 @@ class ProxyFactory(QNetworkProxyFactory):
Return:
A list of QNetworkProxy objects in order of preference.
"""
proxy = config.get('network', 'proxy')
proxy = config.val.content.proxy
if proxy is configtypes.SYSTEM_PROXY:
proxies = QNetworkProxyFactory.systemProxyForQuery(query)
elif isinstance(proxy, pac.PACFetcher):
@@ -69,7 +69,7 @@ class ProxyFactory(QNetworkProxyFactory):
for p in proxies:
if p.type() != QNetworkProxy.NoProxy:
capabilities = p.capabilities()
if config.get('network', 'proxy-dns-requests'):
if config.val.content.proxy_dns_requests:
capabilities |= QNetworkProxy.HostNameLookupCapability
else:
capabilities &= ~QNetworkProxy.HostNameLookupCapability

View File

@@ -1,6 +1,7 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Daniel Schadt
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,18 +22,23 @@
import io
import shutil
import functools
import collections
import attr
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QTimer
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
from qutebrowser.config import config
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'])
@attr.s
class _RetryInfo:
request = attr.ib()
manager = attr.ib()
class DownloadItem(downloads.AbstractDownloadItem):
@@ -110,6 +115,9 @@ class DownloadItem(downloads.AbstractDownloadItem):
def _do_die(self):
"""Abort the download and emit an error."""
self._read_timer.stop()
if self._reply is None:
log.downloads.debug("Reply gone while dying")
return
self._reply.downloadProgress.disconnect()
self._reply.finished.disconnect()
self._reply.error.disconnect()
@@ -270,7 +278,7 @@ class DownloadItem(downloads.AbstractDownloadItem):
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).
# qute://log for example).
return
if not self._reply.isOpen():
raise OSError("Reply is closed!")
@@ -363,7 +371,8 @@ class DownloadManager(downloads.AbstractDownloadManager):
def __init__(self, win_id, parent=None):
super().__init__(parent)
self._networkmanager = networkmanager.NetworkManager(
win_id, None, self)
win_id=win_id, tab_id=None,
private=config.val.content.private_browsing, parent=self)
@pyqtSlot('QUrl')
def get(self, url, *, user_agent=None, **kwargs):
@@ -407,7 +416,8 @@ class DownloadManager(downloads.AbstractDownloadManager):
mhtml.start_download_checked, tab=tab))
message.global_bridge.ask(question, blocking=False)
def get_request(self, request, *, target=None, **kwargs):
def get_request(self, request, *, target=None,
suggested_fn=None, **kwargs):
"""Start a download with a QNetworkRequest.
Args:
@@ -423,7 +433,9 @@ class DownloadManager(downloads.AbstractDownloadManager):
request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
QNetworkRequest.AlwaysNetwork)
if request.url().scheme().lower() != 'data':
if suggested_fn is not None:
pass
elif 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
@@ -475,7 +487,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
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.
downloads.remove_finished is set to -1.
Return:
The created DownloadItem.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -17,21 +17,24 @@
# 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.
"""Backend-independent qute://* code.
Module attributes:
pyeval_output: The output of the last :pyeval command.
_HANDLERS: The handlers registered via decorators.
"""
import sys
import json
import os
import time
import datetime
import urllib.parse
import textwrap
import pkg_resources
from PyQt5.QtCore import QUrlQuery
from PyQt5.QtCore import QUrlQuery, QUrl
import qutebrowser
from qutebrowser.config import config, configdata, configexc, configdiff
from qutebrowser.utils import (version, utils, jinja, log, message, docutils,
objreg)
from qutebrowser.misc import objects
@@ -75,12 +78,25 @@ class QuteSchemeError(Exception):
super().__init__(errorstring)
class add_handler: # pylint: disable=invalid-name
class Redirect(Exception):
"""Decorator to register a qute:* URL handler.
"""Exception to signal a redirect should happen.
Attributes:
_name: The 'foo' part of qute:foo
url: The URL to redirect to, as a QUrl.
"""
def __init__(self, url):
super().__init__(url.toDisplayString())
self.url = url
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.
"""
@@ -103,11 +119,10 @@ class add_handler: # pylint: disable=invalid-name
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",
title="Error while opening qute://url",
url=url.toDisplayString(),
error='{} is not available with this '
'backend'.format(url.toDisplayString()),
icon='')
'backend'.format(url.toDisplayString()))
return 'text/html', html
@@ -125,13 +140,19 @@ def data_for_url(url):
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
log.misc.debug("url: {}, path: {}, host {}".format(
url.toDisplayString(), path, host))
if path and not host:
new_url = QUrl()
new_url.setScheme('qute')
new_url.setHost(path)
new_url.setPath('/')
if new_url.host(): # path was a valid host
raise Redirect(new_url)
try:
handler = _HANDLERS[path]
handler = _HANDLERS[host]
except KeyError:
try:
handler = _HANDLERS[host]
except KeyError:
raise NoHandlerFound(url)
raise NoHandlerFound(url)
try:
mimetype, data = handler(url)
except OSError as e:
@@ -150,7 +171,7 @@ def data_for_url(url):
@add_handler('bookmarks')
def qute_bookmarks(_url):
"""Handler for qute:bookmarks. Display all quickmarks / bookmarks."""
"""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(),
@@ -163,90 +184,71 @@ def qute_bookmarks(_url):
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)
def history_data(start_time, offset=None):
"""Return history data.
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))
Arguments:
start_time: select history starting from this timestamp.
offset: number of items to skip
"""
# history atimes are stored as ints, ensure start_time is not a float
start_time = int(start_time)
hist = objreg.get('web-history')
if offset is not None:
entries = hist.entries_before(start_time, limit=1000, offset=offset)
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)))
# end is 24hrs earlier than start
end_time = start_time - 24*60*60
entries = hist.entries_between(end_time, start_time)
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
return [{"url": e.url, "title": e.title or e.url, "time": e.atime}
for e in entries]
@add_handler('history')
def qute_history(url):
"""Handler for qute://history. Display and serve history."""
if url.path() == '/data':
try:
offset = QUrlQuery(url).queryItemValue("offset")
offset = int(offset) if offset else None
except ValueError as e:
raise QuteSchemeError("Query parameter offset is invalid", e)
# Use start_time in query or current time.
try:
start_time = QUrlQuery(url).queryItemValue("start_time")
start_time = float(start_time) if start_time else time.time()
except ValueError as e:
raise QuteSchemeError("Query parameter start_time is invalid", e)
return 'text/html', json.dumps(history_data(start_time, offset))
else:
if not config.val.content.javascript.enabled:
return 'text/plain', b'JavaScript is required for qute://history'
return 'text/html', jinja.render(
'history.html',
title='History',
gap_interval=config.val.history_gap_interval
)
@add_handler('javascript')
def qute_javascript(url):
"""Handler for qute://javascript.
Return content of file given as query parameter.
"""
path = url.path()
if path:
path = "javascript" + os.sep.join(path.split('/'))
return 'text/html', utils.read_file(path, binary=False)
else:
raise QuteSchemeError("No file specified", ValueError())
@add_handler('pyeval')
def qute_pyeval(_url):
"""Handler for qute:pyeval."""
"""Handler for qute://pyeval."""
html = jinja.render('pre.html', title='pyeval', content=pyeval_output)
return 'text/html', html
@@ -254,7 +256,7 @@ def qute_pyeval(_url):
@add_handler('version')
@add_handler('verizon')
def qute_version(_url):
"""Handler for qute:version."""
"""Handler for qute://version."""
html = jinja.render('version.html', title='Version info',
version=version.version(),
copyright=qutebrowser.__copyright__)
@@ -263,7 +265,7 @@ def qute_version(_url):
@add_handler('plainlog')
def qute_plainlog(url):
"""Handler for qute:plainlog.
"""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.
@@ -283,7 +285,7 @@ def qute_plainlog(url):
@add_handler('log')
def qute_log(url):
"""Handler for qute:log.
"""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.
@@ -304,27 +306,13 @@ def qute_log(url):
@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')
"""Handler for qute://gpl. Return HTML content as string."""
return 'text/html', utils.read_file('html/LICENSE.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
"""Handler for qute://help."""
urlpath = url.path()
if not urlpath or urlpath == '/':
urlpath = 'index.html'
@@ -333,9 +321,102 @@ def qute_help(url):
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:
try:
data = utils.read_file(path)
except OSError:
# No .html around, let's see if we find the asciidoc
asciidoc_path = path.replace('.html', '.asciidoc')
if asciidoc_path.startswith('html/doc/'):
asciidoc_path = asciidoc_path.replace('html/doc/', '../doc/help/')
try:
asciidoc = utils.read_file(asciidoc_path)
except OSError:
asciidoc = None
if asciidoc is None:
raise
preamble = textwrap.dedent("""
There was an error loading the documentation!
This most likely means the documentation was not generated
properly. If you are running qutebrowser from the git repository,
please (re)run scripts/asciidoc2html.py and reload this page.
If you're running a released version this is a bug, please use
:report to report it.
Falling back to the plaintext version.
---------------------------------------------------------------
""")
return 'text/plain', (preamble + asciidoc).encode('utf-8')
else:
return 'text/html', data
@add_handler('backend-warning')
def qute_backend_warning(_url):
"""Handler for qute://backend-warning."""
html = jinja.render('backend-warning.html',
distribution=version.distribution(),
Distribution=version.Distribution,
version=pkg_resources.parse_version,
title="Legacy backend warning")
return 'text/html', html
def _qute_settings_set(url):
"""Handler for qute://settings/set."""
query = QUrlQuery(url)
option = query.queryItemValue('option', QUrl.FullyDecoded)
value = query.queryItemValue('value', QUrl.FullyDecoded)
# https://github.com/qutebrowser/qutebrowser/issues/727
if option == 'content.javascript.enabled' and value == 'false':
msg = ("Refusing to disable javascript via qute://settings "
"as it needs javascript support.")
message.error(msg)
return 'text/html', b'error: ' + msg.encode('utf-8')
try:
config.instance.set_str(option, value, save_yaml=True)
return 'text/html', b'ok'
except configexc.Error as e:
message.error(str(e))
return 'text/html', b'error: ' + str(e).encode('utf-8')
@add_handler('settings')
def qute_settings(url):
"""Handler for qute://settings. View/change qute configuration."""
if url.path() == '/set':
return _qute_settings_set(url)
html = jinja.render('settings.html', title='settings',
configdata=configdata,
confget=config.instance.get_str)
return 'text/html', html
@add_handler('configdiff')
def qute_configdiff(url):
"""Handler for qute://configdiff."""
if url.path() == '/old':
try:
return 'text/html', configdiff.get_diff()
except OSError as e:
error = (b'Failed to read old config: ' +
str(e.strerror).encode('utf-8'))
return 'text/plain', error
else:
data = config.instance.dump_userconfig().encode('utf-8')
return 'text/plain', data

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -21,10 +21,9 @@
import html
import jinja2
from qutebrowser.config import config
from qutebrowser.utils import usertypes, message, log, objreg
from qutebrowser.utils import usertypes, message, log, objreg, jinja
from qutebrowser.mainwindow import mainwindow
class CallSuper(Exception):
@@ -35,16 +34,18 @@ class CallSuper(Exception):
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')
dnt_config = config.val.content.headers.do_not_track
if dnt_config is not None:
dnt = b'1' if dnt_config else b'0'
headers[b'DNT'] = dnt
headers[b'X-Do-Not-Track'] = dnt
accept_language = config.get('network', 'accept-language')
conf_headers = config.val.content.headers.custom
for header, value in conf_headers.items():
headers[header.encode('ascii')] = value.encode('ascii')
accept_language = config.val.content.headers.accept_language
if accept_language is not None:
headers[b'Accept-Language'] = accept_language.encode('ascii')
@@ -72,7 +73,7 @@ def authentication_required(url, authenticator, abort_on):
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'):
if config.val.content.javascript.modal_dialog:
raise CallSuper
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
@@ -86,9 +87,9 @@ def javascript_confirm(url, js_msg, abort_on):
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'):
if config.val.content.javascript.modal_dialog:
raise CallSuper
if config.get('content', 'ignore-javascript-prompt'):
if not config.val.content.javascript.prompt:
return (False, "")
msg = '<b>{}</b> asks:<br/>{}'.format(html.escape(url.toDisplayString()),
@@ -107,10 +108,10 @@ def javascript_prompt(url, js_msg, default, abort_on):
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'):
if config.val.content.javascript.modal_dialog:
raise CallSuper
if config.get('content', 'ignore-javascript-alert'):
if not config.val.content.javascript.alert:
return
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
@@ -119,6 +120,22 @@ def javascript_alert(url, js_msg, abort_on):
abort_on=abort_on)
def javascript_log_message(level, source, line, msg):
"""Display a JavaScript log message."""
logstring = "[{}:{}] {}".format(source, line, msg)
# Needs to line up with the values allowed for the
# content.javascript.log setting.
logmap = {
'none': lambda arg: None,
'debug': log.js.debug,
'info': log.js.info,
'warning': log.js.warning,
'error': log.js.error,
}
logger = logmap[config.val.content.javascript.log[level.name]]
logger(logstring)
def ignore_certificate_errors(url, errors, abort_on):
"""Display a certificate error question.
@@ -129,7 +146,7 @@ def ignore_certificate_errors(url, errors, abort_on):
Return:
True if the error should be ignored, False otherwise.
"""
ssl_strict = config.get('network', 'ssl-strict')
ssl_strict = config.val.content.ssl_strict
log.webview.debug("Certificate errors {!r}, strict {}".format(
errors, ssl_strict))
@@ -137,7 +154,7 @@ def ignore_certificate_errors(url, errors, abort_on):
assert error.is_overridable(), repr(error)
if ssl_strict == 'ask':
err_template = jinja2.Template("""
err_template = jinja.environment.from_string("""
Errors while loading <b>{{url.toDisplayString()}}</b>:<br/>
<ul>
{% for err in errors %}
@@ -155,7 +172,7 @@ def ignore_certificate_errors(url, errors, abort_on):
ignore = False
return ignore
elif ssl_strict is False:
log.webview.debug("ssl-strict is False, only warning about errors")
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
@@ -173,7 +190,7 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on):
Args:
url: The URL the request was done for.
option: A (section, option) tuple for the option to check.
option: An option name 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
@@ -182,7 +199,7 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on):
Return:
The Question object if a question was asked, None otherwise.
"""
config_val = config.get(*option)
config_val = config.instance.get(option)
if config_val == 'ask':
if url.isValid():
text = "Allow the website at <b>{}</b> to {}?".format(
@@ -216,8 +233,9 @@ def get_tab(win_id, target):
win_id = win_id
bg_tab = True
elif target == usertypes.ClickTarget.window:
from qutebrowser.mainwindow import mainwindow
window = mainwindow.MainWindow()
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
window = mainwindow.MainWindow(private=tabbed_browser.private)
window.show()
win_id = window.win_id
bg_tab = False
@@ -231,15 +249,14 @@ def get_tab(win_id, target):
def get_user_stylesheet():
"""Get the combined user-stylesheet."""
filename = config.get('ui', 'user-stylesheet')
css = ''
stylesheets = config.val.content.user_stylesheets
if filename is None:
css = ''
else:
for filename in stylesheets:
with open(filename, 'r', encoding='utf-8') as f:
css = f.read()
css += f.read()
if config.get('ui', 'hide-scrollbar'):
if not config.val.scrolling.bar:
css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }'
return css

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,7 +1,7 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Antoni Boucher <bouanto@zoho.com>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2017 Antoni Boucher <bouanto@zoho.com>
#
# This file is part of qutebrowser.
#
@@ -77,13 +77,9 @@ class UrlMarkManager(QObject):
Signals:
changed: Emitted when anything changed.
added: Emitted when a new quickmark/bookmark was added.
removed: Emitted when an existing quickmark/bookmark was removed.
"""
changed = pyqtSignal()
added = pyqtSignal(str, str)
removed = pyqtSignal(str)
def __init__(self, parent=None):
"""Initialize and read quickmarks."""
@@ -121,7 +117,6 @@ class UrlMarkManager(QObject):
"""
del self.marks[key]
self.changed.emit()
self.removed.emit(key)
class QuickmarkManager(UrlMarkManager):
@@ -133,7 +128,6 @@ class QuickmarkManager(UrlMarkManager):
- self.marks maps names to URLs.
- changed gets emitted with the name as first argument and the URL as
second argument.
- removed gets emitted with the name as argument.
"""
def _init_lineparser(self):
@@ -193,7 +187,6 @@ class QuickmarkManager(UrlMarkManager):
"""Really set the quickmark."""
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:
@@ -243,7 +236,6 @@ class BookmarkManager(UrlMarkManager):
- self.marks maps URLs to titles.
- changed gets emitted with the URL as first argument and the title as
second argument.
- removed gets emitted with the URL as argument.
"""
def _init_lineparser(self):
@@ -295,5 +287,4 @@ class BookmarkManager(UrlMarkManager):
else:
self.marks[urlstr] = title
self.changed.emit()
self.added.emit(title, urlstr)
return True

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,9 +22,6 @@
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
@@ -34,21 +31,20 @@ from PyQt5.QtGui import QMouseEvent
from qutebrowser.config import config
from qutebrowser.keyinput import modeman
from qutebrowser.mainwindow import mainwindow
from qutebrowser.utils import log, usertypes, utils, qtutils, objreg
Group = usertypes.enum('Group', ['all', 'links', 'images', 'url', 'prevnext',
'inputs'])
Group = usertypes.enum('Group', ['all', 'links', 'images', 'url', '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.links: 'a[href], area[href], link[href], [role=link][href]',
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], '
@@ -56,16 +52,6 @@ SELECTORS = {
}
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."""
@@ -120,10 +106,6 @@ class AbstractWebElement(collections.abc.MutableMapping):
"""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
@@ -201,7 +183,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
# 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')
return config.val.input.insert_mode.plugins
else:
# Image/Audio/...
return False
@@ -266,7 +248,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
return self.is_writable()
elif tag in ['embed', 'applet']:
# Flash/Java/...
return config.get('input', 'insert-mode-on-plugins') and not strict
return config.val.input.insert_mode.plugins and not strict
elif tag == 'object':
return self._is_editable_object() and not strict
elif tag in ['div', 'pre']:
@@ -310,6 +292,11 @@ class AbstractWebElement(collections.abc.MutableMapping):
qtutils.ensure_valid(url)
return url
def is_link(self):
"""Return True if this AbstractWebElement is a link."""
href_tags = ['a', 'area', 'link']
return self.tag_name() in href_tags and 'href' in self
def _mouse_pos(self):
"""Get the position to click/hover."""
# Click the center of the largest square fitting into the top/left
@@ -326,6 +313,10 @@ class AbstractWebElement(collections.abc.MutableMapping):
raise Error("Element position is out of view!")
return pos
def _move_text_cursor(self):
"""Move cursor to end after clicking."""
raise NotImplementedError
def _click_fake_event(self, click_target):
"""Send a fake click event to the element."""
pos = self._mouse_pos()
@@ -339,7 +330,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
usertypes.ClickTarget.tab: Qt.ControlModifier,
usertypes.ClickTarget.tab_bg: Qt.ControlModifier,
}
if config.get('tabs', 'background-tabs'):
if config.val.tabs.background:
modifiers[usertypes.ClickTarget.tab] |= Qt.ShiftModifier
else:
modifiers[usertypes.ClickTarget.tab_bg] |= Qt.ShiftModifier
@@ -356,11 +347,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
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)
QTimer.singleShot(0, self._move_text_cursor)
def _click_editable(self, click_target):
"""Fake a click on an editable input field."""
@@ -378,15 +365,15 @@ class AbstractWebElement(collections.abc.MutableMapping):
self._click_fake_event(click_target)
return
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._tab.win_id)
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 = mainwindow.MainWindow(private=tabbed_browser.private)
window.show()
window.tabbed_browser.tabopen(url)
else:
@@ -407,9 +394,8 @@ class AbstractWebElement(collections.abc.MutableMapping):
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:
if self.is_link():
log.webelem.debug("Clicking via JS click()")
self._click_js(click_target)
elif self.is_editable(strict=True):
@@ -422,7 +408,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
elif click_target in [usertypes.ClickTarget.tab,
usertypes.ClickTarget.tab_bg,
usertypes.ClickTarget.window]:
if self.tag_name() in href_tags:
if self.is_link():
self._click_href(click_target)
else:
self._click_fake_event(click_target)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -19,9 +19,7 @@
"""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

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -19,9 +19,7 @@
"""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
@@ -57,8 +55,7 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor):
info: QWebEngineUrlRequestInfo &info
"""
# FIXME:qtwebengine only block ads for NavigationTypeOther?
if (bytes(info.requestMethod()) == b'GET' and
self._host_blocker.is_blocked(info.requestUrl())):
if self._host_blocker.is_blocked(info.requestUrl()):
log.webview.info("Request to {} blocked by host blocker.".format(
info.requestUrl().host()))
info.block(True)
@@ -66,6 +63,6 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor):
for header, value in shared.custom_headers():
info.setHttpHeader(header, value)
user_agent = config.get('network', 'user-agent')
user_agent = config.val.content.headers.user_agent
if user_agent is not None:
info.setHttpHeader(b'User-Agent', user_agent.encode('ascii'))

View File

@@ -0,0 +1,46 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2017 Michal Siedlaczek <michal.siedlaczek@gmail.com>
# 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/>.
"""Installing and configuring spell-checking for QtWebEngine."""
import glob
import os
from PyQt5.QtCore import QLibraryInfo
def dictionary_dir():
"""Return the path (str) to the QtWebEngine's dictionaries directory."""
datapath = QLibraryInfo.location(QLibraryInfo.DataPath)
return os.path.join(datapath, 'qtwebengine_dictionaries')
def installed_file(code):
"""Return the installed dictionary for the given code.
Return the filename of the installed dictionary or None
if the dictionary is not installed.
"""
pathname = os.path.join(dictionary_dir(), '{}*.bdic'.format(code))
matching_dicts = glob.glob(pathname)
if matching_dicts:
with_extension = os.path.basename(matching_dicts[0])
return os.path.splitext(with_extension)[0]
else:
return None

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -25,9 +25,7 @@ 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
@@ -78,32 +76,39 @@ class DownloadItem(downloads.AbstractDownloadItem):
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()
try:
reason = self._qt_item.interruptReasonString()
except AttributeError:
# Qt < 5.9
reason = "Download failed"
self._die(reason)
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()
if self._qt_item.state() != QWebEngineDownloadItem.DownloadInterrupted:
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
raise downloads.UnsupportedOperationError(
"Retrying downloads is unsupported with QtWebEngine")
def _get_open_filename(self):
return self._filename
def _set_fileobj(self, fileobj):
def _set_fileobj(self, fileobj, *,
autoclose=True): # pylint: disable=unused-argument
raise downloads.UnsupportedOperationError
def _set_tempfile(self, fileobj):
fileobj.close()
self._set_filename(fileobj.name, force_overwrite=True,
remember_directory=False)
@@ -144,8 +149,8 @@ def _get_suggested_filename(path):
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'):
filename = re.sub(r'\([0-9]+\)(?=\.|$)', '', filename)
if not qtutils.version_check('5.9', compiled=False):
# https://bugreports.qt.io/browse/QTBUG-58155
filename = urllib.parse.unquote(filename)
# Doing basename a *second* time because there could be a %2F in

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -18,16 +18,14 @@
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
# FIXME:qtwebengine remove this once the stubs are gone
# pylint: disable=unused-variable
# pylint: disable=unused-argument
"""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
@@ -39,6 +37,38 @@ class WebEngineElement(webelem.AbstractWebElement):
def __init__(self, js_dict, tab):
super().__init__(tab)
# Do some sanity checks on the data we get from JS
js_dict_types = {
'id': int,
'text': str,
'value': (str, int, float),
'tag_name': str,
'outer_xml': str,
'class_name': str,
'rects': list,
'attributes': dict,
}
assert set(js_dict.keys()).issubset(js_dict_types.keys())
for name, typ in js_dict_types.items():
if name in js_dict and not isinstance(js_dict[name], typ):
raise TypeError("Got {} for {} from JS but expected {}: "
"{}".format(type(js_dict[name]), name, typ,
js_dict))
for name, value in js_dict['attributes'].items():
if not isinstance(name, str):
raise TypeError("Got {} ({}) for attribute name from JS: "
"{}".format(name, type(name), js_dict))
if not isinstance(value, str):
raise TypeError("Got {} ({}) for attribute {} from JS: "
"{}".format(value, type(value), name, js_dict))
for rect in js_dict['rects']:
assert set(rect.keys()) == {'top', 'right', 'bottom', 'left',
'height', 'width'}, rect.keys()
for value in rect.values():
if not isinstance(value, (int, float)):
raise TypeError("Got {} ({}) for rect from JS: "
"{}".format(value, type(value), js_dict))
self._id = js_dict['id']
self._js_dict = js_dict
@@ -56,9 +86,7 @@ class WebEngineElement(webelem.AbstractWebElement):
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)
self._js_call('set_attribute', key, val)
def __delitem__(self, key):
log.stub()
@@ -69,6 +97,11 @@ class WebEngineElement(webelem.AbstractWebElement):
def __len__(self):
return len(self._js_dict['attributes'])
def _js_call(self, name, *args, callback=None):
"""Wrapper to run stuff from webelem.js."""
js_code = javascript.assemble('webelem', name, self._id, *args)
self._tab.run_js_async(js_code, callback=callback)
def has_frame(self):
return True
@@ -76,10 +109,6 @@ class WebEngineElement(webelem.AbstractWebElement):
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()
@@ -89,7 +118,9 @@ class WebEngineElement(webelem.AbstractWebElement):
The returned name will always be lower-case.
"""
return self._js_dict['tag_name'].lower()
tag = self._js_dict['tag_name']
assert isinstance(tag, str), tag
return tag.lower()
def outer_xml(self):
"""Get the full HTML representation of this element."""
@@ -99,15 +130,13 @@ class WebEngineElement(webelem.AbstractWebElement):
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)
self._js_call('set_value', value)
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)
self._js_call('insert_text', text)
def rect_on_view(self, *, elem_geometry=None, no_js=False):
"""Get the geometry of the element relative to the webview.
@@ -133,7 +162,7 @@ class WebEngineElement(webelem.AbstractWebElement):
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
# 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,
@@ -153,27 +182,27 @@ class WebEngineElement(webelem.AbstractWebElement):
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)
self._js_call('remove_blank_target')
def _move_text_cursor(self):
if self.is_text_input() and self.is_editable():
self._js_call('move_cursor_to_end')
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)
self._js_call('focus')
self._move_text_cursor()
def _click_js(self, _click_target):
settings = QWebEngineSettings.globalSettings()
# FIXME:qtwebengine Have a proper API for this
# pylint: disable=protected-access
settings = self._tab._widget.settings()
# pylint: enable=protected-access
attribute = QWebEngineSettings.JavascriptCanOpenWindows
could_open_windows = settings.testAttribute(attribute)
settings.setAttribute(attribute, True)
@@ -189,5 +218,4 @@ class WebEngineElement(webelem.AbstractWebElement):
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)
self._js_call('click', callback=reset_setting)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -22,9 +22,7 @@
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

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -17,24 +17,22 @@
# 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."""
"""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
from qutebrowser.utils import log, qtutils
class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
"""Handle qute:* requests on QtWebEngine."""
"""Handle qute://* requests on QtWebEngine."""
def install(self, profile):
"""Install the handler for qute: URLs on the given profile."""
"""Install the handler for qute:// URLs on the given profile."""
profile.installUrlSchemeHandler(b'qute', self)
def requestStarted(self, job):
@@ -58,12 +56,15 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
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")
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")
log.misc.exception("Error while handling qute://* URL")
job.fail(QWebEngineUrlRequestJob.RequestFailed)
except qutescheme.Redirect as e:
qtutils.ensure_valid(e.url)
job.redirect(e.url)
else:
log.misc.debug("Returning {} data".format(mimetype))

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -17,6 +17,9 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
# We get various "abstract but not overridden" warnings
# pylint: disable=abstract-method
"""Bridge from QWebEngineSettings to our own settings.
Module attributes:
@@ -26,79 +29,95 @@ Module attributes:
import os
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtGui import QFont
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
QWebEngineScript)
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import spell
from qutebrowser.config import config, websettings
from qutebrowser.utils import objreg, utils, standarddir, javascript
from qutebrowser.utils import utils, standarddir, javascript, qtutils, message
# The default QWebEngineProfile
default_profile = None
# The QWebEngineProfile used for private (off-the-record) windows
private_profile = None
class Attribute(websettings.Attribute):
class Base(websettings.Base):
"""Base settings class with appropriate _get_global_settings."""
def _get_global_settings(self):
return [default_profile.settings(), private_profile.settings()]
class Attribute(Base, websettings.Attribute):
"""A setting set via QWebEngineSettings::setAttribute."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
ENUM_BASE = QWebEngineSettings
class Setter(websettings.Setter):
class Setter(Base, websettings.Setter):
"""A setting set via QWebEngineSettings getter/setter methods."""
"""A setting set via a QWebEngineSettings setter method."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
pass
class NullStringSetter(websettings.NullStringSetter):
class FontFamilySetter(Base, websettings.FontFamilySetter):
"""A setter for settings requiring a null QString as default."""
"""A setter for a font family.
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
Gets the default value from QFont.
"""
def __init__(self, font):
# Mapping from WebEngineSettings::initDefaults in
# qtwebengine/src/core/web_engine_settings.cpp
font_to_qfont = {
QWebEngineSettings.StandardFont: QFont.Serif,
QWebEngineSettings.FixedFont: QFont.Monospace,
QWebEngineSettings.SerifFont: QFont.Serif,
QWebEngineSettings.SansSerifFont: QFont.SansSerif,
QWebEngineSettings.CursiveFont: QFont.Cursive,
QWebEngineSettings.FantasyFont: QFont.Fantasy,
}
super().__init__(setter=QWebEngineSettings.setFontFamily, font=font,
qfont=font_to_qfont[font])
class StaticSetter(websettings.StaticSetter):
"""A setting set via static QWebEngineSettings getter/setter methods."""
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
class ProfileSetter(websettings.Base):
class DefaultProfileSetter(websettings.Base):
"""A setting set on the QWebEngineProfile."""
def __init__(self, getter, setter):
super().__init__()
self._getter = getter
def __init__(self, setter, default=websettings.UNSET):
super().__init__(default)
self._setter = setter
def get(self, settings=None):
utils.unused(settings)
getter = getattr(QWebEngineProfile.defaultProfile(), self._getter)
return getter()
def __repr__(self):
return utils.get_repr(self, setter=self._setter, constructor=True)
def _set(self, value, settings=None):
utils.unused(settings)
setter = getattr(QWebEngineProfile.defaultProfile(), self._setter)
if settings is not None:
raise ValueError("'settings' may not be set with "
"DefaultProfileSetters!")
setter = getattr(default_profile, self._setter)
setter(value)
class PersistentCookiePolicy(ProfileSetter):
class PersistentCookiePolicy(DefaultProfileSetter):
"""The cookies -> store setting is different from other settings."""
"""The content.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')
super().__init__('setPersistentCookiesPolicy')
def _set(self, value, settings=None):
utils.unused(settings)
if settings is not None:
raise ValueError("'settings' may not be set with "
"PersistentCookiePolicy!")
setter = getattr(QWebEngineProfile.defaultProfile(), self._setter)
setter(
QWebEngineProfile.AllowPersistentCookies if value else
@@ -106,15 +125,35 @@ class PersistentCookiePolicy(ProfileSetter):
)
class DictionaryLanguageSetter(DefaultProfileSetter):
"""Sets paths to dictionary files based on language codes."""
def __init__(self):
super().__init__('setSpellCheckLanguages', default=[])
def _find_installed(self, code):
installed_file = spell.installed_file(code)
if not installed_file:
message.warning(
"Language {} is not installed - see scripts/install_dict.py "
"in qutebrowser's sources".format(code))
return installed_file
def _set(self, value, settings=None):
if settings is not None:
raise ValueError("'settings' may not be set with "
"DictionaryLanguageSetter!")
filenames = [self._find_installed(code) for code in value]
super()._set([f for f in filenames if f], settings)
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():
@@ -139,19 +178,50 @@ def _init_stylesheet(profile):
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 _set_http_headers(profile):
"""Set the user agent and accept-language for the given profile.
We override those per request in the URL interceptor (to allow for
per-domain values), but this one still gets used for things like
window.navigator.userAgent/.languages in JS.
"""
profile.setHttpUserAgent(config.val.content.headers.user_agent)
accept_language = config.val.content.headers.accept_language
if accept_language is not None:
profile.setHttpAcceptLanguage(accept_language)
def update_settings(section, option):
def _update_settings(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)
websettings.update_mappings(MAPPINGS, option)
if option in ['scrolling.bar', 'content.user_stylesheets']:
_init_stylesheet(default_profile)
_init_stylesheet(private_profile)
elif option in ['content.headers.user_agent',
'content.headers.accept_language']:
_set_http_headers(default_profile)
_set_http_headers(private_profile)
def _init_profiles():
"""Init the two used QWebEngineProfiles."""
global default_profile, private_profile
default_profile = QWebEngineProfile.defaultProfile()
default_profile.setCachePath(
os.path.join(standarddir.cache(), 'webengine'))
default_profile.setPersistentStoragePath(
os.path.join(standarddir.data(), 'webengine'))
_init_stylesheet(default_profile)
_set_http_headers(default_profile)
private_profile = QWebEngineProfile()
assert private_profile.isOffTheRecord()
_init_stylesheet(private_profile)
_set_http_headers(private_profile)
if qtutils.version_check('5.8'):
default_profile.setSpellCheckEnabled(True)
private_profile.setSpellCheckEnabled(True)
def init(args):
@@ -159,17 +229,16 @@ def init(args):
if args.enable_webengine_inspector:
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
profile = QWebEngineProfile.defaultProfile()
_init_profile(profile)
_init_stylesheet(profile)
_init_profiles()
# We need to do this here as a WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58650
PersistentCookiePolicy().set(config.get('content', 'cookies-store'))
if not qtutils.version_check('5.9', compiled=False):
PersistentCookiePolicy().set(config.val.content.cookies.store)
Attribute(QWebEngineSettings.FullScreenSupportEnabled).set(True)
websettings.init_mappings(MAPPINGS)
objreg.get('config').changed.connect(update_settings)
config.instance.changed.connect(_update_settings)
def shutdown():
@@ -186,105 +255,84 @@ def shutdown():
# - 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),
}
'content.images':
Attribute(QWebEngineSettings.AutoLoadImages),
'content.javascript.enabled':
Attribute(QWebEngineSettings.JavascriptEnabled),
'content.javascript.can_open_tabs_automatically':
Attribute(QWebEngineSettings.JavascriptCanOpenWindows),
'content.javascript.can_access_clipboard':
Attribute(QWebEngineSettings.JavascriptCanAccessClipboard),
'content.plugins':
Attribute(QWebEngineSettings.PluginsEnabled),
'content.hyperlink_auditing':
Attribute(QWebEngineSettings.HyperlinkAuditingEnabled),
'content.local_content_can_access_remote_urls':
Attribute(QWebEngineSettings.LocalContentCanAccessRemoteUrls),
'content.local_content_can_access_file_urls':
Attribute(QWebEngineSettings.LocalContentCanAccessFileUrls),
'content.webgl':
Attribute(QWebEngineSettings.WebGLEnabled),
'content.local_storage':
Attribute(QWebEngineSettings.LocalStorageEnabled),
'content.cache.size':
# 0: automatically managed by QtWebEngine
DefaultProfileSetter('setHttpCacheMaximumSize', default=0),
'content.xss_auditing':
Attribute(QWebEngineSettings.XSSAuditingEnabled),
'content.default_encoding':
Setter(QWebEngineSettings.setDefaultTextEncoding),
'input.spatial_navigation':
Attribute(QWebEngineSettings.SpatialNavigationEnabled),
'input.links_included_in_focus_chain':
Attribute(QWebEngineSettings.LinksIncludedInFocusChain),
'fonts.web.family.standard':
FontFamilySetter(QWebEngineSettings.StandardFont),
'fonts.web.family.fixed':
FontFamilySetter(QWebEngineSettings.FixedFont),
'fonts.web.family.serif':
FontFamilySetter(QWebEngineSettings.SerifFont),
'fonts.web.family.sans_serif':
FontFamilySetter(QWebEngineSettings.SansSerifFont),
'fonts.web.family.cursive':
FontFamilySetter(QWebEngineSettings.CursiveFont),
'fonts.web.family.fantasy':
FontFamilySetter(QWebEngineSettings.FantasyFont),
'fonts.web.size.minimum':
Setter(QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.MinimumFontSize]),
'fonts.web.size.minimum_logical':
Setter(QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.MinimumLogicalFontSize]),
'fonts.web.size.default':
Setter(QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.DefaultFontSize]),
'fonts.web.size.default_fixed':
Setter(QWebEngineSettings.setFontSize,
args=[QWebEngineSettings.DefaultFixedFontSize]),
'scrolling.smooth':
Attribute(QWebEngineSettings.ScrollAnimatorEnabled),
}
try:
MAPPINGS['general']['print-element-backgrounds'] = Attribute(
MAPPINGS['content.print_element_backgrounds'] = Attribute(
QWebEngineSettings.PrintElementBackgrounds)
except AttributeError:
# Added in Qt 5.8
pass
if qtutils.version_check('5.8'):
MAPPINGS['spellcheck.languages'] = DictionaryLanguageSetter()
if qtutils.version_check('5.9', compiled=False):
# https://bugreports.qt.io/browse/QTBUG-58650
MAPPINGS['content.cookies.store'] = PersistentCookiePolicy()

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2016-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -17,30 +17,27 @@
# 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
"""Wrapper over a QWebEngineView."""
import math
import functools
import html as html_utils
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.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import (QWebEnginePage, QWebEngineScript,
QWebEngineProfile)
# pylint: enable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript
from qutebrowser.browser import browsertab, mouse, shared
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
interceptor, webenginequtescheme,
webenginedownloads)
webenginedownloads,
webenginesettings)
from qutebrowser.misc import miscwidgets
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
objreg, jinja)
message, objreg, jinja, debug)
_qute_scheme_handler = None
@@ -52,22 +49,24 @@ def init():
# 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...")
app = QApplication.instance()
log.init.debug("Initializing qute://* handler...")
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
_qute_scheme_handler.install(profile)
_qute_scheme_handler.install(webenginesettings.default_profile)
_qute_scheme_handler.install(webenginesettings.private_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)
req_interceptor.install(webenginesettings.default_profile)
req_interceptor.install(webenginesettings.private_profile)
log.init.debug("Initializing QtWebEngine downloads...")
download_manager = webenginedownloads.DownloadManager(parent=app)
download_manager.install(profile)
download_manager.install(webenginesettings.default_profile)
download_manager.install(webenginesettings.private_profile)
objreg.register('webengine-download-manager', download_manager)
@@ -82,17 +81,17 @@ _JS_WORLD_MAP = {
class WebEngineAction(browsertab.AbstractAction):
"""QtWebKit implementations related to web actions."""
"""QtWebEngine implementations related to web actions."""
def _action(self, action):
self._widget.triggerPageAction(action)
action_class = QWebEnginePage
action_base = QWebEnginePage.WebAction
def exit_fullscreen(self):
self._action(QWebEnginePage.ExitFullScreen)
self._widget.triggerPageAction(QWebEnginePage.ExitFullScreen)
def save_page(self):
"""Save the current page."""
self._action(QWebEnginePage.SavePage)
self._widget.triggerPageAction(QWebEnginePage.SavePage)
class WebEnginePrinting(browsertab.AbstractPrinting):
@@ -128,29 +127,37 @@ class WebEngineSearch(browsertab.AbstractSearch):
super().__init__(parent)
self._flags = QWebEnginePage.FindFlags(0)
def _find(self, text, flags, cb=None):
"""Call findText on the widget with optional callback."""
if cb is None:
self._widget.findText(text, flags)
else:
self._widget.findText(text, flags, cb)
def _find(self, text, flags, callback, caller):
"""Call findText on the widget."""
self.search_displayed = True
def search(self, text, *, ignore_case=False, reverse=False,
def wrapped_callback(found):
"""Wrap the callback to do debug logging."""
found_text = 'found' if found else "didn't find"
if flags:
flag_text = 'with flags {}'.format(debug.qflags_key(
QWebEnginePage, flags, klass=QWebEnginePage.FindFlag))
else:
flag_text = ''
log.webview.debug(' '.join([caller, found_text, text, flag_text])
.strip())
if callback is not None:
callback(found)
self._widget.findText(text, flags, wrapped_callback)
def search(self, text, *, ignore_case='never', reverse=False,
result_cb=None):
flags = QWebEnginePage.FindFlags(0)
if ignore_case == 'smart':
if not text.islower():
flags |= QWebEnginePage.FindCaseSensitively
elif not ignore_case:
flags |= QWebEnginePage.FindCaseSensitively
if reverse:
flags |= QWebEnginePage.FindBackward
self.text = text
self._flags = flags
self._find(text, flags, result_cb)
self._flags = QWebEnginePage.FindFlags(0)
if self._is_case_sensitive(ignore_case):
self._flags |= QWebEnginePage.FindCaseSensitively
if reverse:
self._flags |= QWebEnginePage.FindBackward
self._find(text, self._flags, result_cb, 'search')
def clear(self):
self.search_displayed = False
self._widget.findText('')
def prev_result(self, *, result_cb=None):
@@ -160,10 +167,10 @@ class WebEngineSearch(browsertab.AbstractSearch):
flags &= ~QWebEnginePage.FindBackward
else:
flags |= QWebEnginePage.FindBackward
self._find(self.text, flags, result_cb)
self._find(self.text, flags, result_cb, 'prev_result')
def next_result(self, *, result_cb=None):
self._find(self.text, self._flags, result_cb)
self._find(self.text, self._flags, result_cb, 'next_result')
class WebEngineCaret(browsertab.AbstractCaret):
@@ -237,8 +244,47 @@ class WebEngineCaret(browsertab.AbstractCaret):
raise browsertab.UnsupportedOperationError
return self._widget.selectedText()
def _follow_selected_cb(self, js_elem, tab=False):
"""Callback for javascript which clicks the selected element.
Args:
js_elem: The element serialized from javascript.
tab: Open in a new tab.
"""
if js_elem is None:
return
assert isinstance(js_elem, dict), js_elem
elem = webengineelem.WebEngineElement(js_elem, tab=self._tab)
if tab:
click_type = usertypes.ClickTarget.tab
else:
click_type = usertypes.ClickTarget.normal
# Only click if we see a link
if elem.is_link():
log.webview.debug("Found link in selection, clicking. ClickTarget "
"{}, elem {}".format(click_type, elem))
elem.click(click_type)
def follow_selected(self, *, tab=False):
log.stub()
if self._tab.search.search_displayed:
# We are currently in search mode.
# let's click the link via a fake-click
# https://bugreports.qt.io/browse/QTBUG-60673
self._tab.search.clear()
log.webview.debug("Clicking a searched link via fake key press.")
# send a fake enter, clicking the orange selection box
if tab:
self._tab.key_press(Qt.Key_Enter, modifier=Qt.ControlModifier)
else:
self._tab.key_press(Qt.Key_Enter)
else:
# click an existing blue selection
js_code = javascript.assemble('webelem', 'find_selected_link')
self._tab.run_js_async(js_code, lambda jsret:
self._follow_selected_cb(jsret, tab))
class WebEngineScroller(browsertab.AbstractScroller):
@@ -256,13 +302,10 @@ class WebEngineScroller(browsertab.AbstractScroller):
page = widget.page()
page.scrollPositionChanged.connect(self._update_pos)
def _key_press(self, key, count=1):
def _repeated_key_press(self, key, count=1, modifier=Qt.NoModifier):
"""Send count fake key presses to this scroller's WebEngineTab."""
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)
self._tab.key_press(key, modifier)
@pyqtSlot()
def _update_pos(self):
@@ -289,7 +332,7 @@ class WebEngineScroller(browsertab.AbstractScroller):
else:
perc_y = min(100, round(100 / dy * jsret['px']['y']))
self._at_bottom = dy >= jsret['px']['y']
self._at_bottom = math.ceil(jsret['px']['y']) >= dy
self._pos_perc = perc_x, perc_y
self.perc_changed.emit(*self._pos_perc)
@@ -319,28 +362,28 @@ class WebEngineScroller(browsertab.AbstractScroller):
self._tab.run_js_async(js_code)
def up(self, count=1):
self._key_press(Qt.Key_Up, count)
self._repeated_key_press(Qt.Key_Up, count)
def down(self, count=1):
self._key_press(Qt.Key_Down, count)
self._repeated_key_press(Qt.Key_Down, count)
def left(self, count=1):
self._key_press(Qt.Key_Left, count)
self._repeated_key_press(Qt.Key_Left, count)
def right(self, count=1):
self._key_press(Qt.Key_Right, count)
self._repeated_key_press(Qt.Key_Right, count)
def top(self):
self._key_press(Qt.Key_Home)
self._tab.key_press(Qt.Key_Home)
def bottom(self):
self._key_press(Qt.Key_End)
self._tab.key_press(Qt.Key_End)
def page_up(self, count=1):
self._key_press(Qt.Key_PageUp, count)
self._repeated_key_press(Qt.Key_PageUp, count)
def page_down(self, count=1):
self._key_press(Qt.Key_PageDown, count)
self._repeated_key_press(Qt.Key_PageDown, count)
def at_top(self):
return self.pos_px().y() == 0
@@ -356,24 +399,28 @@ class WebEngineHistory(browsertab.AbstractHistory):
def current_idx(self):
return self._history.currentItemIndex()
def back(self):
self._history.back()
def forward(self):
self._history.forward()
def can_go_back(self):
return self._history.canGoBack()
def can_go_forward(self):
return self._history.canGoForward()
def _item_at(self, i):
return self._history.itemAt(i)
def _go_to_item(self, item):
return self._history.goToItem(item)
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!")
if not qtutils.version_check('5.9', compiled=False):
# WORKAROUND for
# https://github.com/qutebrowser/qutebrowser/issues/2289
# Don't use the history's currentItem here, because of
# https://bugreports.qt.io/browse/QTBUG-59599 and because it doesn't
# contain view-source.
scheme = self._tab.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):
@@ -398,9 +445,6 @@ class WebEngineZoom(browsertab.AbstractZoom):
def _set_factor_internal(self, factor):
self._widget.setZoomFactor(factor)
def factor(self):
return self._widget.zoomFactor()
class WebEngineElements(browsertab.AbstractElements):
@@ -443,18 +487,18 @@ class WebEngineElements(browsertab.AbstractElements):
callback(elem)
def find_css(self, selector, callback, *, only_visible=False):
js_code = javascript.assemble('webelem', 'find_all', selector,
js_code = javascript.assemble('webelem', 'find_css', 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_code = javascript.assemble('webelem', 'find_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_code = javascript.assemble('webelem', 'find_focused')
js_cb = functools.partial(self._js_cb_single, callback)
self._tab.run_js_async(js_code, js_cb)
@@ -462,7 +506,7 @@ class WebEngineElements(browsertab.AbstractElements):
assert pos.x() >= 0
assert pos.y() >= 0
pos /= self._tab.zoom.factor()
js_code = javascript.assemble('webelem', 'element_at_pos',
js_code = javascript.assemble('webelem', 'find_at_pos',
pos.x(), pos.y())
js_cb = functools.partial(self._js_cb_single, callback)
self._tab.run_js_async(js_code, js_cb)
@@ -472,10 +516,11 @@ class WebEngineTab(browsertab.AbstractTab):
"""A QtWebEngine tab in the browser."""
def __init__(self, win_id, mode_manager, parent=None):
def __init__(self, *, win_id, mode_manager, private, parent=None):
super().__init__(win_id=win_id, mode_manager=mode_manager,
parent=parent)
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id)
private=private, parent=parent)
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id,
private=private)
self.history = WebEngineHistory(self)
self.scroller = WebEngineScroller(self, parent=self)
self.caret = WebEngineCaret(win_id=win_id, mode_manager=mode_manager,
@@ -556,9 +601,11 @@ class WebEngineTab(browsertab.AbstractTab):
def shutdown(self):
self.shutting_down.emit()
# WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58563
self.search.clear()
self.action.exit_fullscreen()
if qtutils.version_check('5.8', exact=True, compiled=False):
# WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58563
self.search.clear()
self._widget.shutdown()
def reload(self, *, force=False):
@@ -577,14 +624,12 @@ class WebEngineTab(browsertab.AbstractTab):
def icon(self):
return self._widget.icon()
def set_html(self, html, base_url=None):
def set_html(self, html, base_url=QUrl()):
# 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):
@@ -596,8 +641,24 @@ class WebEngineTab(browsertab.AbstractTab):
def clear_ssl_errors(self):
raise browsertab.UnsupportedOperationError
def key_press(self, key, modifier=Qt.NoModifier):
press_evt = QKeyEvent(QEvent.KeyPress, key, modifier, 0, 0, 0)
release_evt = QKeyEvent(QEvent.KeyRelease, key, modifier,
0, 0, 0)
self.send_event(press_evt)
self.send_event(release_evt)
@pyqtSlot()
def _on_history_trigger(self):
try:
self._widget.page()
except RuntimeError:
# Looks like this slot can be triggered on destroyed tabs:
# https://crashes.qutebrowser.org/view/3abffbed (Qt 5.9.1)
# wrapped C/C++ object of type WebEngineView has been deleted
log.misc.debug("Ignoring history trigger for destroyed tab")
return
url = self.url()
requested_url = self.url(requested=True)
@@ -615,6 +676,32 @@ class WebEngineTab(browsertab.AbstractTab):
self.add_history_item.emit(url, requested_url, title)
@pyqtSlot(QUrl, 'QAuthenticator*', 'QString')
def _on_proxy_authentication_required(self, url, authenticator,
proxy_host):
"""Called when a proxy needs authentication."""
msg = "<b>{}</b> requires a username and password.".format(
html_utils.escape(proxy_host))
answer = message.ask(
title="Proxy authentication required", text=msg,
mode=usertypes.PromptMode.user_pwd,
abort_on=[self.shutting_down, self.load_started])
if answer is not None:
authenticator.setUser(answer.user)
authenticator.setPassword(answer.password)
else:
try:
# pylint: disable=no-member, useless-suppression
sip.assign(authenticator, QAuthenticator())
except AttributeError:
url_string = url.toDisplayString()
error_page = jinja.render(
'error.html',
title="Error loading page: {}".format(url_string),
url=url_string, error="Proxy authentication required",
icon='')
self.set_html(error_page)
@pyqtSlot(QUrl, 'QAuthenticator*')
def _on_authentication_required(self, url, authenticator):
# FIXME:qtwebengine support .netrc
@@ -632,19 +719,31 @@ class WebEngineTab(browsertab.AbstractTab):
error_page = jinja.render(
'error.html',
title="Error loading page: {}".format(url_string),
url=url_string, error="Authentication required", icon='')
url=url_string, error="Authentication required")
self.set_html(error_page)
@pyqtSlot('QWebEngineFullScreenRequest')
def _on_fullscreen_requested(self, request):
request.accept()
on = request.toggleOn()
self.data.fullscreen = on
self.fullscreen_requested.emit(on)
if on:
notification = miscwidgets.FullscreenNotification(self)
notification.show()
notification.set_timeout(3000)
@pyqtSlot()
def _on_load_started(self):
"""Clear search when a new load is started if needed."""
if (qtutils.version_check('5.9', compiled=False) and
not qtutils.version_check('5.9.2', compiled=False)):
# WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-61506
self.search.clear()
super()._on_load_started()
@pyqtSlot(QWebEnginePage.RenderProcessTerminationStatus, int)
def _on_render_process_terminated(self, status, exitcode):
"""Show an error when the renderer process terminated."""
@@ -680,6 +779,8 @@ class WebEngineTab(browsertab.AbstractTab):
page.loadFinished.connect(self._on_load_finished)
page.certificate_error.connect(self._on_ssl_errors)
page.authenticationRequired.connect(self._on_authentication_required)
page.proxyAuthenticationRequired.connect(
self._on_proxy_authentication_required)
page.fullScreenRequested.connect(self._on_fullscreen_requested)
page.contentsSizeChanged.connect(self.contents_size_changed)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -23,28 +23,31 @@ import functools
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.browser.webengine import certificateerror, webenginesettings
from qutebrowser.config import config
from qutebrowser.utils import (log, debug, usertypes, jinja, urlutils, message,
objreg)
from qutebrowser.utils import log, debug, usertypes, jinja, urlutils, message
class WebEngineView(QWebEngineView):
"""Custom QWebEngineView subclass with qutebrowser-specific features."""
def __init__(self, tabdata, win_id, parent=None):
def __init__(self, *, tabdata, win_id, private, parent=None):
super().__init__(parent)
self._win_id = win_id
self._tabdata = tabdata
theme_color = self.style().standardPalette().color(QPalette.Base)
page = WebEnginePage(theme_color=theme_color, parent=self)
if private:
profile = webenginesettings.private_profile
assert profile.isOffTheRecord()
else:
profile = webenginesettings.default_profile
page = WebEnginePage(theme_color=theme_color, profile=profile,
parent=self)
self.setPage(page)
def shutdown(self):
@@ -76,10 +79,10 @@ class WebEngineView(QWebEngineView):
The new QWebEngineView object.
"""
debug_type = debug.qenum_key(QWebEnginePage, wintype)
background_tabs = config.get('tabs', 'background-tabs')
background = config.val.tabs.background
log.webview.debug("createWindow with type {}, background_tabs "
"{}".format(debug_type, background_tabs))
log.webview.debug("createWindow with type {}, background {}".format(
debug_type, background))
if wintype == QWebEnginePage.WebBrowserWindow:
# Shift-Alt-Click
@@ -91,13 +94,13 @@ class WebEngineView(QWebEngineView):
elif wintype == QWebEnginePage.WebBrowserTab:
# Middle-click / Ctrl-Click with Shift
# FIXME:qtwebengine this also affects target=_blank links...
if background_tabs:
if background:
target = usertypes.ClickTarget.tab
else:
target = usertypes.ClickTarget.tab_bg
elif wintype == QWebEnginePage.WebBrowserBackgroundTab:
# Middle-click / Ctrl-Click
if background_tabs:
if background:
target = usertypes.ClickTarget.tab_bg
else:
target = usertypes.ClickTarget.tab
@@ -124,18 +127,18 @@ class WebEnginePage(QWebEnginePage):
certificate_error = pyqtSignal()
shutting_down = pyqtSignal()
def __init__(self, theme_color, parent=None):
super().__init__(parent)
def __init__(self, *, theme_color, profile, parent=None):
super().__init__(profile, 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.instance.changed.connect(self._set_bg_color)
@config.change_filter('colors', 'webpage.bg')
@config.change_filter('colors.webpage.bg')
def _set_bg_color(self):
col = config.get('colors', 'webpage.bg')
col = config.val.colors.webpage.bg
if col is None:
col = self._theme_color
self.setBackgroundColor(col)
@@ -144,11 +147,10 @@ class WebEnginePage(QWebEnginePage):
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'),
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',
@@ -210,7 +212,7 @@ class WebEnginePage(QWebEnginePage):
url_string = url.toDisplayString()
error_page = jinja.render(
'error.html', title="Error loading page: {}".format(url_string),
url=url_string, error=str(error), icon='')
url=url_string, error=str(error))
if error.is_overridable():
ignore = shared.ignore_certificate_errors(
@@ -272,19 +274,12 @@ class WebEnginePage(QWebEnginePage):
def javaScriptConsoleMessage(self, level, msg, line, source):
"""Log javascript messages to qutebrowser's log."""
# FIXME:qtwebengine maybe unify this in the tab api somehow?
setting = config.get('general', 'log-javascript-console')
if setting == 'none':
return
level_to_logger = {
QWebEnginePage.InfoMessageLevel: log.js.info,
QWebEnginePage.WarningMessageLevel: log.js.warning,
QWebEnginePage.ErrorMessageLevel: log.js.error,
level_map = {
QWebEnginePage.InfoMessageLevel: usertypes.JsLogLevel.info,
QWebEnginePage.WarningMessageLevel: usertypes.JsLogLevel.warning,
QWebEnginePage.ErrorMessageLevel: usertypes.JsLogLevel.error,
}
logstring = "[{}:{}] {}".format(source, line, msg)
logger = level_to_logger[level]
logger(logstring)
shared.javascript_log_message(level_map[level], source, line, msg)
def acceptNavigationRequest(self,
url: QUrl,

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

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