summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.flake83
-rw-r--r--.gitignore16
-rw-r--r--MANIFEST.in2
-rw-r--r--doc/changelog.asciidoc4
-rw-r--r--doc/faq.asciidoc2
-rw-r--r--doc/help/configuring.asciidoc2
-rw-r--r--doc/help/settings.asciidoc9
-rw-r--r--icons/qutebrowser.xpm507
-rw-r--r--misc/requirements/requirements-codecov.txt2
-rw-r--r--misc/requirements/requirements-flake8.txt12
-rw-r--r--misc/requirements/requirements-pip.txt2
-rw-r--r--misc/requirements/requirements-tests.txt12
-rw-r--r--misc/requirements/requirements-tests.txt-raw3
-rw-r--r--qutebrowser/app.py17
-rw-r--r--qutebrowser/browser/history.py9
-rw-r--r--qutebrowser/browser/webengine/webenginetab.py47
-rw-r--r--qutebrowser/completion/completer.py5
-rw-r--r--qutebrowser/completion/completiondelegate.py8
-rw-r--r--qutebrowser/config/configdata.yml12
-rw-r--r--qutebrowser/keyinput/modeman.py11
-rw-r--r--requirements.txt2
-rwxr-xr-xscripts/asciidoc2html.py13
-rw-r--r--scripts/testbrowser/cpp/webengine/main.cpp (renamed from scripts/testbrowser_cpp/webengine/main.cpp)0
-rw-r--r--scripts/testbrowser/cpp/webengine/testbrowser.pro (renamed from scripts/testbrowser_cpp/webengine/testbrowser.pro)0
-rw-r--r--scripts/testbrowser/cpp/webkit/main.cpp (renamed from scripts/testbrowser_cpp/webkit/main.cpp)0
-rw-r--r--scripts/testbrowser/cpp/webkit/testbrowser.pro (renamed from scripts/testbrowser_cpp/webkit/testbrowser.pro)0
-rwxr-xr-xscripts/testbrowser/testbrowser_webengine.py50
-rwxr-xr-xscripts/testbrowser/testbrowser_webkit.py (renamed from scripts/testbrowser.py)36
-rw-r--r--tests/end2end/features/marks.feature2
-rw-r--r--tests/end2end/fixtures/quteprocess.py15
-rw-r--r--tests/end2end/fixtures/test_quteprocess.py20
-rw-r--r--tests/end2end/fixtures/test_testprocess.py20
-rw-r--r--tests/end2end/fixtures/testprocess.py24
-rw-r--r--tests/end2end/fixtures/webserver.py10
-rw-r--r--tests/unit/completion/test_completer.py1
-rw-r--r--tests/unit/config/test_config.py4
36 files changed, 530 insertions, 352 deletions
diff --git a/.flake8 b/.flake8
index 06883f526..340132d49 100644
--- a/.flake8
+++ b/.flake8
@@ -1,6 +1,7 @@
[flake8]
exclude = .*,__pycache__,resources.py
# B001: bare except
+# B008: Do not perform calls in argument defaults. (fine with some Qt stuff)
# B305: .next() (false-positives)
# E128: continuation line under-indented for visual indent
# E226: missing whitespace around arithmetic operator
@@ -33,7 +34,7 @@ exclude = .*,__pycache__,resources.py
# D413: Missing blank line after last section (not in pep257?)
# A003: Builtin name for class attribute (needed for attrs)
ignore =
- B001,B305,
+ B001,B008,B305,
E128,E226,E265,E501,E402,E266,E722,E731,
F401,
N802,
diff --git a/.gitignore b/.gitignore
index cb244557b..54a0dcae6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,12 +31,12 @@ __pycache__
/prof
/venv
TODO
-/scripts/testbrowser_cpp/webkit/Makefile
-/scripts/testbrowser_cpp/webkit/main.o
-/scripts/testbrowser_cpp/webkit/testbrowser
-/scripts/testbrowser_cpp/webkit/.qmake.stash
-/scripts/testbrowser_cpp/webengine/Makefile
-/scripts/testbrowser_cpp/webengine/main.o
-/scripts/testbrowser_cpp/webengine/testbrowser
-/scripts/testbrowser_cpp/webengine/.qmake.stash
+/scripts/testbrowser/cpp/webkit/Makefile
+/scripts/testbrowser/cpp/webkit/main.o
+/scripts/testbrowser/cpp/webkit/testbrowser
+/scripts/testbrowser/cpp/webkit/.qmake.stash
+/scripts/testbrowser/cpp/webengine/Makefile
+/scripts/testbrowser/cpp/webengine/main.o
+/scripts/testbrowser/cpp/webengine/testbrowser
+/scripts/testbrowser/cpp/webengine/.qmake.stash
/scripts/dev/pylint_checkers/qute_pylint.egg-info
diff --git a/MANIFEST.in b/MANIFEST.in
index 54bb613f3..b20c2bc77 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -23,7 +23,7 @@ include qutebrowser/config/configdata.yml
prune www
prune scripts/dev
-prune scripts/testbrowser_cpp
+prune scripts/testbrowser/cpp
prune .github
exclude scripts/asciidoc2html.py
exclude doc/notes
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 2fb8af4d7..47bf1e8e8 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -61,6 +61,8 @@ Added
- Support for incremental search, with a new `search.incremental` setting.
- New `--rapid` flag for `:command-accept` (bound to `Ctrl-Enter` by default),
which allows executing a command in the completion without closing it.
+- The `colors.completion.fg` setting can now be a list, allowing to specify
+ different colors for the three completion columns.
Changed
~~~~~~~
@@ -131,6 +133,8 @@ Fixed
- Fix :click-element with an ID containing non-alphanumeric characters.
- Fix crash when a subprocess outputs data which is not decodable as UTF-8.
- Fix crash when closing a tab immediately after hinting.
+- Worked around issues in Qt 5.10 with loading progress never being finished.
+- Fixed a crash when writing a flag before a command (e.g. `:-w open `).
Deprecated
~~~~~~~~~~
diff --git a/doc/faq.asciidoc b/doc/faq.asciidoc
index 7794c9d13..0d94796a4 100644
--- a/doc/faq.asciidoc
+++ b/doc/faq.asciidoc
@@ -221,5 +221,5 @@ My issue is not listed.::
https://github.com/qutebrowser/qutebrowser/issues[the issue tracker] or
using the `:report` command.
If you are reporting a segfault, make sure you read the
- link:doc/stacktrace.asciidoc[guide] on how to report them with all needed
+ link:stacktrace.asciidoc[guide] on how to report them with all needed
information.
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index 766e6bc7f..a9b7b6ddf 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -264,7 +264,7 @@ get a string:
.config.py:
[source,python]
----
-print(str(config.configdir / 'config.py')
+print(str(config.configdir / 'config.py'))
----
Handling errors
diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
index 35c90ba61..53af8399d 100644
--- a/doc/help/settings.asciidoc
+++ b/doc/help/settings.asciidoc
@@ -701,10 +701,15 @@ Default: +pass:[#333333]+
[[colors.completion.fg]]
=== colors.completion.fg
Text color of the completion widget.
+May be a single color to use for all columns or a list of three colors, one for each column.
-Type: <<types,QtColor>>
+Type: <<types,List of QtColor&#44; or QtColor>>
-Default: +pass:[white]+
+Default:
+
+- +pass:[white]+
+- +pass:[white]+
+- +pass:[white]+
[[colors.completion.item.selected.bg]]
=== colors.completion.item.selected.bg
diff --git a/icons/qutebrowser.xpm b/icons/qutebrowser.xpm
index 8fac91045..04e183154 100644
--- a/icons/qutebrowser.xpm
+++ b/icons/qutebrowser.xpm
@@ -1,207 +1,302 @@
/* XPM */
-static char *qutebrowser[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 169 2 ",
-" c #0A396E",
-". c #0B3C72",
-"X c #0B4077",
-"o c #0C437B",
-"O c #134175",
-"+ c #15467C",
-"@ c #18477B",
-"# c #1A497D",
-"$ c #0D4B86",
-"% c #0F4E8D",
-"& c #124A80",
-"* c #1F4F83",
-"= c #0E518C",
-"- c #1F5084",
-"; c #11508C",
-": c #0F5193",
-"> c #115799",
-", c #115B9C",
-"< c #204F83",
-"1 c #245287",
-"2 c #2A598C",
-"3 c #325E8F",
-"4 c #11609F",
-"5 c #346496",
-"6 c #3B6898",
-"7 c #115CA1",
-"8 c #115EAC",
-"9 c #1263A3",
-"0 c #1260AD",
-"q c #136BAC",
-"w c #136BB2",
-"e c #1366BA",
-"r c #196BB2",
-"t c #157ABB",
-"y c #1577BB",
-"u c #2E6DB0",
-"i c #387FB1",
-"p c #456E9A",
-"a c #4873A1",
-"s c #4375AA",
-"d c #507AA6",
-"f c #597EA4",
-"g c #4D7EB3",
-"h c #156FCB",
-"j c #167AC5",
-"k c #1675CA",
-"l c #177BCE",
-"z c #1777D8",
-"x c #1476E4",
-"c c #167BE6",
-"v c #167DE8",
-"b c #197EEF",
-"n c #1A7FF0",
-"m c #1A80BE",
-"M c #5F87AF",
-"N c #5D8BBA",
-"B c #5A84B1",
-"V c #6C8FB3",
-"C c #6F96BE",
-"Z c #1886CC",
-"A c #1883D7",
-"S c #198DD5",
-"D c #1987D9",
-"F c #198ADC",
-"G c #1A96DC",
-"H c #3090D9",
-"J c #1682E9",
-"K c #1983ED",
-"L c #1689E9",
-"P c #1A8DEE",
-"I c #1B95ED",
-"U c #1C9EEA",
-"Y c #1B97E4",
-"T c #1A84F2",
-"R c #1A8BF2",
-"E c #1C94F4",
-"W c #1D9CF5",
-"Q c #3388E6",
-"! c #3D90E9",
-"~ c #228EF3",
-"^ c #229FF6",
-"/ c #3294F4",
-"( c #3D9FF6",
-") c #339CF4",
-"_ c #1CA2E5",
-"` c #1DABEE",
-"' c #1DA4F6",
-"] c #1EA9F7",
-"[ c #1EADF8",
-"{ c #1FB4F9",
-"} c #1FB9FA",
-"| c #20ACF8",
-" . c #27A4F6",
-".. c #3DA9F6",
-"X. c #20B9FA",
-"o. c #2EB6F9",
-"O. c #458DC9",
-"+. c #5C8DC1",
-"@. c #5795C6",
-"#. c #709DCB",
-"$. c #74A8DD",
-"%. c #4A97EA",
-"&. c #4896EA",
-"*. c #559EEA",
-"=. c #439AF5",
-"-. c #46A3F6",
-";. c #5FA9F6",
-":. c #5EA6F3",
-">. c #47BCF9",
-",. c #51B5F8",
-"<. c #58BDF8",
-"1. c #68ABEF",
-"2. c #7DB9E7",
-"3. c #63AEF7",
-"4. c #6FB1F7",
-"5. c #66B9F8",
-"6. c #61B2F6",
-"7. c #71B4F7",
-"8. c #78B7F4",
-"9. c #72BFF9",
-"0. c #3BC0FA",
-"q. c #6FCEFB",
-"w. c #6CC5FA",
-"e. c #7BCAF9",
-"r. c #89A7C3",
-"t. c #83A2C1",
-"y. c #98B6D3",
-"u. c #9DB9D3",
-"i. c #89B6E4",
-"p. c #83B6E9",
-"a. c #81BDF7",
-"s. c #83BFF8",
-"d. c #9EC4E9",
-"f. c #8CC2F9",
-"g. c #85CDFB",
-"h. c #87C4F9",
-"j. c #92C6F9",
-"k. c #95CAFA",
-"l. c #9CCBFA",
-"z. c #89D7FC",
-"x. c #91D9FC",
-"c. c #9CDEFD",
-"v. c #9ED2FB",
-"b. c #A7CAEC",
-"n. c #B5CEE3",
-"m. c #A1CEFA",
-"M. c #AED0F0",
-"N. c #ACD6FA",
-"B. c #A0DFFC",
-"V. c #AFD8FC",
-"C. c #B5D9FB",
-"Z. c #BCDDFC",
-"A. c #BFDCF5",
-"S. c #ACE3FD",
-"D. c #B5E5FE",
-"F. c #BBE2FC",
-"G. c #CFE5F5",
-"H. c #C3E1FC",
-"J. c #CAE6FD",
-"K. c #CCEBFD",
-"L. c #C4EBFE",
-"P. c #D6EDFE",
-"I. c #DAEEFD",
-"U. c #DEF1FE",
-"Y. c #D6F2FE",
-"T. c #E4F4FE",
-"R. c #E9F6FE",
-"E. c #EBF8FF",
-"W. c None",
-/* pixels */
-"W.W.W.W.W.W.W.W.W.W.W.c.S.L.Y.E.E.S.X.} W.W.W.W.W.W.W.W.W.W.W.W.",
-"W.W.W.W.W.W.W.W.W.D.T.E.E.T.L.D.c.z.} } X.} } W.W.W.W.W.W.W.W.W.",
-"W.W.W.W.W.W.W.B.T.T.R.T.R.U.0.X.z.S.} } } } { { X.W.W.W.W.W.W.W.",
-"W.W.W.W.W.W.x.x.K.T.T.T.L.P.q.o.{ } } ` _ { { { { { W.W.W.W.W.W.",
-"W.W.W.W.W.c.P.D.G.u.r.i 9 Z _ { { G 4 X t { { { { { { W.W.W.W.W.",
-"W.W.W.W.K.U.n.f O { = t { { { { [ { { W.W.W.W.",
-"W.W.W.F.I.t.. ' t { { [ [ [ [ [ >.W.W.W.",
-"W.W.x.P.V ' X t ` [ [ [ [ [ [ o.e.W.W.",
-"W.W.J.y. X t S Y Z $ ' . y [ [ [ ] [ [ | Z.J.W.W.",
-"W.<.e.& , _ ] ] [ ] U . ' . y [ ' [ ] ] ] w.K.J.g.W.",
-"W.' S o ' ' [ ' [ ' ] o ' . y Y 9 = = 9 @.J.J.J.F.W.",
-"W.| , j ' ' ' ' ' ' ' o ' . $ p A.J.J.g.",
-"' .. G ' ' ' ' ' ' ' o ' . M H.H.h.",
-",.2. . W ' W ' ' ' ' W . ' . M.A.x.",
-"N.M.. . W W W ' W W W W .w 9 I U 0 #.Z.m.",
-" .9.O D W W W W ' W j $ % F W W W .5 d Z.C.",
-"W W ; 9 9.h.5...Q % o j W W W W W W O. 3 C.N.",
-"E W 7 B b.d.a . w E E W W W E W E A @ C.l.",
-"I E l u W E W E W E E E E A . - k.6.",
-"P E E 7 m.o E E E E E E E E l . = E P ",
-"L E E E > . O s.o E E E E E E E E 7 , E L ",
-"W.R E R ) #.5 1 6 N i.2 s.+ E E E E E E R L . k R W.",
-"W.L R E -.m.m.m.m.m.m.2 m.@ N m.m.s.( R R % X E J W.",
-"W.W.K R ~ a.m.l.l.l.l.2 s.+ < i.l.m.j.h % e K W.W.",
-"W.W.J R R / l.l.l.l.k.2 s.+ * 5 + 8 R J W.W.",
-"W.W.W.v T R 3.k.k.j.k.2 2 j.& . 8 R v W.W.W.",
-"W.W.W.W.J T ~ 7.j.j.j.g +.p.j.s.+. . . : z T v W.W.W.W.",
-"W.W.W.W.W.c T T =.f.j.j.s.j.j.j.j.$.g s u e h b T T v W.W.W.W.W.",
-"W.W.W.W.W.W.c b n 4.f.f.s.m.s.s.s.j.s.j./ T n T b c W.W.W.W.W.W.",
-"W.W.W.W.W.W.W.c x 1.s.s.s.s.s.s.s.s.4.=.n T n c c W.W.W.W.W.W.W.",
-"W.W.W.W.W.W.W.W.W.&.*.1.a.s.s.s.s.3.n n v x x W.W.W.W.W.W.W.W.W.",
-"W.W.W.W.W.W.W.W.W.W.W.%.%.%.%.*.*.Q x x x W.W.W.W.W.W.W.W.W.W.W."
-};
+static char * qutebrowser_xpm[] = {
+"32 32 267 2",
+" c None",
+". c #9FD4FD",
+"+ c #99CBFE",
+"@ c #90C3FE",
+"# c #89BFFE",
+"$ c #81BCFF",
+"% c #80BBFF",
+"& c #9BCAFD",
+"* c #A9DBFB",
+"= c #88D3FB",
+"- c #98CBFE",
+"; c #81BBFF",
+"> c #7EBAFF",
+", c #84BDFF",
+"' c #8DC2FF",
+") c #96C7FE",
+"! c #A0CCFE",
+"~ c #A9D1FE",
+"{ c #CEE5FD",
+"] c #C7E3FC",
+"^ c #8AD3FB",
+"/ c #9DCFFD",
+"( c #C3DFFD",
+"_ c #CDE4FD",
+": c #A3CEFE",
+"< c #94C6FE",
+"[ c #CAE5FC",
+"} c #7DD0FB",
+"| c #9ECDFD",
+"1 c #A1CDFE",
+"2 c #8BC1FF",
+"3 c #87BFFF",
+"4 c #ADD4FE",
+"5 c #C6E1FD",
+"6 c #CCE3FC",
+"7 c #A7DAFB",
+"8 c #9DCBFE",
+"9 c #78AFF1",
+"0 c #6096D4",
+"a c #4B82C0",
+"b c #5A84B3",
+"c c #6589B1",
+"d c #6F92B9",
+"e c #90AED0",
+"f c #C4DBF5",
+"g c #6286AE",
+"h c #7D9EC2",
+"i c #BADFFC",
+"j c #85BDFE",
+"k c #78B4F8",
+"l c #4C83C0",
+"m c #1E4F87",
+"n c #0A396E",
+"o c #345D8D",
+"p c #CDE4FC",
+"q c #88A7CA",
+"r c #1D497C",
+"s c #799BBF",
+"t c #8AC1FD",
+"u c #5E97D7",
+"v c #14457B",
+"w c #4F76A0",
+"x c #A9D5FC",
+"y c #95C9FD",
+"z c #4C82C1",
+"A c #0A3A6F",
+"B c #C9E3FD",
+"C c #95CCFC",
+"D c #629BDB",
+"E c #0B3A6F",
+"F c #0C3B6F",
+"G c #4E749F",
+"H c #8CACCE",
+"I c #6185AD",
+"J c #CBE4FD",
+"K c #89C0FF",
+"L c #98CDFA",
+"M c #27558A",
+"N c #144175",
+"O c #9BB8D8",
+"P c #335D8C",
+"Q c #AFC9E6",
+"R c #AFD4FE",
+"S c #91C7FD",
+"T c #A0C0DE",
+"U c #194779",
+"V c #80A1C5",
+"W c #C8E1F9",
+"X c #9CB9D8",
+"Y c #7799BE",
+"Z c #6489B0",
+"` c #7092B9",
+" . c #6E9DCF",
+".. c #79B5F9",
+"+. c #83BDFE",
+"@. c #7395BA",
+"#. c #315C8B",
+"$. c #7C9EC2",
+"%. c #C0D9F3",
+"&. c #7294BA",
+"*. c #5C94D4",
+"=. c #91CCFC",
+"-. c #88CBFA",
+";. c #5179A3",
+">. c #6E91B7",
+",. c #6084AC",
+"'. c #96B3D4",
+"). c #275283",
+"!. c #0C3C71",
+"~. c #629CDC",
+"{. c #94C6FD",
+"]. c #A7D2FC",
+"^. c #36659A",
+"/. c #2C5788",
+"(. c #9DBAD9",
+"_. c #B4CEEA",
+":. c #476E9A",
+"<. c #7EB9FE",
+"[. c #8DC3FD",
+"}. c #8CC2FE",
+"|. c #2F619B",
+"1. c #87A6C9",
+"2. c #7A9BC0",
+"3. c #CBE2FB",
+"4. c #C7DFF8",
+"5. c #6C8FB5",
+"6. c #113F73",
+"7. c #0F3D71",
+"8. c #547AA4",
+"9. c #9CBAD9",
+"0. c #B9D3EE",
+"a. c #A3C0DE",
+"b. c #31629A",
+"c. c #659EE0",
+"d. c #87BFFE",
+"e. c #C3E0FD",
+"f. c #4371A4",
+"g. c #7496BB",
+"h. c #90AFD1",
+"i. c #245081",
+"j. c #416A96",
+"k. c #B0CBE7",
+"l. c #CCE4FD",
+"m. c #7DB8FD",
+"n. c #1E5088",
+"o. c #497EBC",
+"p. c #C9E3FC",
+"q. c #7193B9",
+"r. c #C6E0FB",
+"s. c #A2CDFE",
+"t. c #97C8FE",
+"u. c #A7D0FE",
+"v. c #BDDCFD",
+"w. c #9EC2E8",
+"x. c #416996",
+"y. c #366AA6",
+"z. c #C0DEFC",
+"A. c #A2BFDD",
+"B. c #326299",
+"C. c #649DDF",
+"D. c #71ABED",
+"E. c #3569A4",
+"F. c #0D3C71",
+"G. c #6998CD",
+"H. c #30639D",
+"I. c #A8D3F8",
+"J. c #2B5686",
+"K. c #3A679B",
+"L. c #ADCAEA",
+"M. c #85A6C9",
+"N. c #33639B",
+"O. c #9CCBFD",
+"P. c #86C2F7",
+"Q. c #0E3C71",
+"R. c #1B4C83",
+"S. c #5D95D5",
+"T. c #557BA5",
+"U. c #85C0F6",
+"V. c #55A8EF",
+"W. c #94B3D3",
+"X. c #1C497C",
+"Y. c #13437A",
+"Z. c #487DBB",
+"`. c #7BB7FB",
+" + c #76B1F5",
+".+ c #4E85C3",
+"++ c #ACD3FE",
+"@+ c #2F5989",
+"#+ c #7597BC",
+"$+ c #53A7EF",
+"%+ c #C6E1FC",
+"&+ c #B6D5F7",
+"*+ c #5890D0",
+"=+ c #4076B2",
+"-+ c #619ADB",
+";+ c #7CB7FC",
+">+ c #7DB9FE",
+",+ c #5087C6",
+"'+ c #134479",
+")+ c #23548D",
+"!+ c #24558D",
+"~+ c #8AAACC",
+"{+ c #A2C1E1",
+"]+ c #86C1F5",
+"^+ c #B4D7FE",
+"/+ c #6CA5E8",
+"(+ c #22548C",
+"_+ c #6D94BF",
+":+ c #98B6D6",
+"<+ c #134174",
+"[+ c #84BDF5",
+"}+ c #CAE4FC",
+"|+ c #CBE3FD",
+"1+ c #8FC3FF",
+"2+ c #3F72AD",
+"3+ c #49719C",
+"4+ c #0C3B70",
+"5+ c #9CBBDB",
+"6+ c #79B7F3",
+"7+ c #BFDCFD",
+"8+ c #7FBBFF",
+"9+ c #7E9FC3",
+"0+ c #77B6F3",
+"a+ c #A5CEF7",
+"b+ c #9FCBFE",
+"c+ c #3267A1",
+"d+ c #A4CDF7",
+"e+ c #B9D9FA",
+"f+ c #C7E1FD",
+"g+ c #90C3FF",
+"h+ c #15457C",
+"i+ c #558CCB",
+"j+ c #2E5889",
+"k+ c #7B9CC1",
+"l+ c #C4DDF6",
+"m+ c #BBDAFA",
+"n+ c #CDE5FD",
+"o+ c #B3D6FE",
+"p+ c #80BAFF",
+"q+ c #4E84C3",
+"r+ c #3E73AF",
+"s+ c #78B3F7",
+"t+ c #5991D1",
+"u+ c #477DBA",
+"v+ c #4075B2",
+"w+ c #5783B6",
+"x+ c #BDD6F0",
+"y+ c #A1CBF6",
+"z+ c #90C4FF",
+"A+ c #BCDBFD",
+"B+ c #73B0F1",
+"C+ c #C5E0FB",
+"D+ c #91C5FF",
+"E+ c #AED3FE",
+"F+ c #C9E2FC",
+"G+ c #76B2F2",
+"H+ c #8BBFF9",
+"I+ c #81BBFE",
+"J+ c #9ECBFE",
+"K+ c #84B8F3",
+"L+ c #79B4F4",
+"M+ c #88BEFA",
+"N+ c #83BCFE",
+"O+ c #A4CFFC",
+"P+ c #A6CDF6",
+"Q+ c #82B8F2",
+"R+ c #529BEC",
+" . + @ # $ % & * = ",
+" - ; > > , ' ) ! ~ { { { ] ^ ",
+" / ; > > > > ; ( _ : < { { { { { [ } ",
+" | 1 2 > > > 2 3 4 5 { { { { { 6 { { { 7 ",
+" 8 $ < 9 0 a b c d e { { { { f g h { { { { i ",
+" j k l m n n n n n n o { { p q r n s { { { { { i ",
+" t u v n n n n n n n n o { { w n n n s { { { { { { x ",
+" y z A n n n n n n n n n o { { o n n n s { { { { { { B C ",
+" D E n n n F G H I n n n o { { o n n n s { { { { { J K % ",
+" L M n n n N O { { s n n n o { { o n n P Q { { { { { R > > S ",
+" T n n n n H { { { s n n n o { { o U V 6 W X Y Z ` ...> > +. ",
+" @.n n n #.{ { { { s n n n o { { $.%.W &.U n n n n n v *.> > =.",
+"-.;.n n n >.{ { { { s n n n ,.{ { { '.).n n n n n n n n !.~.> {.",
+"].^.n n n q { { { { s n /.(.{ { _.:.n n n n n n n n n n n m <.[.",
+"}.|.n n n H { { { { 1.2.3.{ 4.5.6.n n n 7.8.9.0.a.b.n n n n c.d.",
+"e.f.n n n g.{ { { { { { { h.i.n n n n j.k.{ { { l.m.n.n n n o.$ ",
+"p.q.n n n /.r.s.t.u.v.w.x.n n n n i.h.{ { { { { { u.o.n n n y.$ ",
+"z.A.n n n n B.C.D.u E.F.n n n 6.5.4.{ 3.2.1.{ { { { G.n n n H.d.",
+"I.p J.n n n n n n n n n n n K.L.{ { (./.n s { { { { M.n n n N.O.",
+"P.{ (.Q.n n n n n n n n R.S.> K _ ,.n n n s { { { { 5.n n n T.U.",
+"V.{ { W.X.n n n n n Y.Z.`. +.+> ++o n n n s { { { { @+n n n #+$+",
+" %+{ { &+*+Z.=+a -+;+>+,+'+)+> > !+n n n s { { { ~+n n n n {+ ",
+" ]+{ { ^+> > > > > /+(+n n )+> > )+n n n _+{ { :+<+n n n o [+ ",
+" }+{ |+1+> > > > l n n n )+> > )+n n n 2+~+3+E n n n 4+5+ ",
+" 6+{ { 7+8+> > > l n n n )+> > )+n n n n n n n n n F 9+0+ ",
+" a+{ { b+> > > l n n n c+> > )+n n n n n n n n r O d+ ",
+" e+{ f+g+> > l n h+i+<.> > )+n n n n n E j+k+l+m+ ",
+" e+{ n+o+p+q+r+s+> > > > t+u+v+w+2.W.x+{ { e+ ",
+" y+{ { z+>+> > > > > > > > > A+{ { { { d+ ",
+" B+C+) > > > > > > > > D+E+{ { { F+G+ ",
+" H+I+> > > > > > J+{ { { C+K+ ",
+" L+M+# N+; 8+O+P+Q+R+ "};
diff --git a/misc/requirements/requirements-codecov.txt b/misc/requirements/requirements-codecov.txt
index 6601cfb12..df7a12ed6 100644
--- a/misc/requirements/requirements-codecov.txt
+++ b/misc/requirements/requirements-codecov.txt
@@ -2,7 +2,7 @@
certifi==2017.11.5
chardet==3.0.4
-codecov==2.0.10
+codecov==2.0.13
coverage==4.4.2
idna==2.6
requests==2.18.4
diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt
index 37ceb7f31..0ae43d663 100644
--- a/misc/requirements/requirements-flake8.txt
+++ b/misc/requirements/requirements-flake8.txt
@@ -1,23 +1,23 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-attrs==17.3.0
+attrs==17.4.0
flake8==3.5.0
-flake8-bugbear==17.4.0
+flake8-bugbear==17.12.0
flake8-builtins==1.0.post0
flake8-comprehensions==1.4.1
flake8-copyright==0.2.0
flake8-debugger==3.0.0
flake8-deprecated==1.3
-flake8-docstrings==1.1.0
-flake8-future-import==0.4.3
+flake8-docstrings==1.3.0
+flake8-future-import==0.4.4
flake8-mock==0.3
flake8-per-file-ignores==0.4
-flake8-polyfill==1.0.1
+flake8-polyfill==1.0.2
flake8-string-format==0.2.3
flake8-tidy-imports==1.1.0
flake8-tuple==0.2.13
mccabe==0.6.1
-pep8-naming==0.4.1
+pep8-naming==0.5.0
pycodestyle==2.3.1
pydocstyle==2.1.1
pyflakes==1.6.0
diff --git a/misc/requirements/requirements-pip.txt b/misc/requirements/requirements-pip.txt
index b7914cac5..54cacc3c3 100644
--- a/misc/requirements/requirements-pip.txt
+++ b/misc/requirements/requirements-pip.txt
@@ -3,6 +3,6 @@
appdirs==1.4.3
packaging==16.8
pyparsing==2.2.0
-setuptools==38.2.4
+setuptools==38.4.0
six==1.11.0
wheel==0.30.0
diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt
index bf80acee7..e5f9d35af 100644
--- a/misc/requirements/requirements-tests.txt
+++ b/misc/requirements/requirements-tests.txt
@@ -1,6 +1,6 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-attrs==17.3.0
+attrs==17.4.0
beautifulsoup4==4.6.0
cheroot==6.0.0
click==6.7
@@ -11,7 +11,7 @@ fields==5.0.0
Flask==0.12.2
glob2==0.6
hunter==2.0.2
-hypothesis==3.42.1
+hypothesis==3.44.13
itsdangerous==0.24
# Jinja2==2.10
Mako==1.0.7
@@ -21,19 +21,19 @@ parse-type==0.4.2
pluggy==0.6.0
py==1.5.2
py-cpuinfo==3.3.0
-pytest==3.3.1
+pytest==3.3.1 # rq.filter: != 3.3.2
pytest-bdd==2.19.0
pytest-benchmark==3.1.1
pytest-cov==2.5.1
pytest-faulthandler==1.3.1
pytest-instafail==0.3.0
pytest-mock==1.6.3
-pytest-qt==2.3.0
+pytest-qt==2.3.1
pytest-repeat==0.4.1
-pytest-rerunfailures==3.1
+pytest-rerunfailures==4.0
pytest-travis-fold==1.3.0
pytest-xvfb==1.0.0
PyVirtualDisplay==0.2.1
six==1.11.0
vulture==0.26
-Werkzeug==0.13
+Werkzeug==0.14.1
diff --git a/misc/requirements/requirements-tests.txt-raw b/misc/requirements/requirements-tests.txt-raw
index 121689980..174eeb7df 100644
--- a/misc/requirements/requirements-tests.txt-raw
+++ b/misc/requirements/requirements-tests.txt-raw
@@ -4,7 +4,7 @@ coverage
Flask
hunter
hypothesis
-pytest
+pytest==3.3.1
pytest-bdd
pytest-benchmark
pytest-cov
@@ -19,3 +19,4 @@ pytest-xvfb
vulture
#@ ignore: Jinja2, MarkupSafe, colorama
+#@ filter: pytest != 3.3.2
diff --git a/qutebrowser/app.py b/qutebrowser/app.py
index a2d768923..e3d06391d 100644
--- a/qutebrowser/app.py
+++ b/qutebrowser/app.py
@@ -872,10 +872,6 @@ class EventFilter(QObject):
super().__init__(parent)
self._activated = True
self._handlers = {
- QEvent.MouseButtonDblClick: self._handle_mouse_event,
- QEvent.MouseButtonPress: self._handle_mouse_event,
- QEvent.MouseButtonRelease: self._handle_mouse_event,
- QEvent.MouseMove: self._handle_mouse_event,
QEvent.KeyPress: self._handle_key_event,
QEvent.KeyRelease: self._handle_key_event,
}
@@ -900,19 +896,6 @@ class EventFilter(QObject):
# No window available yet, or not a MainWindow
return False
- def _handle_mouse_event(self, _event):
- """Handle a mouse event.
-
- Args:
- _event: The QEvent which is about to be delivered.
-
- Return:
- True if the event should be filtered, False if it's passed through.
- """
- # Mouse cursor shown (overrideCursor None) -> don't filter event
- # Mouse cursor hidden (overrideCursor not None) -> filter event
- return qApp.overrideCursor() is not None
-
def eventFilter(self, obj, event):
"""Handle an event.
diff --git a/qutebrowser/browser/history.py b/qutebrowser/browser/history.py
index ecab730ae..04bc1be15 100644
--- a/qutebrowser/browser/history.py
+++ b/qutebrowser/browser/history.py
@@ -32,7 +32,7 @@ from qutebrowser.misc import objects, sql
# increment to indicate that HistoryCompletion must be regenerated
-_USER_VERSION = 1
+_USER_VERSION = 2
class CompletionHistory(sql.SqlTable):
@@ -102,7 +102,8 @@ class WebHistory(sql.SqlTable):
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')
+ 'WHERE NOT redirect and url NOT LIKE "qute://back%" '
+ '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)
@@ -171,7 +172,9 @@ class WebHistory(sql.SqlTable):
@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':
+ if any(url.scheme() == 'data' or
+ (url.scheme(), url.host()) == ('qute', 'back')
+ for url in (url, requested_url)):
return
if url.isEmpty():
# things set via setHtml
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index 813f1eb9c..9328698bc 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -24,7 +24,8 @@ import functools
import html as html_utils
import sip
-from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QPointF, QUrl, QTimer
+from PyQt5.QtCore import (pyqtSignal, pyqtSlot, Qt, QEvent, QPoint, QPointF,
+ QUrl, QTimer)
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtNetwork import QAuthenticator
from PyQt5.QtWidgets import QApplication
@@ -539,7 +540,15 @@ class WebEngineElements(browsertab.AbstractElements):
class WebEngineTab(browsertab.AbstractTab):
- """A QtWebEngine tab in the browser."""
+ """A QtWebEngine tab in the browser.
+
+ Signals:
+ _load_finished_fake:
+ Used in place of unreliable loadFinished
+ """
+
+ # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-65223
+ _load_finished_fake = pyqtSignal(bool)
def __init__(self, *, win_id, mode_manager, private, parent=None):
super().__init__(win_id=win_id, mode_manager=mode_manager,
@@ -793,6 +802,24 @@ class WebEngineTab(browsertab.AbstractTab):
}
self.renderer_process_terminated.emit(status_map[status], exitcode)
+ @pyqtSlot(int)
+ def _on_load_progress_workaround(self, perc):
+ """Use loadProgress(100) to emit loadFinished(True).
+
+ See https://bugreports.qt.io/browse/QTBUG-65223
+ """
+ if perc == 100 and self.load_status() != usertypes.LoadStatus.error:
+ self._load_finished_fake.emit(True)
+
+ @pyqtSlot(bool)
+ def _on_load_finished_workaround(self, ok):
+ """Use only loadFinished(False).
+
+ See https://bugreports.qt.io/browse/QTBUG-65223
+ """
+ if not ok:
+ self._load_finished_fake.emit(False)
+
def _connect_signals(self):
view = self._widget
page = view.page()
@@ -801,9 +828,6 @@ class WebEngineTab(browsertab.AbstractTab):
page.linkHovered.connect(self.link_hovered)
page.loadProgress.connect(self._on_load_progress)
page.loadStarted.connect(self._on_load_started)
- page.loadFinished.connect(self._on_history_trigger)
- page.loadFinished.connect(self._restore_zoom)
- page.loadFinished.connect(self._on_load_finished)
page.certificate_error.connect(self._on_ssl_errors)
page.authenticationRequired.connect(self._on_authentication_required)
page.proxyAuthenticationRequired.connect(
@@ -816,6 +840,19 @@ class WebEngineTab(browsertab.AbstractTab):
view.renderProcessTerminated.connect(
self._on_render_process_terminated)
view.iconChanged.connect(self.icon_changed)
+ # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-65223
+ if qtutils.version_check('5.10', compiled=False):
+ page.loadProgress.connect(self._on_load_progress_workaround)
+ self._load_finished_fake.connect(self._on_history_trigger)
+ self._load_finished_fake.connect(self._restore_zoom)
+ self._load_finished_fake.connect(self._on_load_finished)
+ page.loadFinished.connect(self._on_load_finished_workaround)
+ else:
+ # for older Qt versions which break with the above
+ page.loadProgress.connect(self._on_load_progress)
+ page.loadFinished.connect(self._on_history_trigger)
+ page.loadFinished.connect(self._restore_zoom)
+ page.loadFinished.connect(self._on_load_finished)
def event_target(self):
return self._widget.focusProxy()
diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py
index 30a180554..4e187750d 100644
--- a/qutebrowser/completion/completer.py
+++ b/qutebrowser/completion/completer.py
@@ -87,8 +87,6 @@ class Completer(QObject):
# cursor on a flag or after an explicit split (--)
return None
log.completion.debug("Before removing flags: {}".format(before_cursor))
- before_cursor = [x for x in before_cursor if not x.startswith('-')]
- log.completion.debug("After removing flags: {}".format(before_cursor))
if not before_cursor:
# '|' or 'set|'
log.completion.debug('Starting command completion')
@@ -99,6 +97,9 @@ class Completer(QObject):
log.completion.debug("No completion for unknown command: {}"
.format(before_cursor[0]))
return None
+
+ before_cursor = [x for x in before_cursor if not x.startswith('-')]
+ log.completion.debug("After removing flags: {}".format(before_cursor))
argpos = len(before_cursor) - 1
try:
func = cmd.get_pos_arg_info(argpos).completion
diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py
index 6688a2dfa..b4f9c5a33 100644
--- a/qutebrowser/completion/completiondelegate.py
+++ b/qutebrowser/completion/completiondelegate.py
@@ -138,10 +138,10 @@ class CompletionItemDelegate(QStyledItemDelegate):
self._painter.translate(text_rect.left(), text_rect.top())
self._get_textdoc(index)
- self._draw_textdoc(text_rect)
+ self._draw_textdoc(text_rect, index.column())
self._painter.restore()
- def _draw_textdoc(self, rect):
+ def _draw_textdoc(self, rect, col):
"""Draw the QTextDocument of an item.
Args:
@@ -156,7 +156,9 @@ class CompletionItemDelegate(QStyledItemDelegate):
elif not self._opt.state & QStyle.State_Enabled:
color = config.val.colors.completion.category.fg
else:
- color = config.val.colors.completion.fg
+ colors = config.val.colors.completion.fg
+ # if multiple colors are set, use different colors per column
+ color = colors[col % len(colors)]
self._painter.setPen(color)
ctx = QAbstractTextDocumentLayout.PaintContext()
diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
index 8778cc013..a118a8b59 100644
--- a/qutebrowser/config/configdata.yml
+++ b/qutebrowser/config/configdata.yml
@@ -1540,9 +1540,15 @@ zoom.text_only:
## colors
colors.completion.fg:
- default: white
- type: QtColor
- desc: Text color of the completion widget.
+ default: ["white", "white", "white"]
+ type:
+ name: ListOrValue
+ valtype: QtColor
+ desc: >-
+ Text color of the completion widget.
+
+ May be a single color to use for all columns or a list of three colors,
+ one for each column.
colors.completion.odd.bg:
default: '#444444'
diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py
index ad9bd06ee..b8c46476f 100644
--- a/qutebrowser/keyinput/modeman.py
+++ b/qutebrowser/keyinput/modeman.py
@@ -322,10 +322,13 @@ class ModeManager(QObject):
if self.mode is None:
# We got events before mode is set, so just pass them through.
return False
- if event.type() == QEvent.KeyPress:
- return self._eventFilter_keypress(event)
- else:
- return self._eventFilter_keyrelease(event)
+
+ handlers = {
+ QEvent.KeyPress: self._eventFilter_keypress,
+ QEvent.KeyRelease: self._eventFilter_keyrelease,
+ }
+ handler = handlers[event.type()]
+ return handler(event)
@cmdutils.register(instance='mode-manager', scope='window')
def clear_keychain(self):
diff --git a/requirements.txt b/requirements.txt
index 8d95759b2..0d2652698 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-attrs==17.3.0
+attrs==17.4.0
colorama==0.3.9
cssutils==1.0.2
Jinja2==2.10
diff --git a/scripts/asciidoc2html.py b/scripts/asciidoc2html.py
index dce1f27bd..01af53693 100755
--- a/scripts/asciidoc2html.py
+++ b/scripts/asciidoc2html.py
@@ -147,13 +147,14 @@ class AsciiDoc:
last_line = ""
for line in infp:
- if line.strip() == '// QUTE_WEB_HIDE':
+ line = line.rstrip()
+ if line == '// QUTE_WEB_HIDE':
assert not hidden
hidden = True
- elif line.strip() == '// QUTE_WEB_HIDE_END':
+ elif line == '// QUTE_WEB_HIDE_END':
assert hidden
hidden = False
- elif line == "The Compiler <mail@qutebrowser.org>\n":
+ elif line == "The Compiler <mail@qutebrowser.org>":
continue
elif re.fullmatch(r':\w+:.*', line):
# asciidoc field
@@ -163,16 +164,16 @@ class AsciiDoc:
if re.fullmatch(r'=+', line):
line = line.replace('=', '-')
found_title = True
- title = last_line.rstrip('\n') + " | qutebrowser\n"
+ title = last_line + " | qutebrowser\n"
title += "=" * (len(title) - 1)
elif re.fullmatch(r'= .+', line):
line = '==' + line[1:]
found_title = True
- title = last_line.rstrip('\n') + " | qutebrowser\n"
+ title = last_line + " | qutebrowser\n"
title += "=" * (len(title) - 1)
if not hidden:
- outfp.write(line.replace(".asciidoc[", ".html["))
+ outfp.write(line.replace(".asciidoc[", ".html[") + '\n')
last_line = line
current_lines = outfp.getvalue()
diff --git a/scripts/testbrowser_cpp/webengine/main.cpp b/scripts/testbrowser/cpp/webengine/main.cpp
index 311432e92..311432e92 100644
--- a/scripts/testbrowser_cpp/webengine/main.cpp
+++ b/scripts/testbrowser/cpp/webengine/main.cpp
diff --git a/scripts/testbrowser_cpp/webengine/testbrowser.pro b/scripts/testbrowser/cpp/webengine/testbrowser.pro
index 12a1cf7f6..12a1cf7f6 100644
--- a/scripts/testbrowser_cpp/webengine/testbrowser.pro
+++ b/scripts/testbrowser/cpp/webengine/testbrowser.pro
diff --git a/scripts/testbrowser_cpp/webkit/main.cpp b/scripts/testbrowser/cpp/webkit/main.cpp
index 06c3d1a4f..06c3d1a4f 100644
--- a/scripts/testbrowser_cpp/webkit/main.cpp
+++ b/scripts/testbrowser/cpp/webkit/main.cpp
diff --git a/scripts/testbrowser_cpp/webkit/testbrowser.pro b/scripts/testbrowser/cpp/webkit/testbrowser.pro
index 59f55ddfc..59f55ddfc 100644
--- a/scripts/testbrowser_cpp/webkit/testbrowser.pro
+++ b/scripts/testbrowser/cpp/webkit/testbrowser.pro
diff --git a/scripts/testbrowser/testbrowser_webengine.py b/scripts/testbrowser/testbrowser_webengine.py
new file mode 100755
index 000000000..e6353dc23
--- /dev/null
+++ b/scripts/testbrowser/testbrowser_webengine.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2014-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
+#
+# This file is part of qutebrowser.
+#
+# qutebrowser is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# qutebrowser is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
+
+"""Very simple browser for testing purposes."""
+
+import sys
+import argparse
+
+from PyQt5.QtCore import QUrl
+from PyQt5.QtWidgets import QApplication
+from PyQt5.QtWebEngineWidgets import QWebEngineView
+
+
+def parse_args():
+ """Parse commandline arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('url', help='The URL to open')
+ return parser.parse_known_args()[0]
+
+
+if __name__ == '__main__':
+ args = parse_args()
+ app = QApplication(sys.argv)
+ wv = QWebEngineView()
+
+ wv.loadStarted.connect(lambda: print("Loading started"))
+ wv.loadProgress.connect(lambda p: print("Loading progress: {}%".format(p)))
+ wv.loadFinished.connect(lambda: print("Loading finished"))
+
+ wv.load(QUrl.fromUserInput(args.url))
+ wv.show()
+
+ app.exec_()
diff --git a/scripts/testbrowser.py b/scripts/testbrowser/testbrowser_webkit.py
index fbe48c451..7c7081f18 100755
--- a/scripts/testbrowser.py
+++ b/scripts/testbrowser/testbrowser_webkit.py
@@ -25,16 +25,8 @@ import argparse
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
-
-try:
- from PyQt5.QtWebKitWidgets import QWebView
-except ImportError:
- QWebView = None
-
-try:
- from PyQt5.QtWebEngineWidgets import QWebEngineView
-except ImportError:
- QWebEngineView = None
+from PyQt5.QtWebKit import QWebSettings
+from PyQt5.QtWebKitWidgets import QWebView
def parse_args():
@@ -43,39 +35,19 @@ def parse_args():
parser.add_argument('url', help='The URL to open')
parser.add_argument('--plugins', '-p', help='Enable plugins',
default=False, action='store_true')
- if QWebEngineView is not None:
- parser.add_argument('--webengine', help='Use QtWebEngine',
- default=False, action='store_true')
return parser.parse_known_args()[0]
if __name__ == '__main__':
args = parse_args()
app = QApplication(sys.argv)
-
- if QWebView is None and QWebEngineView is None:
- print("Found no suitable backend to run with!")
- sys.exit(1)
- elif QWebView is None and not args.webengine:
- print("Using QtWebEngine because QtWebKit is unavailable")
- wv = QWebEngineView()
- using_webengine = True
- elif args.webengine:
- if QWebEngineView is None:
- print("Requested QtWebEngine, but it could not be imported!")
- sys.exit(1)
- wv = QWebEngineView()
- using_webengine = True
- else:
- wv = QWebView()
- using_webengine = False
+ wv = QWebView()
wv.loadStarted.connect(lambda: print("Loading started"))
wv.loadProgress.connect(lambda p: print("Loading progress: {}%".format(p)))
wv.loadFinished.connect(lambda: print("Loading finished"))
- if args.plugins and not using_webengine:
- from PyQt5.QtWebKit import QWebSettings
+ if args.plugins:
wv.settings().setAttribute(QWebSettings.PluginsEnabled, True)
wv.load(QUrl.fromUserInput(args.url))
diff --git a/tests/end2end/features/marks.feature b/tests/end2end/features/marks.feature
index 605bd3971..f7da07255 100644
--- a/tests/end2end/features/marks.feature
+++ b/tests/end2end/features/marks.feature
@@ -86,7 +86,7 @@ Feature: Setting positional marks
And I wait until the scroll position changed to 10/10
Then the page should be scrolled to 10 10
- @qtwebengine_todo: Does not emit loaded signal for fragments?
+ @qtwebengine_skip: Does not emit loaded signal for fragments?
Scenario: Jumping back after following a link
When I hint with args "links normal" and follow s
And I wait until data/marks.html#bottom is loaded
diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py
index 3f5e727e6..a2947e5af 100644
--- a/tests/end2end/fixtures/quteprocess.py
+++ b/tests/end2end/fixtures/quteprocess.py
@@ -44,9 +44,9 @@ from end2end.fixtures import testprocess
instance_counter = itertools.count()
-def is_ignored_qt_message(message):
+def is_ignored_qt_message(pytestconfig, message):
"""Check if the message is listed in qt_log_ignore."""
- regexes = pytest.config.getini('qt_log_ignore')
+ regexes = pytestconfig.getini('qt_log_ignore')
for regex in regexes:
if re.search(regex, message):
return True
@@ -207,7 +207,7 @@ class LogLine(testprocess.Line):
expected: Whether the message was expected or not.
"""
- def __init__(self, data):
+ def __init__(self, pytestconfig, data):
super().__init__(data)
try:
line = json.loads(data)
@@ -229,7 +229,7 @@ class LogLine(testprocess.Line):
self.traceback = line.get('traceback')
self.message = line['message']
- self.expected = is_ignored_qt_message(self.message)
+ self.expected = is_ignored_qt_message(pytestconfig, self.message)
self.use_color = False
def __str__(self):
@@ -299,14 +299,13 @@ class QuteProc(testprocess.Process):
'message']
def __init__(self, request, *, parent=None):
- super().__init__(parent)
+ super().__init__(request, parent)
self._ipc_socket = None
self.basedir = None
self._focus_ready = False
self._load_ready = False
self._instance_id = next(instance_counter)
self._run_counter = itertools.count()
- self.request = request
def _is_ready(self, what):
"""Called by _parse_line if loading/focusing is done.
@@ -372,11 +371,11 @@ class QuteProc(testprocess.Process):
def _parse_line(self, line):
try:
- log_line = LogLine(line)
+ log_line = LogLine(self.request.config, line)
except testprocess.InvalidLine:
if not line.strip():
return None
- elif (is_ignored_qt_message(line) or
+ elif (is_ignored_qt_message(self.request.config, line) or
is_ignored_lowlevel_message(line) or
is_ignored_chromium_message(line) or
self.request.node.get_marker('no_invalid_lines')):
diff --git a/tests/end2end/fixtures/test_quteprocess.py b/tests/end2end/fixtures/test_quteprocess.py
index f8241397f..aa3fb5857 100644
--- a/tests/end2end/fixtures/test_quteprocess.py
+++ b/tests/end2end/fixtures/test_quteprocess.py
@@ -45,6 +45,10 @@ class FakeConfig:
'--qute-delay': 0,
'--color': True,
'--verbose': False,
+ '--capture': None,
+ }
+ INI = {
+ 'qt_log_ignore': [],
}
def __init__(self):
@@ -53,6 +57,9 @@ class FakeConfig:
def getoption(self, name):
return self.ARGS[name]
+ def getini(self, name):
+ return self.INI[name]
+
class FakeNode:
@@ -222,8 +229,8 @@ def test_quteprocess_quitting(qtbot, quteproc_process):
{'category': 'py.warnings'},
id='resourcewarning'),
])
-def test_log_line_parse(data, attrs):
- line = quteprocess.LogLine(data)
+def test_log_line_parse(pytestconfig, data, attrs):
+ line = quteprocess.LogLine(pytestconfig, data)
for name, expected in attrs.items():
actual = getattr(line, name)
assert actual == expected, name
@@ -283,9 +290,10 @@ def test_log_line_parse(data, attrs):
'\033[36mfoo bar:qux:10\033[0m \033[37mquux\033[0m',
id='expected error colorized'),
])
-def test_log_line_formatted(data, colorized, expect_error, expected):
+def test_log_line_formatted(pytestconfig,
+ data, colorized, expect_error, expected):
line = json.dumps(data)
- record = quteprocess.LogLine(line)
+ record = quteprocess.LogLine(pytestconfig, line)
record.expected = expect_error
ts = datetime.datetime.fromtimestamp(data['created']).strftime('%H:%M:%S')
ts += '.{:03.0f}'.format(data['msecs'])
@@ -293,9 +301,9 @@ def test_log_line_formatted(data, colorized, expect_error, expected):
assert record.formatted_str(colorized=colorized) == expected
-def test_log_line_no_match():
+def test_log_line_no_match(pytestconfig):
with pytest.raises(testprocess.InvalidLine):
- quteprocess.LogLine("Hello World!")
+ quteprocess.LogLine(pytestconfig, "Hello World!")
class TestClickElementByText:
diff --git a/tests/end2end/fixtures/test_testprocess.py b/tests/end2end/fixtures/test_testprocess.py
index 1811b7fb1..6ceb032af 100644
--- a/tests/end2end/fixtures/test_testprocess.py
+++ b/tests/end2end/fixtures/test_testprocess.py
@@ -51,8 +51,8 @@ class PythonProcess(testprocess.Process):
"""A testprocess which runs the given Python code."""
- def __init__(self):
- super().__init__()
+ def __init__(self, request):
+ super().__init__(request)
self.proc.setReadChannel(QProcess.StandardOutput)
self.code = None
@@ -103,22 +103,22 @@ class NoReadyPythonProcess(PythonProcess):
@pytest.fixture
-def pyproc():
- proc = PythonProcess()
+def pyproc(request):
+ proc = PythonProcess(request)
yield proc
proc.terminate()
@pytest.fixture
-def quit_pyproc():
- proc = QuitPythonProcess()
+def quit_pyproc(request):
+ proc = QuitPythonProcess(request)
yield proc
proc.terminate()
@pytest.fixture
-def noready_pyproc():
- proc = NoReadyPythonProcess()
+def noready_pyproc(request):
+ proc = NoReadyPythonProcess(request)
yield proc
proc.terminate()
@@ -149,9 +149,9 @@ def test_process_never_started(qtbot, quit_pyproc):
quit_pyproc.after_test()
-def test_wait_signal_raising(qtbot):
+def test_wait_signal_raising(request, qtbot):
"""testprocess._wait_signal should raise by default."""
- proc = testprocess.Process()
+ proc = testprocess.Process(request)
with pytest.raises(qtbot.TimeoutError):
with proc._wait_signal(proc.proc.started, timeout=0):
pass
diff --git a/tests/end2end/fixtures/testprocess.py b/tests/end2end/fixtures/testprocess.py
index ac220af58..3fb259e47 100644
--- a/tests/end2end/fixtures/testprocess.py
+++ b/tests/end2end/fixtures/testprocess.py
@@ -73,12 +73,11 @@ class Line:
waited_for = attr.ib(False)
-def _render_log(data, threshold=100):
+def _render_log(data, *, verbose, threshold=100):
"""Shorten the given log without -v and convert to a string."""
data = [str(d) for d in data]
is_exception = any('Traceback (most recent call last):' in line or
'Uncaught exception' in line for line in data)
- verbose = pytest.config.getoption('--verbose')
if len(data) > threshold and not verbose and not is_exception:
msg = '[{} lines suppressed, use -v to show]'.format(
len(data) - threshold)
@@ -105,15 +104,17 @@ def pytest_runtest_makereport(item, call):
# is actually a tuple. This is handled similarily in pytest-qt too.
return
- if pytest.config.getoption('--capture') == 'no':
+ if item.config.getoption('--capture') == 'no':
# Already printed live
return
+ verbose = item.config.getoption('--verbose')
if quteproc_log is not None:
report.longrepr.addsection("qutebrowser output",
- _render_log(quteproc_log))
+ _render_log(quteproc_log, verbose=verbose))
if server_log is not None:
- report.longrepr.addsection("server output", _render_log(server_log))
+ report.longrepr.addsection("server output",
+ _render_log(server_log, verbose=verbose))
class Process(QObject):
@@ -128,6 +129,7 @@ class Process(QObject):
_started: Whether the process was ever started.
proc: The QProcess for the underlying process.
exit_expected: Whether the process is expected to quit.
+ request: The request object for the current test.
Signals:
ready: Emitted when the server finished starting up.
@@ -138,8 +140,9 @@ class Process(QObject):
new_data = pyqtSignal(object)
KEYS = ['data']
- def __init__(self, parent=None):
+ def __init__(self, request, parent=None):
super().__init__(parent)
+ self.request = request
self.captured_log = []
self._started = False
self._invalid = []
@@ -150,7 +153,7 @@ class Process(QObject):
def _log(self, line):
"""Add the given line to the captured log output."""
- if pytest.config.getoption('--capture') == 'no':
+ if self.request.config.getoption('--capture') == 'no':
print(line)
self.captured_log.append(line)
@@ -225,6 +228,8 @@ class Process(QObject):
"""Start the process and wait until it started."""
self._start(args, env=env)
self._started = True
+ verbose = self.request.config.getoption('--verbose')
+
timeout = 60 if 'CI' in os.environ else 20
for _ in range(timeout):
with self._wait_signal(self.ready, timeout=1000,
@@ -236,14 +241,15 @@ class Process(QObject):
return
# _start ensures it actually started, but it might quit shortly
# afterwards
- raise ProcessExited('\n' + _render_log(self.captured_log))
+ raise ProcessExited('\n' + _render_log(self.captured_log,
+ verbose=verbose))
if blocker.signal_triggered:
self._after_start()
return
raise WaitForTimeout("Timed out while waiting for process start.\n" +
- _render_log(self.captured_log))
+ _render_log(self.captured_log, verbose=verbose))
def _start(self, args, env):
"""Actually start the process."""
diff --git a/tests/end2end/fixtures/webserver.py b/tests/end2end/fixtures/webserver.py
index a40c62015..93ef04f03 100644
--- a/tests/end2end/fixtures/webserver.py
+++ b/tests/end2end/fixtures/webserver.py
@@ -137,8 +137,8 @@ class WebserverProcess(testprocess.Process):
KEYS = ['verb', 'path']
- def __init__(self, script, parent=None):
- super().__init__(parent)
+ def __init__(self, request, script, parent=None):
+ super().__init__(request, parent)
self._script = script
self.port = utils.random_port()
self.new_data.connect(self.new_request)
@@ -174,9 +174,9 @@ class WebserverProcess(testprocess.Process):
@pytest.fixture(scope='session', autouse=True)
-def server(qapp):
+def server(qapp, request):
"""Fixture for an server object which ensures clean setup/teardown."""
- server = WebserverProcess('webserver_sub')
+ server = WebserverProcess(request, 'webserver_sub')
server.start()
yield server
server.terminate()
@@ -198,7 +198,7 @@ def ssl_server(request, qapp):
This needs to be explicitly used in a test, and overwrites the server log
used in that test.
"""
- server = WebserverProcess('webserver_sub_ssl')
+ server = WebserverProcess(request, 'webserver_sub_ssl')
request.node._server_log = server.captured_log
server.start()
yield server
diff --git a/tests/unit/completion/test_completer.py b/tests/unit/completion/test_completer.py
index e25d4e5d1..4b39b7032 100644
--- a/tests/unit/completion/test_completer.py
+++ b/tests/unit/completion/test_completer.py
@@ -190,6 +190,7 @@ def _set_cmd_prompt(cmd, txt):
(':gibberish nonesense |', None, '', []),
('/:help|', None, '', []),
('::bind|', 'command', ':bind', []),
+ (':-w open |', None, '', []),
])
def test_update_completion(txt, kind, pattern, pos_args, status_command_stub,
completer_obj, completion_widget_stub, config_stub,
diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
index 32a7a8119..d8bf73700 100644
--- a/tests/unit/config/test_config.py
+++ b/tests/unit/config/test_config.py
@@ -385,7 +385,7 @@ class TestConfig:
def test_get(self, conf):
"""Test conf.get() with a QColor (where get/get_obj is different)."""
- assert conf.get('colors.completion.fg') == QColor('white')
+ assert conf.get('colors.completion.category.fg') == QColor('white')
@pytest.mark.parametrize('value', [{}, {'normal': {'a': 'nop'}}])
def test_get_bindings(self, config_stub, conf, value):
@@ -400,7 +400,7 @@ class TestConfig:
assert not conf._mutables
def test_get_obj_simple(self, conf):
- assert conf.get_obj('colors.completion.fg') == 'white'
+ assert conf.get_obj('colors.completion.category.fg') == 'white'
@pytest.mark.parametrize('option', ['content.headers.custom',
'keyhint.blacklist',