Compare commits

...

49 Commits

Author SHA1 Message Date
Florian Bruhin
e9e411311a Remove unused import 2017-10-09 10:08:45 +02:00
Florian Bruhin
33b71ee937 Use develop branch of PyInstaller
https://github.com/pyinstaller/pyinstaller/pull/2519 was merged.
Fixes #2880

(cherry picked from commit ba04822388)
2017-10-09 08:46:31 +02:00
Florian Bruhin
d166587f3d Release v0.11.1 2017-10-09 08:30:18 +02:00
Florian Bruhin
dd663df35f Update changelog from master 2017-10-09 08:30:03 +02:00
Florian Bruhin
9d292128d2 Remove test_upgrade_version
This is the last v0.11.x release
2017-10-09 08:24:56 +02:00
Florian Bruhin
f3eb5dbb66 Revert "Only emit perc_changed signal when the percentage actually changed"
This reverts commit 3eaad092b8.
This breaks various end2end test relying on getting log messages for scrolling.
2017-10-06 10:17:13 +02:00
Florian Bruhin
3eaad092b8 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

(cherry picked from commit 1d50c2c39a)
2017-10-06 08:54:52 +02:00
Florian Bruhin
38bccd4fdd Remove unused import
(cherry picked from commit 629f6a6876)
2017-10-04 11:16:18 +02:00
Florian Bruhin
9a5668f7a0 Fix test_version after OpenGL removal 2017-10-04 09:32:33 +02:00
Florian Bruhin
48023e7b1d Use ctypes instead of PyOpenGL for QtWebEngine Nvidia workaround
Normally a dependency change like this wouldn't appear on a stable branch, but
it looks like multiple people have issues with importing PyOpenGL:

Traceback (most recent call last):
  ...
  File "/usr/lib/python3/dist-packages/qutebrowser/browser/webengine/webenginesettings.py", line 208, in init
    from OpenGL import GL  # pylint: disable=unused-variable
  File "/usr/lib/python3/dist-packages/OpenGL/GL/__init__.py", line 3, in <module>
    from OpenGL.GL.VERSION.GL_1_1 import *
  File "/usr/lib/python3/dist-packages/OpenGL/GL/VERSION/GL_1_1.py", line 10, in <module>
    from OpenGL import platform, constants, constant, arrays
  File "/usr/lib/python3/dist-packages/OpenGL/arrays/__init__.py", line 22, in <module>
    formathandler.FormatHandler.loadAll()
  File "/usr/lib/python3/dist-packages/OpenGL/arrays/formathandler.py", line 28, in loadAll
    cls.loadPlugin( entrypoint )
  File "/usr/lib/python3/dist-packages/OpenGL/arrays/formathandler.py", line 35, in loadPlugin
    plugin_class = entrypoint.load()
  File "/usr/lib/python3/dist-packages/OpenGL/plugins.py", line 14, in load
    return importByName( self.import_path )
  File "/usr/lib/python3/dist-packages/OpenGL/plugins.py", line 28, in importByName
    module = __import__( ".".join(moduleName), {}, {}, moduleName)
  File "/usr/lib/python3/dist-packages/OpenGL/arrays/vbo.py", line 430, in <module>
    def mapVBO( vbo, access=GL.GL_READ_WRITE ):
AttributeError: module 'OpenGL.GL' has no attribute 'GL_READ_WRITE'

Fixes #2821

(cherry picked from commit a942613d7f)
2017-10-04 06:54:08 +02:00
Florian Bruhin
74e1b1ec26 Make userscripts work on both Python 2 and 3
(cherry picked from commit dca962ca03)
2017-09-29 13:39:09 +02:00
Florian Bruhin
cfe7386f20 eslint: Turn off function-paren-newline 2017-09-10 12:50:25 +02:00
Jay Kamat
12b00dad44 Enforce a minimum size for non-pinned tabs
Closes #2826
2017-09-10 01:52:55 +02:00
Jay Kamat
ccf3cb6d7c Restructure minimum tab size behavior 2017-09-10 01:52:55 +02:00
Jay Kamat
fcd8be5b68 Test for saving a session with --only-active-window 2017-08-28 07:58:32 +02:00
cryzed
259d08ba29 :save-session --only-active-window implies --with-private for private windows 2017-08-28 07:58:32 +02:00
Florian Bruhin
9d65039b35 Ignore a new Geoclue error during tests 2017-08-08 22:01:36 +02:00
Florian Bruhin
e50b7b65a4 version.distribution(): Handle Funtoo 2017-08-08 21:29:07 +02:00
Florian Bruhin
1aefaaf7c7 Fix tests for QProcess changes 2017-07-23 22:11:01 +02:00
Florian Bruhin
4da89139d1 Disallow :spawn -u -d
(cherry picked from commit efe6719f4f354348e7db6f77dc22c319850de5d4)
2017-07-23 21:34:56 +02:00
Florian Bruhin
3f04c94047 Fix error message with :spawn -d
(cherry picked from commit c951b71307e666cb6a02c1c0e9f54131ac61266a)
2017-07-23 21:34:50 +02:00
Florian Bruhin
00f456fd7f Fix the "try again" button on error pages
Fixes #2810

(cherry picked from commit 5c367e7ab2)
2017-07-13 17:28:06 +02:00
Jay Kamat
00d5aa6b22 Refactor tab_close_prompt_if_pinned
Now it lives in tabbedbrowser.py as method instead of a static function

(cherry picked from commit 7dfca60893)
2017-07-13 11:03:28 +02:00
Jay Kamat
91c5eff2c9 Prompt when closing a pinned tab via the mouse
Closes #2761

(cherry picked from commit 4d1dbe11e8)
2017-07-13 11:03:22 +02:00
Florian Bruhin
0d704043ec Fix printing on macOS
Fixes #2798

(cherry picked from commit 53620ecce4)
2017-07-12 07:43:18 +02:00
Florian Bruhin
b11abb028b Remove unused import
(cherry picked from commit cfb169b5f0)
2017-07-09 12:40:30 +02:00
Florian Bruhin
474e904409 Move OpenGL workaround import
OpenGL.GL gets imported in earlyinit already anyways, so we can move everything
there.

(cherry picked from commit 9e7f2e470f)
2017-07-09 11:57:48 +02:00
Florian Bruhin
cc05cb1c67 Recommend QT_XCB_FORCE_SOFTWARE_OPENGL
This won't disable OpenGL for stuff started from qutebrowser.

See #2368.

(cherry picked from commit fcf5158258)
2017-07-08 17:37:44 +02:00
Florian Bruhin
e10ce420ab 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.

(cherry picked from commit b81474d2fd)
2017-07-08 17:34:41 +02:00
Florian Bruhin
5b5adc1a00 Fix :restart with private browsing mode
(cherry picked from commit 0de0bbfa71)
2017-07-08 10:46:57 +02:00
Florian Bruhin
63fa412882 Fix build_release.py 2017-07-07 15:18:14 +02:00
Florian Bruhin
47ad8f212e build_release: Fail GitHub uploads early 2017-07-07 14:28:44 +02:00
Florian Bruhin
7ac27fdd85 Add Gentoo instructions to backend warning 2017-07-06 00:40:58 +02:00
Florian Bruhin
d4baeb2ada Merge branch 'pr/2747' into v0.11.x 2017-07-05 22:15:23 +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
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
Marius
df6b8b7ff5 Update tabwidget.py 2017-06-21 09:03:15 +02: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
30 changed files with 209 additions and 118 deletions

View File

@@ -14,6 +14,20 @@ This project adheres to http://semver.org/[Semantic Versioning].
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
v0.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
-------
@@ -183,7 +197,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
~~~~~~~
@@ -485,7 +499,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
------
@@ -848,7 +862,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
@@ -923,7 +937,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
@@ -1034,7 +1048,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.
@@ -1132,7 +1146,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.
@@ -1152,7 +1166,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.
@@ -1288,7 +1302,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
@@ -1324,7 +1338,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

@@ -699,7 +699,7 @@ qutebrowser release
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)
* Windows: Run `C:\Python36-32\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

View File

@@ -108,7 +108,6 @@ The following software and libraries are required to run qutebrowser:
* http://jinja.pocoo.org/[jinja2]
* http://pygments.org/[pygments]
* http://pyyaml.org/wiki/PyYAML[PyYAML]
* http://pyopengl.sourceforge.net/[PyOpenGL] when using QtWebEngine
The following libraries are optional and provide a better user experience:
@@ -193,6 +192,7 @@ Contributors, sorted by the number of commits in descending order:
* knaggita
* Oliver Caldwell
* Nikolay Amiantov
* Marius
* Julian Weigt
* Tomasz Kramkowski
* Sebastian Frysztak
@@ -217,7 +217,6 @@ Contributors, sorted by the number of commits in descending order:
* Michał Góral
* Michael Ilsaas
* Martin Zimmermann
* Marius
* Link
* Jussi Timperi
* Cosmin Popescu

View File

@@ -41,7 +41,7 @@ a = Analysis(['../qutebrowser/__main__.py'],
pathex=['misc'],
binaries=None,
datas=get_data_files(),
hiddenimports=['PyQt5.QtOpenGL'],
hiddenimports=['PyQt5.QtOpenGL', 'PyQt5._QOpenGLFunctions_2_0'],
hookspath=[],
runtime_hooks=[],
excludes=['tkinter'],

View File

@@ -1,3 +1,3 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-e git+https://github.com/xoviat/pyinstaller.git@qtweb#egg=PyInstaller
-e git+https://github.com/pyinstaller/pyinstaller.git@develop#egg=PyInstaller

View File

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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Executes python-readability on current page and opens the summary as new tab.
#

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

@@ -46,6 +46,7 @@ qt_log_ignore =
^QGeoclueMaster error creating GeoclueMasterClient\.
^Geoclue error: Process org\.freedesktop\.Geoclue\.Master exited with status 127
^QDBusConnection: name 'org.freedesktop.Geoclue.Master' had owner '' but we thought it was ':1.1'
^Failed to create Geoclue client interface. Geoclue error: org\.freedesktop\.DBus\.Error\.Disconnected
^QObject::connect: Cannot connect \(null\)::stateChanged\(QNetworkSession::State\) to QNetworkReplyHttpImpl::_q_networkSessionStateChanged\(QNetworkSession::State\)
^QXcbClipboard: Cannot transfer data, no data available
^load glyph failed

View File

@@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2017 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version_info__ = (0, 11, 0)
__version_info__ = (0, 11, 1)
__version__ = '.'.join(str(e) for e in __version_info__)
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."

View File

@@ -634,7 +634,7 @@ class Quitter:
# 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)
# Open a new process and immediately shutdown the existing one
try:
args, cwd = self._get_restart_args(pages, session)

View File

@@ -20,11 +20,12 @@
"""Command dispatcher for TabbedBrowser."""
import os
import sys
import os.path
import shlex
import functools
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
@@ -227,19 +228,6 @@ class CommandDispatcher:
self._tabbed_browser.close_tab(tab)
tabbar.setSelectionBehaviorOnRemove(old_selection_behavior)
def _tab_close_prompt_if_pinned(self, tab, force, yes_action):
"""Helper method for tab_close.
If tab is pinned, prompt. If everything is good, run yes_action.
"""
if tab.data.pinned and not force:
message.confirm_async(
title='Pinned Tab',
text="Are you sure you want to close a pinned tab?",
yes_action=yes_action, default=False)
else:
yes_action()
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', count=True)
def tab_close(self, prev=False, next_=False, opposite=False,
@@ -260,7 +248,7 @@ class CommandDispatcher:
close = functools.partial(self._tab_close, tab, prev,
next_, opposite)
self._tab_close_prompt_if_pinned(tab, force, close)
self._tabbed_browser.tab_close_prompt_if_pinned(tab, force, close)
@cmdutils.register(instance='command-dispatcher', scope='window',
name='tab-pin')
@@ -436,9 +424,18 @@ class CommandDispatcher:
message.error("Printing failed!")
diag.deleteLater()
def do_print():
"""Called when the dialog was closed."""
tab.printing.to_printer(diag.printer(), print_callback)
diag = QPrintDialog(tab)
diag.open(lambda: tab.printing.to_printer(diag.printer(),
print_callback))
if sys.platform == 'darwin':
# 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')
@@ -918,8 +915,9 @@ class CommandDispatcher:
if not force:
for i, tab in enumerate(self._tabbed_browser.widgets()):
if _to_close(i) and tab.data.pinned:
self._tab_close_prompt_if_pinned(
tab, force,
self._tabbed_browser.tab_close_prompt_if_pinned(
tab,
force,
lambda: self.tab_only(
prev=prev, next_=next_, force=True))
return
@@ -1165,6 +1163,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:

View File

@@ -28,7 +28,9 @@ Module attributes:
"""
import os
import logging
import sys
import ctypes
import ctypes.util
from PyQt5.QtGui import QFont
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
@@ -200,12 +202,10 @@ def init(args):
if args.enable_webengine_inspector:
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
# Workaround for a black screen with some setups
# https://github.com/spyder-ide/spyder/issues/3226
if not os.environ.get('QUTE_NO_OPENGL_WORKAROUND'):
# Hide "No OpenGL_accelerate module loaded: ..." message
logging.getLogger('OpenGL.acceleratesupport').propagate = False
from OpenGL import GL # pylint: disable=unused-variable
# WORKAROUND for
# https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826
if sys.platform == 'linux':
ctypes.CDLL(ctypes.util.find_library("GL"), mode=ctypes.RTLD_GLOBAL)
_init_profiles()

View File

@@ -51,12 +51,13 @@ def init():
global _qute_scheme_handler
app = QApplication.instance()
software_rendering = os.environ.get('LIBGL_ALWAYS_SOFTWARE') == '1'
software_rendering = (os.environ.get('LIBGL_ALWAYS_SOFTWARE') == '1' or
'QT_XCB_FORCE_SOFTWARE_OPENGL' in os.environ)
if version.opengl_vendor() == 'nouveau' and not software_rendering:
# FIXME:qtwebengine display something more sophisticated here
raise browsertab.WebTabError(
"QtWebEngine is not supported with Nouveau graphics (unless "
"LIBGL_ALWAYS_SOFTWARE is set as environment variable).")
"QT_XCB_FORCE_SOFTWARE_OPENGL is set as environment variable).")
log.init.debug("Initializing qute://* handler...")
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)

View File

@@ -70,6 +70,8 @@ the <span class="mono">qute://settings</span> page or caret browsing).</span>
{{ install_webengine('qt5-qtwebengine') }}
{% elif distribution.parsed == Distribution.opensuse %}
{{ install_webengine('libqt5-qtwebengine') }}
{% elif distribution.parsed == Distribution.gentoo %}
{{ install_webengine('dev-qt/qtwebengine') }}
{% else %}
{{ unknown_system() }}
{% endif %}

View File

@@ -61,7 +61,7 @@ li {
{{ super() }}
function tryagain()
{
location.href = url;
location.href = "{{ url }}";
}
{% endblock %}

View File

@@ -43,3 +43,4 @@ rules:
array-bracket-newline: "off"
array-element-newline: "off"
no-multi-spaces: ["error", {"ignoreEOLComments": true}]
function-paren-newline: "off"

View File

@@ -232,6 +232,19 @@ class TabbedBrowser(tabwidget.TabWidget):
for tab in self.widgets():
self._remove_tab(tab)
def tab_close_prompt_if_pinned(self, tab, force, yes_action):
"""Helper method for tab_close.
If tab is pinned, prompt. If everything is good, run yes_action.
"""
if tab.data.pinned and not force:
message.confirm_async(
title='Pinned Tab',
text="Are you sure you want to close a pinned tab?",
yes_action=yes_action, default=False)
else:
yes_action()
def close_tab(self, tab, *, add_undo=True):
"""Close a tab.
@@ -366,7 +379,8 @@ class TabbedBrowser(tabwidget.TabWidget):
log.webview.debug("Got invalid tab {} for index {}!".format(
tab, idx))
return
self.close_tab(tab)
self.tab_close_prompt_if_pinned(
tab, False, lambda: self.close_tab(tab))
@pyqtSlot(browsertab.AbstractTab)
def on_window_close_requested(self, widget):

View File

@@ -503,10 +503,6 @@ class TabBar(QTabBar):
# We return it directly rather than setting `size' because we don't
# want to ensure it's valid in this special case.
return QSize()
elif self.count() * minimum_size.width() > self.width():
# If we don't have enough space, we return the minimum size so we
# get scroll buttons as soon as needed.
size = minimum_size
else:
tab_width_pinned_conf = config.get('tabs', 'pinned-width')
@@ -517,19 +513,21 @@ class TabBar(QTabBar):
no_pinned_count = self.count() - self.pinned_count
pinned_width = tab_width_pinned_conf * self.pinned_count
no_pinned_width = self.width() - pinned_width
# Prevent any tabs from being smaller than the min size
no_pinned_width = max(self.width() - pinned_width,
minimum_size.width() * no_pinned_count)
if pinned:
width = tab_width_pinned_conf
else:
# If we *do* have enough space, tabs should occupy the whole
# window width. If there are pinned tabs their size will be
# subtracted from the total window width.
# During shutdown the self.count goes down,
# but the self.pinned_count not - this generates some odd
# Tabs should attempt to occupy the whole window width. If
# there are pinned tabs their size will be subtracted from the
# total window width. During shutdown the self.count goes
# down, but the self.pinned_count not - this generates some odd
# behavior. To avoid this we compare self.count against
# self.pinned_count.
# self.pinned_count. If we end up having too little space, we
# set the minimum size below.
if self.pinned_count > 0 and no_pinned_count > 0:
width = no_pinned_width / no_pinned_count
else:
@@ -541,6 +539,10 @@ class TabBar(QTabBar):
index < no_pinned_width % no_pinned_count):
width += 1
# If we don't have enough space, we return the minimum size so we
# get scroll buttons as soon as needed.
width = max(width, minimum_size.width())
size = QSize(width, height)
qtutils.ensure_valid(size)
return size
@@ -761,6 +763,17 @@ class TabBarStyle(QCommonStyle):
rct = super().subElementRect(sr, opt, widget)
return rct
else:
try:
# We need this so the left scroll button is aligned properly.
# Otherwise, empty space will be shown after the last tab even
# though the button width is set to 0
#
# QStyle.SE_TabBarScrollLeftButton was added in Qt 5.7
if sr == QStyle.SE_TabBarScrollLeftButton:
return super().subElementRect(sr, opt, widget)
except AttributeError:
pass
return self._style.subElementRect(sr, opt, widget)
def _tab_layout(self, opt):

View File

@@ -342,7 +342,6 @@ def check_libraries(backend):
modules['PyQt5.QtWebEngineWidgets'] = _missing_str("QtWebEngine",
webengine=True)
modules['PyQt5.QtOpenGL'] = _missing_str("PyQt5.QtOpenGL")
modules['OpenGL'] = _missing_str("PyOpenGL")
else:
assert backend == 'webkit'
modules['PyQt5.QtWebKit'] = _missing_str("PyQt5.QtWebKit")

View File

@@ -154,8 +154,8 @@ class GUIProcess(QObject):
log.procs.debug("Process started.")
self._started = True
else:
message.error("Error while spawning {}: {}.".format(
self._what, self._proc.error()))
message.error("Error while spawning {}: {}".format(
self._what, ERROR_STRINGS[self._proc.error()]))
def exit_status(self):
return self._proc.exitStatus()

View File

@@ -492,7 +492,7 @@ class SessionManager(QObject):
try:
if only_active_window:
name = self.save(name, only_window=win_id,
with_private=with_private)
with_private=True)
else:
name = self.save(name, with_private=with_private)
except SessionError as e:

View File

@@ -81,6 +81,8 @@ def distribution():
return None
pretty = info.get('PRETTY_NAME', 'Unknown')
if pretty == 'Linux': # Thanks, Funtoo
pretty = info.get('NAME', pretty)
if 'VERSION_ID' in info:
dist_version = pkg_resources.parse_version(info['VERSION_ID'])
@@ -88,8 +90,11 @@ def distribution():
dist_version = None
dist_id = info.get('ID', None)
id_mappings = {
'funtoo': 'gentoo', # does not have ID_LIKE=gentoo
}
try:
parsed = Distribution[dist_id]
parsed = Distribution[id_mappings.get(dist_id, dist_id)]
except KeyError:
parsed = Distribution.unknown
@@ -186,7 +191,6 @@ def _module_versions():
('yaml', ['__version__']),
('cssutils', ['__version__']),
('typing', []),
('OpenGL', ['__version__']),
('PyQt5.QtWebEngineWidgets', []),
('PyQt5.QtWebKitWidgets', []),
])

View File

@@ -7,4 +7,3 @@ MarkupSafe==1.0
Pygments==2.2.0
pyPEG2==2.15.2
PyYAML==3.12
PyOpenGL==3.1.0

View File

@@ -64,7 +64,7 @@ def call_tox(toxenv, *args, python=sys.executable):
env['PYTHON'] = python
env['PATH'] = os.environ['PATH'] + os.pathsep + os.path.dirname(python)
subprocess.check_call(
[sys.executable, '-m', 'tox', '-v', '-e', toxenv] + list(args),
[sys.executable, '-m', 'tox', '-vv', '-e', toxenv] + list(args),
env=env)
@@ -109,8 +109,11 @@ def patch_osx_app():
for f in glob.glob(os.path.join(qtwe_core_dir, 'Resources', '*')):
dest = os.path.join(app_path, 'Contents', 'Resources')
if os.path.isdir(f):
shutil.copytree(f, os.path.join(dest, f))
dir_dest = os.path.join(dest, os.path.basename(f))
print("Copying directory {} to {}".format(f, dir_dest))
shutil.copytree(f, dir_dest)
else:
print("Copying {} to {}".format(f, dest))
shutil.copy(f, dest)
# Link dependencies
for lib in ['QtCore', 'QtWebEngineCore', 'QtQuick', 'QtQml', 'QtNetwork',
@@ -124,7 +127,16 @@ def patch_osx_app():
def build_osx():
"""Build OS X .dmg/.app."""
utils.print_title("Cleaning up...")
for f in ['wc.dmg', 'template.dmg']:
try:
os.remove(f)
except FileNotFoundError:
pass
for d in ['dist', 'build']:
shutil.rmtree(d, ignore_errors=True)
utils.print_title("Updating 3rdparty content")
# Currently disabled because QtWebEngine has no pdfjs support
# update_3rdparty.run(ace=False, pdfjs=True, fancy_dmg=False)
utils.print_title("Building .app via pyinstaller")
call_tox('pyinstaller', '-r')
@@ -132,25 +144,24 @@ def build_osx():
patch_osx_app()
utils.print_title("Building .dmg")
subprocess.check_call(['make', '-f', 'scripts/dev/Makefile-dmg'])
utils.print_title("Cleaning up...")
for f in ['wc.dmg', 'template.dmg']:
os.remove(f)
for d in ['dist', 'build']:
shutil.rmtree(d)
dmg_name = 'qutebrowser-{}.dmg'.format(qutebrowser.__version__)
os.rename('qutebrowser.dmg', dmg_name)
utils.print_title("Running smoke test")
with tempfile.TemporaryDirectory() as tmpdir:
subprocess.check_call(['hdiutil', 'attach', dmg_name,
'-mountpoint', tmpdir])
try:
binary = os.path.join(tmpdir, 'qutebrowser.app', 'Contents',
'MacOS', 'qutebrowser')
smoke_test(binary)
finally:
subprocess.check_call(['hdiutil', 'detach', tmpdir])
try:
with tempfile.TemporaryDirectory() as tmpdir:
subprocess.check_call(['hdiutil', 'attach', dmg_name,
'-mountpoint', tmpdir])
try:
binary = os.path.join(tmpdir, 'qutebrowser.app', 'Contents',
'MacOS', 'qutebrowser')
smoke_test(binary)
finally:
subprocess.call(['hdiutil', 'detach', tmpdir])
except PermissionError as e:
print("Failed to remove tempdir: {}".format(e))
return [(dmg_name, 'application/x-apple-diskimage', 'OS X .dmg')]
@@ -167,6 +178,7 @@ def patch_windows(out_dir):
def build_windows():
"""Build windows executables/setups."""
utils.print_title("Updating 3rdparty content")
# Currently disabled because QtWebEngine has no pdfjs support
# update_3rdparty.run(ace=False, pdfjs=True, fancy_dmg=False)
utils.print_title("Building Windows binaries")
@@ -203,8 +215,8 @@ def build_windows():
'/DVERSION={}'.format(qutebrowser.__version__),
'misc/qutebrowser.nsi'])
name_32 = 'qutebrowser-{}-win32.msi'.format(qutebrowser.__version__)
name_64 = 'qutebrowser-{}-amd64.msi'.format(qutebrowser.__version__)
name_32 = 'qutebrowser-{}-win32.exe'.format(qutebrowser.__version__)
name_64 = 'qutebrowser-{}-amd64.exe'.format(qutebrowser.__version__)
artifacts += [
(os.path.join('dist', name_32),
@@ -280,6 +292,14 @@ def build_sdist():
return artifacts
def read_github_token():
"""Read the GitHub API token from disk."""
token_file = os.path.join(os.path.expanduser('~'), '.gh_token')
with open(token_file, encoding='ascii') as f:
token = f.read().strip()
return token
def github_upload(artifacts, tag):
"""Upload the given artifacts to GitHub.
@@ -290,9 +310,7 @@ def github_upload(artifacts, tag):
import github3
utils.print_title("Uploading to github...")
token_file = os.path.join(os.path.expanduser('~'), '.gh_token')
with open(token_file, encoding='ascii') as f:
token = f.read().strip()
token = read_github_token()
gh = github3.login(token=token)
repo = gh.repository('qutebrowser', 'qutebrowser')
@@ -329,6 +347,12 @@ def main():
upload_to_pypi = False
if args.upload is not None:
# Fail early when trying to upload without github3 installed
# or without API token
import github3 # pylint: disable=unused-variable
read_github_token()
if os.name == 'nt':
if sys.maxsize > 2**32:
# WORKAROUND

View File

@@ -153,3 +153,26 @@ Feature: Using private browsing
- history:
- url: http://localhost:*/data/numbers/1.txt
- url: http://localhost:*/data/numbers/2.txt
Scenario: Saving a private session with only-active-window
When I open data/numbers/1.txt
And I open data/numbers/2.txt in a new tab
And I open data/numbers/3.txt in a private window
And I open data/numbers/4.txt in a new tab
And I open data/numbers/5.txt in a new tab
And I run :session-save --only-active-window window_session_name
And I run :window-only
And I run :tab-only
And I run :session-load -c window_session_name
And I wait until data/numbers/5.txt is loaded
Then the session should look like:
windows:
- tabs:
- history:
- url: http://localhost:*/data/numbers/3.txt
- history:
- url: http://localhost:*/data/numbers/4.txt
- history:
- active: true
url: http://localhost:*/data/numbers/5.txt

View File

@@ -60,8 +60,3 @@ Feature: :spawn
Scenario: Running :spawn with userscript that expects the stdin getting closed
When I run :spawn -u (testdata)/userscripts/stdinclose.py
Then the message "stdin closed" should be shown
@posix
Scenario: Running :spawn -d with userscript that expects the stdin getting closed
When I run :spawn -d -u (testdata)/userscripts/stdinclose.py
Then the message "stdin closed" should be shown

View File

@@ -27,7 +27,6 @@ import shutil
from PyQt5.QtGui import QColor
import pytest
import qutebrowser
from qutebrowser.config import config, configexc, configdata
from qutebrowser.config.parsers import keyconf
from qutebrowser.commands import runners
@@ -397,19 +396,6 @@ class TestDefaultConfig:
for cmd in conf.get_bindings_for(sectname).values():
runner.parse(cmd)
def test_upgrade_version(self):
"""Fail when the qutebrowser version changed.
The aim of this is to remind us to add a new file to old_configs.
If the config file of the current release didn't change compared to the
last one in old_configs, just increment the version here.
If it did change, place a new qutebrowser-vx.y.z.conf in old_configs
and then increment the version.
"""
assert qutebrowser.__version__ == '0.11.0'
@pytest.mark.parametrize('filename',
os.listdir(os.path.join(os.path.dirname(__file__), 'old_configs')),
ids=os.path.basename)

View File

@@ -128,11 +128,13 @@ def test_start_detached_error(fake_proc, message_mock, caplog):
"""Test starting a detached process with ok=False."""
argv = ['foo', 'bar']
fake_proc._proc.startDetached.return_value = (False, 0)
fake_proc._proc.error.return_value = "Error message"
fake_proc._proc.error.return_value = QProcess.FailedToStart
with caplog.at_level(logging.ERROR):
fake_proc.start_detached(*argv)
msg = message_mock.getmsg(usertypes.MessageLevel.error)
assert msg.text == "Error while spawning testprocess: Error message."
expected = ("Error while spawning testprocess: The process failed to "
"start.")
assert msg.text == expected
def test_double_start(qtbot, proc, py_proc):

View File

@@ -163,6 +163,15 @@ from qutebrowser.browser import pdfjs
version.DistributionInfo(
id='manjaro', parsed=version.Distribution.manjaro,
version=None, pretty='Manjaro Linux')),
# Funtoo
("""
ID="funtoo"
NAME="Funtoo GNU/Linux"
PRETTY_NAME="Linux"
""",
version.DistributionInfo(
id='funtoo', parsed=version.Distribution.gentoo,
version=None, pretty='Funtoo GNU/Linux')),
])
def test_distribution(tmpdir, monkeypatch, os_release, expected):
os_release_file = tmpdir / 'os-release'
@@ -496,7 +505,6 @@ class ImportFake:
'typing': True,
'PyQt5.QtWebEngineWidgets': True,
'PyQt5.QtWebKitWidgets': True,
'OpenGL': True,
}
self.version_attribute = '__version__'
self.version = '1.2.3'
@@ -556,7 +564,7 @@ class TestModuleVersions:
"""Test with all modules present in version 1.2.3."""
expected = ['sip: yes', 'colorama: 1.2.3', 'pypeg2: 1.2.3',
'jinja2: 1.2.3', 'pygments: 1.2.3', 'yaml: 1.2.3',
'cssutils: 1.2.3', 'typing: yes', 'OpenGL: 1.2.3',
'cssutils: 1.2.3', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes',
'PyQt5.QtWebKitWidgets: yes']
assert version._module_versions() == expected
@@ -580,17 +588,17 @@ class TestModuleVersions:
@pytest.mark.parametrize('value, expected', [
('VERSION', ['sip: yes', 'colorama: 1.2.3', 'pypeg2: yes',
'jinja2: yes', 'pygments: yes', 'yaml: yes',
'cssutils: yes', 'typing: yes', 'OpenGL: yes',
'cssutils: yes', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes',
'PyQt5.QtWebKitWidgets: yes']),
('SIP_VERSION_STR', ['sip: 1.2.3', 'colorama: yes', 'pypeg2: yes',
'jinja2: yes', 'pygments: yes', 'yaml: yes',
'cssutils: yes', 'typing: yes', 'OpenGL: yes',
'cssutils: yes', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes',
'PyQt5.QtWebKitWidgets: yes']),
(None, ['sip: yes', 'colorama: yes', 'pypeg2: yes', 'jinja2: yes',
'pygments: yes', 'yaml: yes', 'cssutils: yes', 'typing: yes',
'OpenGL: yes', 'PyQt5.QtWebEngineWidgets: yes',
'PyQt5.QtWebEngineWidgets: yes',
'PyQt5.QtWebKitWidgets: yes']),
])
def test_version_attribute(self, value, expected, import_fake):