Split utils.misc into utils.{qt,misc}
This commit is contained in:
parent
3443364de1
commit
8a8ca0c34f
@ -288,7 +288,7 @@ displaying it to the user.
|
||||
* Name a string URL something like `urlstr`, and a `QUrl` something like `url`.
|
||||
* Mention in the docstring whether your function needs a URL string or a
|
||||
`QUrl`.
|
||||
* Call `qt_ensure_valid` from `utils.misc` whenever getting or creating a
|
||||
* Call `qt_ensure_valid` from `utils.qt` whenever getting or creating a
|
||||
`QUrl` and take appropriate action if not.
|
||||
|
||||
|
||||
|
5
doc/TODO
5
doc/TODO
@ -25,11 +25,6 @@ Before 0.1
|
||||
qt_ensure_valid and qt_check_overflow
|
||||
check return values
|
||||
|
||||
Style
|
||||
=====
|
||||
|
||||
- Move some stuff from utils.misc to utils.qt and move utils.signals there too.
|
||||
|
||||
New big features
|
||||
================
|
||||
|
||||
|
@ -57,8 +57,8 @@ from qutebrowser.config.iniparsers import ReadWriteConfigParser
|
||||
from qutebrowser.config.lineparser import LineConfigParser
|
||||
from qutebrowser.browser.cookies import CookieJar
|
||||
from qutebrowser.browser.downloads import DownloadManager
|
||||
from qutebrowser.utils.misc import (get_standard_dir, actute_warning,
|
||||
get_qt_args)
|
||||
from qutebrowser.utils.misc import get_standard_dir, actute_warning
|
||||
from qutebrowser.utils.qt import get_qt_args
|
||||
from qutebrowser.utils.readline import ReadlineBridge
|
||||
from qutebrowser.utils.usertypes import Timer
|
||||
|
||||
|
@ -37,8 +37,9 @@ import qutebrowser.utils.webelem as webelem
|
||||
import qutebrowser.browser.quickmarks as quickmarks
|
||||
import qutebrowser.utils.log as log
|
||||
import qutebrowser.utils.url as urlutils
|
||||
from qutebrowser.utils.misc import (check_overflow, shell_escape,
|
||||
check_print_compat, qt_ensure_valid)
|
||||
from qutebrowser.utils.misc import shell_escape
|
||||
from qutebrowser.utils.qt import (check_overflow, check_print_compat,
|
||||
qt_ensure_valid)
|
||||
from qutebrowser.utils.editor import ExternalEditor
|
||||
from qutebrowser.commands.exceptions import CommandError
|
||||
from qutebrowser.commands.userscripts import UserscriptRunner
|
||||
|
@ -33,7 +33,7 @@ import qutebrowser.utils.webelem as webelem
|
||||
from qutebrowser.commands.exceptions import CommandError
|
||||
from qutebrowser.utils.usertypes import enum
|
||||
from qutebrowser.utils.log import hints as logger
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
ElemTuple = namedtuple('ElemTuple', 'elem, label')
|
||||
|
@ -33,7 +33,8 @@ import qutebrowser.utils.message as message
|
||||
import qutebrowser.commands.utils as cmdutils
|
||||
from qutebrowser.utils.usertypes import PromptMode
|
||||
from qutebrowser.config.lineparser import LineConfigParser
|
||||
from qutebrowser.utils.misc import get_standard_dir, qt_ensure_valid
|
||||
from qutebrowser.utils.misc import get_standard_dir
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
from qutebrowser.commands.exceptions import CommandError
|
||||
|
||||
|
||||
|
@ -30,7 +30,8 @@ from PyQt5.QtWebKitWidgets import QWebPage
|
||||
import qutebrowser.utils.message as message
|
||||
import qutebrowser.config.config as config
|
||||
import qutebrowser.utils.log as log
|
||||
from qutebrowser.utils.misc import read_file, check_print_compat
|
||||
from qutebrowser.utils.misc import read_file
|
||||
from qutebrowser.utils.qt import check_print_compat
|
||||
from qutebrowser.utils.usertypes import PromptMode
|
||||
|
||||
|
||||
|
@ -26,7 +26,7 @@ Module attributes:
|
||||
import inspect
|
||||
from collections import Iterable
|
||||
|
||||
import qutebrowser.utils.misc as utils
|
||||
import qutebrowser.utils.qt as qtutils
|
||||
from qutebrowser.commands.command import Command
|
||||
from qutebrowser.commands.exceptions import CommandError
|
||||
|
||||
@ -46,7 +46,7 @@ def check_overflow(arg, ctype):
|
||||
"""
|
||||
# FIXME we somehow should have nicer exceptions...
|
||||
try:
|
||||
utils.check_overflow(arg, ctype)
|
||||
qtutils.check_overflow(arg, ctype)
|
||||
except OverflowError:
|
||||
raise CommandError("Numeric argument is too large for internal {} "
|
||||
"representation.".format(ctype))
|
||||
|
@ -32,7 +32,7 @@ from collections import OrderedDict
|
||||
from qutebrowser.config.value import SettingValue
|
||||
import qutebrowser.config.conftypes as types
|
||||
import qutebrowser.config.sections as sect
|
||||
from qutebrowser.utils.misc import MAXVALS
|
||||
from qutebrowser.utils.qt import MAXVALS
|
||||
|
||||
|
||||
FIRST_COMMENT = r"""
|
||||
|
@ -27,7 +27,7 @@ from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
||||
|
||||
from qutebrowser.utils.usertypes import enum
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
Role = enum('marks', 'sort', start=Qt.UserRole)
|
||||
|
@ -26,7 +26,7 @@ import qutebrowser.config.configdata as configdata
|
||||
from qutebrowser.models.basecompletion import BaseCompletionModel
|
||||
from qutebrowser.commands.utils import cmd_dict
|
||||
from qutebrowser.utils.log import completion as logger
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class SettingSectionCompletionModel(BaseCompletionModel):
|
||||
|
@ -27,7 +27,7 @@ from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex
|
||||
|
||||
from qutebrowser.models.basecompletion import Role
|
||||
from qutebrowser.utils.log import completion as logger
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class CompletionFilterModel(QSortFilterProxyModel):
|
||||
|
@ -25,7 +25,7 @@ from PyQt5.QtWidgets import QApplication
|
||||
|
||||
import qutebrowser.config.config as config
|
||||
from qutebrowser.utils.usertypes import enum
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
Role = enum('item', start=Qt.UserRole)
|
||||
|
@ -55,7 +55,7 @@ def _parse_args():
|
||||
"Default: auto.")
|
||||
# For the Qt args, we use store_const with const=True rather than
|
||||
# store_true because we want the default to be None, to make
|
||||
# utils.misc:get_qt_args easier.
|
||||
# utils.qt:get_qt_args easier.
|
||||
debug.add_argument('--qt-style', help="Set the Qt GUI style to use.",
|
||||
metavar='STYLE')
|
||||
debug.add_argument('--qt-stylesheet', help="Override the Qt application "
|
||||
|
@ -24,7 +24,6 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import argparse
|
||||
import unittest
|
||||
import os.path
|
||||
import subprocess
|
||||
@ -62,60 +61,6 @@ class ElidingTests(TestCase):
|
||||
self.assertEqual(utils.elide('foobar', 3), 'fo' + self.ELLIPSIS)
|
||||
|
||||
|
||||
class CheckOverflowTests(TestCase):
|
||||
|
||||
"""Test check_overflow.
|
||||
|
||||
Class attributes:
|
||||
INT32_MIN: Minimum valid value for a signed int32.
|
||||
INT32_MAX: Maximum valid value for a signed int32.
|
||||
INT64_MIN: Minimum valid value for a signed int64.
|
||||
INT64_MAX: Maximum valid value for a signed int64.
|
||||
GOOD_VALUES: A dict of types mapped to a list of good values.
|
||||
BAD_VALUES: A dict of types mapped to a list of bad values.
|
||||
"""
|
||||
|
||||
INT32_MIN = -(2 ** 31)
|
||||
INT32_MAX = 2 ** 31 - 1
|
||||
INT64_MIN = -(2 ** 63)
|
||||
INT64_MAX = 2 ** 63 - 1
|
||||
|
||||
GOOD_VALUES = {
|
||||
'int': [-1, 0, 1, 23.42, INT32_MIN, INT32_MAX],
|
||||
'int64': [-1, 0, 1, 23.42, INT64_MIN, INT64_MAX],
|
||||
}
|
||||
|
||||
BAD_VALUES = {
|
||||
'int': [(INT32_MIN - 1, INT32_MIN),
|
||||
(INT32_MAX + 1, INT32_MAX),
|
||||
(float(INT32_MAX + 1), INT32_MAX)],
|
||||
'int64': [(INT64_MIN - 1, INT64_MIN),
|
||||
(INT64_MAX + 1, INT64_MAX),
|
||||
(float(INT64_MAX + 1), INT64_MAX)],
|
||||
}
|
||||
|
||||
def test_good_values(self):
|
||||
"""Test values which are inside bounds."""
|
||||
for ctype, vals in self.GOOD_VALUES.items():
|
||||
for val in vals:
|
||||
utils.check_overflow(val, ctype)
|
||||
|
||||
def test_bad_values_fatal(self):
|
||||
"""Test values which are outside bounds with fatal=True."""
|
||||
for ctype, vals in self.BAD_VALUES.items():
|
||||
for (val, _) in vals:
|
||||
with self.assertRaises(OverflowError, msg=ctype):
|
||||
utils.check_overflow(val, ctype)
|
||||
|
||||
def test_bad_values_nonfatal(self):
|
||||
"""Test values which are outside bounds with fatal=False."""
|
||||
for ctype, vals in self.BAD_VALUES.items():
|
||||
for (val, replacement) in vals:
|
||||
newval = utils.check_overflow(val, ctype, fatal=False)
|
||||
self.assertEqual(newval, replacement,
|
||||
"{}: {}".format(ctype, val))
|
||||
|
||||
|
||||
class ReadFileTests(TestCase):
|
||||
|
||||
"""Test read_file."""
|
||||
@ -383,59 +328,6 @@ class GetStandardDirWindowsTests(TestCase):
|
||||
self.app.quit()
|
||||
|
||||
|
||||
class GetQtArgsTests(TestCase):
|
||||
|
||||
"""Tests for get_qt_args."""
|
||||
|
||||
def setUp(self):
|
||||
self.parser = argparse.ArgumentParser()
|
||||
|
||||
def _namespace(self, cmdline, flags=None, args=None):
|
||||
"""Get an argparse namespace object based on arguments given.
|
||||
|
||||
Args:
|
||||
cmdline: The given commandline.
|
||||
flags: A list of strings (argument names) for flags without an
|
||||
argument.
|
||||
args: A list of arguemnt names for flags with an argument.
|
||||
"""
|
||||
if flags is not None:
|
||||
for e in flags:
|
||||
self.parser.add_argument(e, action='store_true')
|
||||
if args is not None:
|
||||
for e in args:
|
||||
self.parser.add_argument(e, nargs=1)
|
||||
return self.parser.parse_args(cmdline)
|
||||
|
||||
def test_no_qt_args(self):
|
||||
"""Test commandline with no Qt arguments given."""
|
||||
ns = self._namespace(['--foo'], flags=['--foo'])
|
||||
self.assertEqual(utils.get_qt_args(ns), [sys.argv[0]])
|
||||
|
||||
def test_qt_flag(self):
|
||||
"""Test commandline with a Qt flag."""
|
||||
ns = self._namespace(['--foo', '--qt-reverse', '--bar'],
|
||||
flags=['--foo', '--qt-reverse', '--bar'])
|
||||
self.assertEqual(utils.get_qt_args(ns), [sys.argv[0], '-reverse'])
|
||||
|
||||
def test_qt_arg(self):
|
||||
"""Test commandline with a Qt argument."""
|
||||
ns = self._namespace(['--qt-stylesheet', 'foobar'],
|
||||
args=['--qt-stylesheet'])
|
||||
self.assertEqual(utils.get_qt_args(ns), [sys.argv[0], '-stylesheet',
|
||||
'foobar'])
|
||||
|
||||
def test_qt_both(self):
|
||||
"""Test commandline with a Qt argument and flag."""
|
||||
ns = self._namespace(['--qt-stylesheet', 'foobar', '--qt-reverse'],
|
||||
flags=['--qt-reverse'], args=['--qt-stylesheet'])
|
||||
qt_args = utils.get_qt_args(ns)
|
||||
self.assertEqual(qt_args[0], sys.argv[0])
|
||||
self.assertIn('-reverse', qt_args)
|
||||
self.assertIn('-stylesheet', qt_args)
|
||||
self.assertIn('foobar', qt_args)
|
||||
|
||||
|
||||
class InterpolateColorTests(TestCase):
|
||||
|
||||
"""Tests for interpolate_color.
|
||||
|
140
qutebrowser/test/utils/test_qt.py
Normal file
140
qutebrowser/test/utils/test_qt.py
Normal file
@ -0,0 +1,140 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2014 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/>.
|
||||
|
||||
# pylint: disable=missing-docstring,blacklisted-name,protected-access
|
||||
|
||||
"""Tests for qutebrowser.utils.qt."""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import unittest
|
||||
from unittest import TestCase
|
||||
|
||||
import qutebrowser.utils.qt as qt
|
||||
|
||||
|
||||
class CheckOverflowTests(TestCase):
|
||||
|
||||
"""Test check_overflow.
|
||||
|
||||
Class attributes:
|
||||
INT32_MIN: Minimum valid value for a signed int32.
|
||||
INT32_MAX: Maximum valid value for a signed int32.
|
||||
INT64_MIN: Minimum valid value for a signed int64.
|
||||
INT64_MAX: Maximum valid value for a signed int64.
|
||||
GOOD_VALUES: A dict of types mapped to a list of good values.
|
||||
BAD_VALUES: A dict of types mapped to a list of bad values.
|
||||
"""
|
||||
|
||||
INT32_MIN = -(2 ** 31)
|
||||
INT32_MAX = 2 ** 31 - 1
|
||||
INT64_MIN = -(2 ** 63)
|
||||
INT64_MAX = 2 ** 63 - 1
|
||||
|
||||
GOOD_VALUES = {
|
||||
'int': [-1, 0, 1, 23.42, INT32_MIN, INT32_MAX],
|
||||
'int64': [-1, 0, 1, 23.42, INT64_MIN, INT64_MAX],
|
||||
}
|
||||
|
||||
BAD_VALUES = {
|
||||
'int': [(INT32_MIN - 1, INT32_MIN),
|
||||
(INT32_MAX + 1, INT32_MAX),
|
||||
(float(INT32_MAX + 1), INT32_MAX)],
|
||||
'int64': [(INT64_MIN - 1, INT64_MIN),
|
||||
(INT64_MAX + 1, INT64_MAX),
|
||||
(float(INT64_MAX + 1), INT64_MAX)],
|
||||
}
|
||||
|
||||
def test_good_values(self):
|
||||
"""Test values which are inside bounds."""
|
||||
for ctype, vals in self.GOOD_VALUES.items():
|
||||
for val in vals:
|
||||
qt.check_overflow(val, ctype)
|
||||
|
||||
def test_bad_values_fatal(self):
|
||||
"""Test values which are outside bounds with fatal=True."""
|
||||
for ctype, vals in self.BAD_VALUES.items():
|
||||
for (val, _) in vals:
|
||||
with self.assertRaises(OverflowError, msg=ctype):
|
||||
qt.check_overflow(val, ctype)
|
||||
|
||||
def test_bad_values_nonfatal(self):
|
||||
"""Test values which are outside bounds with fatal=False."""
|
||||
for ctype, vals in self.BAD_VALUES.items():
|
||||
for (val, replacement) in vals:
|
||||
newval = qt.check_overflow(val, ctype, fatal=False)
|
||||
self.assertEqual(newval, replacement,
|
||||
"{}: {}".format(ctype, val))
|
||||
|
||||
|
||||
class GetQtArgsTests(TestCase):
|
||||
|
||||
"""Tests for get_qt_args."""
|
||||
|
||||
def setUp(self):
|
||||
self.parser = argparse.ArgumentParser()
|
||||
|
||||
def _namespace(self, cmdline, flags=None, args=None):
|
||||
"""Get an argparse namespace object based on arguments given.
|
||||
|
||||
Args:
|
||||
cmdline: The given commandline.
|
||||
flags: A list of strings (argument names) for flags without an
|
||||
argument.
|
||||
args: A list of arguemnt names for flags with an argument.
|
||||
"""
|
||||
if flags is not None:
|
||||
for e in flags:
|
||||
self.parser.add_argument(e, action='store_true')
|
||||
if args is not None:
|
||||
for e in args:
|
||||
self.parser.add_argument(e, nargs=1)
|
||||
return self.parser.parse_args(cmdline)
|
||||
|
||||
def test_no_qt_args(self):
|
||||
"""Test commandline with no Qt arguments given."""
|
||||
ns = self._namespace(['--foo'], flags=['--foo'])
|
||||
self.assertEqual(qt.get_qt_args(ns), [sys.argv[0]])
|
||||
|
||||
def test_qt_flag(self):
|
||||
"""Test commandline with a Qt flag."""
|
||||
ns = self._namespace(['--foo', '--qt-reverse', '--bar'],
|
||||
flags=['--foo', '--qt-reverse', '--bar'])
|
||||
self.assertEqual(qt.get_qt_args(ns), [sys.argv[0], '-reverse'])
|
||||
|
||||
def test_qt_arg(self):
|
||||
"""Test commandline with a Qt argument."""
|
||||
ns = self._namespace(['--qt-stylesheet', 'foobar'],
|
||||
args=['--qt-stylesheet'])
|
||||
self.assertEqual(qt.get_qt_args(ns), [sys.argv[0], '-stylesheet',
|
||||
'foobar'])
|
||||
|
||||
def test_qt_both(self):
|
||||
"""Test commandline with a Qt argument and flag."""
|
||||
ns = self._namespace(['--qt-stylesheet', 'foobar', '--qt-reverse'],
|
||||
flags=['--qt-reverse'], args=['--qt-stylesheet'])
|
||||
qt_args = qt.get_qt_args(ns)
|
||||
self.assertEqual(qt_args[0], sys.argv[0])
|
||||
self.assertIn('-reverse', qt_args)
|
||||
self.assertIn('-stylesheet', qt_args)
|
||||
self.assertIn('foobar', qt_args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -139,12 +139,11 @@ def check_pyqt_core():
|
||||
# people only using the GUI notice them as well.
|
||||
def check_qt_version():
|
||||
"""Check if the Qt version is recent enough."""
|
||||
# We don't use qutebrowser.utils.misc:qt_version_check because we didn't
|
||||
# check for pkg_resources yet.
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||
import operator
|
||||
from PyQt5.QtCore import qVersion
|
||||
from distutils.version import StrictVersion as Version
|
||||
if Version(qVersion()) < Version('5.2.0'):
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||
from qutebrowser.utils.qt import qt_version_check
|
||||
if qt_version_check('5.2.0', operator.lt):
|
||||
app = QApplication(sys.argv)
|
||||
msgbox = QMessageBox(QMessageBox.Critical, "qutebrowser: Fatal error!",
|
||||
textwrap.dedent("""
|
||||
|
@ -17,50 +17,23 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Other utilities which don't fit anywhere else.
|
||||
|
||||
Module attributes:
|
||||
MAXVAL: A dictionary of C/Qt types (as string) mapped to their maximum
|
||||
value.
|
||||
"""
|
||||
"""Other utilities which don't fit anywhere else. """
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import shlex
|
||||
import os.path
|
||||
import operator
|
||||
import urllib.request
|
||||
from urllib.parse import urljoin, urlencode
|
||||
from functools import reduce
|
||||
|
||||
from distutils.version import StrictVersion as Version
|
||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths, QEventLoop, qVersion
|
||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths
|
||||
from PyQt5.QtGui import QColor
|
||||
from pkg_resources import resource_string
|
||||
|
||||
import qutebrowser
|
||||
|
||||
|
||||
MAXVALS = {
|
||||
'int': 2 ** 31 - 1,
|
||||
'int64': 2 ** 63 - 1,
|
||||
}
|
||||
|
||||
MINVALS = {
|
||||
'int': -(2 ** 31),
|
||||
'int64': -(2 ** 63),
|
||||
}
|
||||
|
||||
|
||||
def qt_version_check(version, op=operator.ge):
|
||||
"""Check if the Qt runtime version is the version supplied or newer.
|
||||
|
||||
Args:
|
||||
version: The version to check against.
|
||||
op: The operator to use for the check.
|
||||
"""
|
||||
return op(Version(qVersion()), Version(version))
|
||||
from qutebrowser.utils.qt import qt_version_check, qt_ensure_valid
|
||||
|
||||
|
||||
def elide(text, length):
|
||||
@ -73,38 +46,6 @@ def elide(text, length):
|
||||
return text[:length - 1] + '\u2026'
|
||||
|
||||
|
||||
def check_overflow(arg, ctype, fatal=True):
|
||||
"""Check if the given argument is in bounds for the given type.
|
||||
|
||||
Args:
|
||||
arg: The argument to check
|
||||
ctype: The C/Qt type to check as a string.
|
||||
fatal: Wether to raise exceptions (True) or truncate values (False)
|
||||
|
||||
Return
|
||||
The truncated argument if fatal=False
|
||||
The original argument if it's in bounds.
|
||||
|
||||
Raise:
|
||||
OverflowError if the argument is out of bounds and fatal=True.
|
||||
"""
|
||||
# FIXME we somehow should have nicer exceptions...
|
||||
maxval = MAXVALS[ctype]
|
||||
minval = MINVALS[ctype]
|
||||
if arg > maxval:
|
||||
if fatal:
|
||||
raise OverflowError(arg)
|
||||
else:
|
||||
return maxval
|
||||
elif arg < minval:
|
||||
if fatal:
|
||||
raise OverflowError(arg)
|
||||
else:
|
||||
return minval
|
||||
else:
|
||||
return arg
|
||||
|
||||
|
||||
def read_file(filename):
|
||||
"""Get the contents of a file contained with qutebrowser.
|
||||
|
||||
@ -267,30 +208,6 @@ def actute_warning():
|
||||
break
|
||||
|
||||
|
||||
def get_qt_args(namespace):
|
||||
"""Get the Qt QApplication arguments based on an argparse namespace.
|
||||
|
||||
Args:
|
||||
namespace: The argparse namespace.
|
||||
|
||||
Return:
|
||||
The argv list to be passed to Qt.
|
||||
"""
|
||||
argv = [sys.argv[0]]
|
||||
for argname, val in vars(namespace).items():
|
||||
if not argname.startswith('qt_'):
|
||||
continue
|
||||
elif val is None:
|
||||
# flag/argument not given
|
||||
continue
|
||||
elif val is True:
|
||||
argv.append('-' + argname[3:])
|
||||
else:
|
||||
argv.append('-' + argname[3:])
|
||||
argv.append(val[0])
|
||||
return argv
|
||||
|
||||
|
||||
def _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3, percent):
|
||||
"""Get a color which is percent% interpolated between start and end.
|
||||
|
||||
@ -388,53 +305,3 @@ def format_size(size, base=1024, suffix=''):
|
||||
return '{:.02f}{}{}'.format(size, p, suffix)
|
||||
size /= base
|
||||
return '{:.02f}{}{}'.format(size, prefixes[-1], suffix)
|
||||
|
||||
|
||||
def check_print_compat():
|
||||
"""Check if printing should work in the given Qt version."""
|
||||
return not (os.name == 'nt' and qt_version_check('5.3.0', operator.lt))
|
||||
|
||||
|
||||
def qt_ensure_valid(obj):
|
||||
"""Ensure a Qt object with an .isValid() method is valid.
|
||||
|
||||
Raise:
|
||||
QtValueError if the object is invalid.
|
||||
"""
|
||||
if not obj.isValid():
|
||||
raise QtValueError(obj)
|
||||
|
||||
|
||||
class QtValueError(ValueError):
|
||||
|
||||
"""Exception which gets raised by qt_ensure_valid."""
|
||||
|
||||
def __init__(self, obj):
|
||||
try:
|
||||
self.reason = obj.errorString()
|
||||
except AttributeError:
|
||||
self.reason = None
|
||||
err = "{} is not valid".format(obj)
|
||||
if self.reason:
|
||||
err += ": {}".format(self.reason)
|
||||
super().__init__(err)
|
||||
|
||||
|
||||
class EventLoop(QEventLoop):
|
||||
|
||||
"""A thin wrapper around QEventLoop.
|
||||
|
||||
Raises an exception when doing exec_() multiple times.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._executing = False
|
||||
|
||||
def exec_(self, flags=QEventLoop.AllEvents):
|
||||
"""Override exec_ to raise an exception when re-running."""
|
||||
if self._executing:
|
||||
raise AssertionError("Eventloop is already running!")
|
||||
self._executing = True
|
||||
super().exec_(flags)
|
||||
self._executing = False
|
||||
|
162
qutebrowser/utils/qt.py
Normal file
162
qutebrowser/utils/qt.py
Normal file
@ -0,0 +1,162 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2014 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/>.
|
||||
|
||||
"""Misc. utilities related to Qt.
|
||||
|
||||
Module attributes:
|
||||
MAXVALS: A dictionary of C/Qt types (as string) mapped to their maximum
|
||||
value.
|
||||
MINVALS: A dictionary of C/Qt types (as string) mapped to their minimum
|
||||
value.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import operator
|
||||
from distutils.version import StrictVersion as Version
|
||||
|
||||
from PyQt5.QtCore import QEventLoop, qVersion
|
||||
|
||||
|
||||
MAXVALS = {
|
||||
'int': 2 ** 31 - 1,
|
||||
'int64': 2 ** 63 - 1,
|
||||
}
|
||||
|
||||
MINVALS = {
|
||||
'int': -(2 ** 31),
|
||||
'int64': -(2 ** 63),
|
||||
}
|
||||
|
||||
|
||||
def qt_version_check(version, op=operator.ge):
|
||||
"""Check if the Qt runtime version is the version supplied or newer.
|
||||
|
||||
Args:
|
||||
version: The version to check against.
|
||||
op: The operator to use for the check.
|
||||
"""
|
||||
return op(Version(qVersion()), Version(version))
|
||||
|
||||
|
||||
def check_overflow(arg, ctype, fatal=True):
|
||||
"""Check if the given argument is in bounds for the given type.
|
||||
|
||||
Args:
|
||||
arg: The argument to check
|
||||
ctype: The C/Qt type to check as a string.
|
||||
fatal: Wether to raise exceptions (True) or truncate values (False)
|
||||
|
||||
Return
|
||||
The truncated argument if fatal=False
|
||||
The original argument if it's in bounds.
|
||||
|
||||
Raise:
|
||||
OverflowError if the argument is out of bounds and fatal=True.
|
||||
"""
|
||||
# FIXME we somehow should have nicer exceptions...
|
||||
maxval = MAXVALS[ctype]
|
||||
minval = MINVALS[ctype]
|
||||
if arg > maxval:
|
||||
if fatal:
|
||||
raise OverflowError(arg)
|
||||
else:
|
||||
return maxval
|
||||
elif arg < minval:
|
||||
if fatal:
|
||||
raise OverflowError(arg)
|
||||
else:
|
||||
return minval
|
||||
else:
|
||||
return arg
|
||||
|
||||
|
||||
def get_qt_args(namespace):
|
||||
"""Get the Qt QApplication arguments based on an argparse namespace.
|
||||
|
||||
Args:
|
||||
namespace: The argparse namespace.
|
||||
|
||||
Return:
|
||||
The argv list to be passed to Qt.
|
||||
"""
|
||||
argv = [sys.argv[0]]
|
||||
for argname, val in vars(namespace).items():
|
||||
if not argname.startswith('qt_'):
|
||||
continue
|
||||
elif val is None:
|
||||
# flag/argument not given
|
||||
continue
|
||||
elif val is True:
|
||||
argv.append('-' + argname[3:])
|
||||
else:
|
||||
argv.append('-' + argname[3:])
|
||||
argv.append(val[0])
|
||||
return argv
|
||||
|
||||
|
||||
def check_print_compat():
|
||||
"""Check if printing should work in the given Qt version."""
|
||||
return not (os.name == 'nt' and qt_version_check('5.3.0', operator.lt))
|
||||
|
||||
|
||||
def qt_ensure_valid(obj):
|
||||
"""Ensure a Qt object with an .isValid() method is valid.
|
||||
|
||||
Raise:
|
||||
QtValueError if the object is invalid.
|
||||
"""
|
||||
if not obj.isValid():
|
||||
raise QtValueError(obj)
|
||||
|
||||
|
||||
class QtValueError(ValueError):
|
||||
|
||||
"""Exception which gets raised by qt_ensure_valid."""
|
||||
|
||||
def __init__(self, obj):
|
||||
try:
|
||||
self.reason = obj.errorString()
|
||||
except AttributeError:
|
||||
self.reason = None
|
||||
err = "{} is not valid".format(obj)
|
||||
if self.reason:
|
||||
err += ": {}".format(self.reason)
|
||||
super().__init__(err)
|
||||
|
||||
|
||||
class EventLoop(QEventLoop):
|
||||
|
||||
"""A thin wrapper around QEventLoop.
|
||||
|
||||
Raises an exception when doing exec_() multiple times.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._executing = False
|
||||
|
||||
def exec_(self, flags=QEventLoop.AllEvents):
|
||||
"""Override exec_ to raise an exception when re-running."""
|
||||
if self._executing:
|
||||
raise AssertionError("Eventloop is already running!")
|
||||
self._executing = True
|
||||
super().exec_(flags)
|
||||
self._executing = False
|
@ -31,7 +31,7 @@ import qutebrowser.commands.utils as cmdutils
|
||||
from qutebrowser.widgets.completiondelegate import CompletionItemDelegate
|
||||
from qutebrowser.config.style import set_register_stylesheet
|
||||
from qutebrowser.utils.completer import Completer
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class CompletionView(QTreeView):
|
||||
|
@ -31,7 +31,7 @@ from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
|
||||
import qutebrowser.config.config as config
|
||||
from qutebrowser.models.basecompletion import Role
|
||||
from qutebrowser.config.style import get_stylesheet
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class CompletionItemDelegate(QStyledItemDelegate):
|
||||
|
@ -24,7 +24,7 @@ from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
|
||||
|
||||
from qutebrowser.models.downloadmodel import DownloadModel, Role
|
||||
from qutebrowser.config.style import set_register_stylesheet
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class DownloadView(QListView):
|
||||
|
@ -27,7 +27,6 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout
|
||||
|
||||
import qutebrowser.commands.utils as cmdutils
|
||||
import qutebrowser.config.config as config
|
||||
import qutebrowser.utils.misc as utils
|
||||
import qutebrowser.utils.message as message
|
||||
import qutebrowser.utils.log as log
|
||||
from qutebrowser.widgets.statusbar.bar import StatusBar
|
||||
@ -35,6 +34,7 @@ from qutebrowser.widgets.tabbedbrowser import TabbedBrowser
|
||||
from qutebrowser.widgets.completion import CompletionView
|
||||
from qutebrowser.widgets.downloads import DownloadView
|
||||
from qutebrowser.utils.usertypes import PromptMode
|
||||
from qutebrowser.utils.qt import check_overflow, qt_ensure_valid
|
||||
|
||||
|
||||
class MainWindow(QWidget):
|
||||
@ -138,7 +138,7 @@ class MainWindow(QWidget):
|
||||
# hpoint now would be the bottom-left edge of the widget if it was on
|
||||
# the top of the main window.
|
||||
topleft_y = self.height() - self.status.height() - height
|
||||
topleft_y = utils.check_overflow(topleft_y, 'int', fatal=False)
|
||||
topleft_y = check_overflow(topleft_y, 'int', fatal=False)
|
||||
topleft = QPoint(0, topleft_y)
|
||||
bottomright = self.status.geometry().topRight()
|
||||
rect = QRect(topleft, bottomright)
|
||||
@ -147,7 +147,7 @@ class MainWindow(QWidget):
|
||||
"topleft: {}, bottomright: {}".format(
|
||||
confheight, self.height(), height, contents_height,
|
||||
self.status.height(), topleft, bottomright))
|
||||
utils.qt_ensure_valid(rect)
|
||||
qt_ensure_valid(rect)
|
||||
self.completion.setGeometry(rect)
|
||||
|
||||
@cmdutils.register(instance='mainwindow', name=['quit', 'q'], nargs=0)
|
||||
|
@ -27,7 +27,7 @@ import qutebrowser.commands.utils as cmdutils
|
||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
||||
from qutebrowser.widgets.misc import MinimalLineEdit
|
||||
from qutebrowser.utils.usertypes import PromptMode, Question
|
||||
from qutebrowser.utils.misc import EventLoop
|
||||
from qutebrowser.utils.qt import EventLoop
|
||||
|
||||
|
||||
class Prompt(QWidget):
|
||||
|
@ -23,7 +23,7 @@ from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QLabel, QSizePolicy
|
||||
from PyQt5.QtGui import QPainter
|
||||
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class TextBase(QLabel):
|
||||
|
@ -32,7 +32,7 @@ from qutebrowser.widgets.tabwidget import TabWidget, EmptyTabIcon
|
||||
from qutebrowser.widgets.webview import WebView
|
||||
from qutebrowser.browser.signalfilter import SignalFilter
|
||||
from qutebrowser.browser.commands import CommandDispatcher
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class TabbedBrowser(TabWidget):
|
||||
|
@ -26,7 +26,7 @@ from PyQt5.QtGui import QIcon, QPixmap
|
||||
import qutebrowser.config.config as config
|
||||
from qutebrowser.config.style import set_register_stylesheet
|
||||
from qutebrowser.utils.style import Style
|
||||
from qutebrowser.utils.misc import qt_ensure_valid
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
|
||||
|
||||
class EmptyTabIcon(QIcon):
|
||||
|
@ -31,7 +31,8 @@ import qutebrowser.keyinput.modeman as modeman
|
||||
import qutebrowser.utils.message as message
|
||||
import qutebrowser.utils.webelem as webelem
|
||||
import qutebrowser.utils.log as log
|
||||
from qutebrowser.utils.misc import elide, qt_ensure_valid
|
||||
from qutebrowser.utils.misc import elide
|
||||
from qutebrowser.utils.qt import qt_ensure_valid
|
||||
from qutebrowser.browser.webpage import BrowserPage
|
||||
from qutebrowser.browser.hints import HintManager
|
||||
from qutebrowser.utils.usertypes import NeighborList, enum
|
||||
|
Loading…
Reference in New Issue
Block a user