Nicer docstrings

This commit is contained in:
Florian Bruhin 2014-02-19 10:58:32 +01:00
parent 25d57c8c6d
commit 9a990d56d9
18 changed files with 850 additions and 170 deletions

View File

@ -15,21 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""A vim like browser based on Qt.
Files:
__init__.py - This file.
__main__.py - Entry point for qutebrowser, to use
'python -m qutebrowser'.
app.py - Main qutebrowser application>
simplebrowser.py - Simple browser for testing purposes.
Subpackages:
commands - Handling of commands and key parsing.
utils - Misc utility code.
widgets - Qt widgets displayed on the screen.
"""
"""A vim like browser based on Qt."""
import os.path

View File

@ -132,7 +132,12 @@ class QuteBrowser(QApplication):
self._timers.append(timer)
def _parseopts(self):
"""Parse command line options."""
"""Parse command line options.
Return:
Argument namespace from argparse.
"""
parser = ArgumentParser("usage: %(prog)s [options]")
parser.add_argument('-l', '--log', dest='loglevel',
help='Set loglevel', default='info')
@ -222,9 +227,11 @@ class QuteBrowser(QApplication):
def _recover_pages(self):
"""Try to recover all open pages.
Return a list of open pages, or an empty list.
Called from _exception_hook, so as forgiving as possible.
Return:
A list of open pages, or an empty list.
"""
pages = []
if self.mainwindow is None:
@ -308,6 +315,9 @@ class QuteBrowser(QApplication):
This only quits if both the CrashDialog was ready to quit AND the
shutdown is complete.
Args:
The sender of the quit signal (string)
"""
self._quit_status[sender] = True
logging.debug("maybe_quit called from {}, quit status {}".format(
@ -323,10 +333,15 @@ class QuteBrowser(QApplication):
This gets called as a slot from all commands, and then calls the
appropriate command handler.
tpl -- A tuple in the form (count, argv) where argv is [cmd, arg, ...]
All handlers supporting a count should have a keyword argument count.
Args:
tpl: A tuple in the form (count, argv) where argv is
[cmd, arg, ...]
Return:
The handlers return value.
"""
(count, argv) = tpl
cmd = argv[0]
@ -371,10 +386,11 @@ class QuteBrowser(QApplication):
def pyeval(self, s):
"""Evaluate a python string and display the results as a webpage.
s -- The string to evaluate.
:pyeval command handler.
Args:
s: The string to evaluate.
"""
try:
r = eval(s)
@ -389,6 +405,9 @@ class QuteBrowser(QApplication):
:crash command handler.
Raises:
Always raises Exception.
"""
raise Exception
@ -399,7 +418,8 @@ class QuteBrowser(QApplication):
For some reason lastWindowClosing sometimes seem to get emitted twice,
so we make sure we only run once here.
quit -- Whether to quit after shutting down.
Args:
do_quit: Whether to quit after shutting down.
"""
if self._shutting_down:

View File

@ -67,7 +67,11 @@ class KeyParser(QObject):
Return True if the keypress has been handled, and False if not.
e -- the KeyPressEvent from Qt
Args:
e: the KeyPressEvent from Qt.
Return:
True if event has been handled, False otherwise.
"""
MODMASK2STR = {
@ -103,7 +107,11 @@ class KeyParser(QObject):
any possible command, and either run the command, ignore it, or
display an error.
e -- the KeyPressEvent from Qt.
Args:
e: the KeyPressEvent from Qt.
Emit:
set_cmd_text: If the keystring should be shown in the statusbar.
"""
# FIXME maybe we can do this in an easier way by using QKeySeqyence
@ -155,7 +163,13 @@ class KeyParser(QObject):
def _match_key(self, cmdstr_needle):
"""Try to match a given keystring with any bound keychain.
cmdstr_needle: The command string to find.
Args:
cmdstr_needle: The command string to find.
Return:
A tuple (matchtype, hay) where matchtype is MATCH_DEFINITIVE,
MATCH_PARTIAL or MATCH_NONE and hay is the long keystring where the
part was found in.
"""
try:
@ -177,7 +191,11 @@ class KeyParser(QObject):
def _normalize_keystr(self, keystr):
"""Normalize a keystring like Ctrl-Q to a keystring like Ctrl+Q.
keystr -- The key combination as a string.
Args:
keystr: The key combination as a string.
Return:
The normalized keystring.
"""
replacements = [
@ -196,9 +214,14 @@ class KeyParser(QObject):
def _run_or_fill(self, cmdstr, count=None, ignore_exc=True):
"""Run the command in cmdstr or fill the statusbar if args missing.
cmdstr -- The command string.
count -- Optional command count.
ignore_exc -- Ignore exceptions.
Args:
cmdstr: The command string.
count: Optional command count.
ignore_exc: Ignore exceptions.
Emit:
set_cmd_text: If a partial command should be printed to the
statusbar.
"""
try:
@ -217,6 +240,9 @@ class KeyParser(QObject):
Config format: key = command, e.g.:
gg = scrollstart
Args:
sect: The section to get the keybindings from.
"""
for (key, cmd) in sect.items():
if key.startswith('@') and key.endswith('@'):
@ -232,7 +258,11 @@ class KeyParser(QObject):
def handle(self, e):
"""Handle a new keypress and call the respective handlers.
e -- the KeyPressEvent from Qt
Args:
e: the KeyPressEvent from Qt
Emit:
keystring_updated: If a new keystring should be set.
"""
handled = self._handle_modifier_key(e)

View File

@ -63,6 +63,12 @@ class Command(QObject):
Raise ArgumentCountError if not.
Args:
args: The supplied arguments
Raise:
ArgumentCountError if the argument count is wrong.
"""
if ((isinstance(self.nargs, int) and len(args) != self.nargs) or
(self.nargs == '?' and len(args) > 1) or
@ -73,8 +79,12 @@ class Command(QObject):
def run(self, args=None, count=None):
"""Run the command.
args -- Arguments to the command.
count -- Command repetition count.
Args:
args: Arguments to the command.
count: Command repetition count.
Emit:
The command's signal.
"""
dbgout = ["command called:", self.mainname]

View File

@ -72,8 +72,12 @@ class SearchParser(QObject):
def _search(self, text, rev=False):
"""Search for a text on the current page.
text -- The text to search for.
rev -- Search direction.
Args:
text: The text to search for.
rev: Search direction, True if reverse, else False.
Emit:
do_search: If a search should be started.
"""
if self._text is not None and self._text != text:
@ -92,7 +96,8 @@ class SearchParser(QObject):
def search(self, text):
"""Search for a text on a website.
text -- The text to search for.
Args:
text: The text to search for.
"""
self._search(text)
@ -101,13 +106,22 @@ class SearchParser(QObject):
def search_rev(self, text):
"""Search for a text on a website in reverse direction.
text -- The text to search for.
Args:
text: The text to search for.
"""
self._search(text, rev=True)
def nextsearch(self, count=1):
"""Continue the search to the ([count]th) next term."""
"""Continue the search to the ([count]th) next term.
Args:
count: How many elements to ignore.
Emit:
do_search: If a search should be started.
"""
if self._text is not None:
for i in range(count): # pylint: disable=unused-variable
self.do_search.emit(self._text, self._flags)
@ -137,7 +151,11 @@ class CommandParser(QObject):
def _parse(self, text):
"""Split the commandline text into command and arguments.
Raise NoSuchCommandError if a command wasn't found.
Args:
text: Text to parse.
Raise:
NoSuchCommandError if a command wasn't found.
"""
parts = text.strip().split(maxsplit=1)
@ -163,7 +181,12 @@ class CommandParser(QObject):
self._cmd.check(self._args)
def _run(self, count=None):
"""Run a command with an optional count."""
"""Run a command with an optional count.
Args:
count: Count to pass to the command.
"""
if count is not None:
self._cmd.run(self._args, count=count)
else:
@ -175,13 +198,26 @@ class CommandParser(QObject):
If ignore_exc is True, ignore exceptions and return True/False.
Raise NoSuchCommandError if a command wasn't found, and
ArgumentCountError if a command was called with the wrong count of
arguments.
Args:
text: The text to parse.
count: The count to pass to the command.
ignore_exc: Ignore exceptions and return False instead.
Raise:
NoSuchCommandError: if a command wasn't found.
ArgumentCountError: if a command was called with the wrong count of
arguments.
Return:
FIXME
Emit:
error: If there was an error parsing a command.
"""
if ';;' in text:
for sub in text.split(';;'):
# FIXME handle return codes
self.run(sub, count, ignore_exc)
return
try:
@ -201,3 +237,4 @@ class CommandParser(QObject):
else:
raise
self._run(count=count)
# FIXME return val

View File

@ -42,8 +42,12 @@ class CompletionModel(QAbstractItemModel):
def _node(self, index):
"""Return the interal data representation for index.
Return the CompletionItem for index, or the root CompletionItem if the
index was invalid.
Args:
index: The QModelIndex to get data for.
Return:
The CompletionItem for index, or the root CompletionItem if the
index was invalid.
"""
if index.isValid():
@ -52,7 +56,16 @@ class CompletionModel(QAbstractItemModel):
return self._root
def _get_marks(self, needle, haystack):
"""Return the marks for needle in haystack."""
"""Return the marks for needle in haystack.
Args:
needle: The substring which should match.
haystack: The string where the matches should be in.
Return:
A list of (startidx, endidx) tuples.
"""
pos1 = pos2 = 0
marks = []
if not needle:
@ -68,7 +81,8 @@ class CompletionModel(QAbstractItemModel):
def mark_all_items(self, needle):
"""Mark a string in all items (children of root-children).
needle -- The string to mark.
Args:
needle: The string to mark.
"""
for i in range(self.rowCount()):
@ -82,7 +96,8 @@ class CompletionModel(QAbstractItemModel):
def init_data(self, data):
"""Initialize the Qt model based on the data given.
data -- dict of data to process.
Args:
data: dict of data to process.
"""
for (cat, items) in data.items():
@ -99,6 +114,11 @@ class CompletionModel(QAbstractItemModel):
Override QAbstractItemModel::removeRows.
Args:
position: The start row to remove.
count: How many rows to remove.
parent: The parent QModelIndex.
"""
node = self._node(parent)
self.beginRemoveRows(parent, position, position + count - 1)
@ -110,6 +130,13 @@ class CompletionModel(QAbstractItemModel):
Override QAbstractItemModel::columnCount.
Args:
parent: The parent for which to return the column count. Currently
ignored.
Return:
Column count as an integer.
"""
# pylint: disable=unused-argument
return self._root.column_count()
@ -120,6 +147,12 @@ class CompletionModel(QAbstractItemModel):
Use the root frame if parent is invalid.
Override QAbstractItemModel::rowCount.
Args:
parent: The parent for which to return the row count.
Return:
Row count as an integer.
"""
if parent.column() > 0:
return 0
@ -134,9 +167,15 @@ class CompletionModel(QAbstractItemModel):
def data(self, index, role=Qt.DisplayRole):
"""Return the data for role/index as QVariant.
Return an invalid QVariant on error.
Override QAbstractItemModel::data.
Args:
index: The QModelIndex for which to get data for.
roel: The role to use for the data.
Return:
The data as QVariant or an invalid QVariant on error.
"""
if not index.isValid():
return QVariant()
@ -152,9 +191,15 @@ class CompletionModel(QAbstractItemModel):
def headerData(self, section, orientation, role=Qt.DisplayRole):
"""Return the header data for role/index as QVariant.
Return an invalid QVariant on error.
Override QAbstractItemModel::headerData.
Args:
section: The section (as int) for which to get the header data.
orientation: Qt.Vertical or Qt.Horizontal
Return:
The data as QVariant or an invalid QVariant on error.
"""
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self._root.data(section))
@ -163,9 +208,19 @@ class CompletionModel(QAbstractItemModel):
def setData(self, index, value, role=Qt.EditRole):
"""Set the data for role/index to value.
Return True on success, False on failure.
Override QAbstractItemModel::setData.
Args:
index: The QModelIndex where to set the data.
value: The new data value.
role: The role to set the data for.
Return:
True on success, False on failure.
Emit:
dataChanged when the data was changed.
"""
if not index.isValid():
return False
@ -180,9 +235,14 @@ class CompletionModel(QAbstractItemModel):
def flags(self, index):
"""Return the item flags for index.
Return Qt.NoItemFlags on error.
Override QAbstractItemModel::flags.
Args:
index: The QModelIndex to get item flags for.
Return:
The item flags, or Qt.NoItemFlags on error.
"""
# FIXME categories are not selectable, but moving via arrow keys still
# tries to select them
@ -197,9 +257,16 @@ class CompletionModel(QAbstractItemModel):
def index(self, row, column, parent=QModelIndex()):
"""Return the QModelIndex for row/column/parent.
Return an invalid QModelIndex on failure.
Override QAbstractItemModel::index.
Args:
row: The row (int) to get an index for.
column: The column (int) to get an index for.
parent: The parent (QModelIndex) to get an index for.
Return:
A generated QModelIndex or an invalid QModelIndex on failure.
"""
if (0 <= row < self.rowCount(parent) and
0 <= column < self.columnCount(parent)):
@ -223,9 +290,14 @@ class CompletionModel(QAbstractItemModel):
def parent(self, index):
"""Return the QModelIndex of the parent of the object behind index.
Return an invalid QModelIndex on failure.
Override QAbstractItemModel::parent.
Args:
index: The QModelIndex to get the parent for.
Return:
The parent's QModelIndex or an invalid QModelIndex on failure.
"""
if not index.isValid():
return QModelIndex()
@ -237,9 +309,11 @@ class CompletionModel(QAbstractItemModel):
def sort(self, column, order=Qt.AscendingOrder):
"""Sort the data in column according to order.
Raise NotImplementedError, should be overwritten in a superclass.
Override QAbstractItemModel::sort.
Raise:
NotImplementedError, should be overwritten in a superclass.
"""
raise NotImplementedError
@ -259,8 +333,9 @@ class CompletionItem():
def __init__(self, data, parent=None):
"""Constructor for CompletionItem.
data -- The data for the model, as tuple (columns).
parent -- An optional parent item.
Args:
data: The data for the model, as tuple (columns).
parent: An optional parent item.
"""
self.parent = parent
@ -271,7 +346,15 @@ class CompletionItem():
def data(self, column, role=Qt.DisplayRole):
"""Get the data for role/column.
Raise ValueError if the role is invalid.
Args:
column: The column (int) to get data for.
role: The role to get data for.
Return:
The requested data.
Raise:
ValueError if the role is invalid.
"""
if role == Qt.DisplayRole:
@ -284,7 +367,13 @@ class CompletionItem():
def setdata(self, column, value, role=Qt.DisplayRole):
"""Set the data for column/role to value.
Raise ValueError if the role is invalid.
Args:
column: The column (int) to set the data for.
value: The value to set the data to.
role: The role to set the data for.
Raise:
ValueError if the role is invalid.
"""
if role == Qt.DisplayRole:
@ -295,11 +384,21 @@ class CompletionItem():
raise ValueError
def column_count(self):
"""Return the column count in the item."""
"""Get the column count in the item.
Return:
The column count.
"""
return len(self._data)
def row(self):
"""Return the row index (int) of the item, or 0 if it's a root item."""
"""Get the row index (int) of the item.
Return:
The row index of the item, or 0 if we're a root item.
"""
if self.parent:
return self.parent.children.index(self)
return 0

View File

@ -54,6 +54,9 @@ class CompletionFilterModel(QSortFilterProxyModel):
If the current completion model overrides sort(), it is used.
If not, the default implementation in QCompletionFilterModel is called.
Args:
val: The value to set.
"""
self._pattern = val
self.invalidateFilter()
@ -74,7 +77,8 @@ class CompletionFilterModel(QSortFilterProxyModel):
def srcmodel(self, model):
"""Set a new source model and clear the pattern.
model -- The new source model.
Args:
model: The new source model.
"""
# FIXME change this to a property
@ -97,11 +101,13 @@ class CompletionFilterModel(QSortFilterProxyModel):
Override QSortFilterProxyModel::filterAcceptsRow.
row -- The row of the item.
parent -- The parent item QModelIndex.
Args:
row: The row of the item.
parent: The parent item QModelIndex.
Return True if self.pattern is contained in item, or if it's a root
item (category). Else returns False.
Return:
True if self.pattern is contained in item, or if it's a root item
(category). False in all other cases
"""
if parent == QModelIndex():
@ -116,12 +122,16 @@ class CompletionFilterModel(QSortFilterProxyModel):
def lessThan(self, lindex, rindex):
"""Custom sorting implementation.
lindex -- The QModelIndex of the left item (*left* < right)
rindex -- The QModelIndex of the right item (left < *right*)
Prefers all items which start with self.pattern. Other than that, uses
normal Python string sorting.
Args:
lindex: The QModelIndex of the left item (*left* < right)
rindex: The QModelIndex of the right item (left < *right*)
Return:
True if left < right, else False
"""
left = self.srcmodel.data(lindex).value()
right = self.srcmodel.data(rindex).value()

View File

@ -41,7 +41,14 @@ pyeval_output = None
def handle(url):
"""Handle about page with an url.
Return HTML content.
Args:
url: The url (string) to serve the about page for.
Raise:
ValueError if passed URL is not an about URL
Return:
HTML content as bytes.
"""
if not is_about_url(url):
@ -51,15 +58,27 @@ def handle(url):
def _transform_url(url):
"""Transform a special URL to an AboutHandlers method name."""
"""Transform a special URL to an AboutHandlers method name.
Args:
url: The URL as string.
Return:
The method name about_*
"""
return url.replace('http://', '').replace('about:', 'about_')
def _get_html(title, snippet):
"""Add HTML boilerplate to a html snippet.
title -- The title the page should have.
snippet -- The html snippet.
Args:
title: The title the page should have.
snippet: The html snippet.
Return:
HTML content as bytes.
"""
return _html_template.format(title=title, body=snippet).encode('UTF-8')
@ -71,10 +90,10 @@ class AboutHandlers:
@classmethod
def about_pyeval(cls):
"""Handler for about:pyeval."""
"""Handler for about:pyeval. Return HTML content as bytes."""
return _get_html('pyeval', '<pre>{}</pre>'.format(pyeval_output))
@classmethod
def about_version(cls):
"""Handler for about:version."""
"""Handler for about:version. Return HTML content as bytes."""
return _get_html('Version', '<pre>{}</pre>'.format(version()))

View File

@ -36,7 +36,12 @@ _UNSET = object()
def init(confdir):
"""Initialize the global objects based on the config in configdir."""
"""Initialize the global objects based on the config in configdir.
Args:
confdir: The directory where the configs are stored in.
"""
global config, state, colordict, fontdict
logging.debug("Config init, confdir {}".format(confdir))
config = Config(confdir, 'qutebrowser.conf', read_file('qutebrowser.conf'))
@ -49,7 +54,15 @@ def init(confdir):
def get_stylesheet(template):
"""Return a formatted stylesheet based on a template."""
"""Format a stylesheet based on a template.
Args:
template: The stylesheet template as string.
Return:
The formatted template as string.
"""
return template.strip().format(color=colordict, font=fontdict)
@ -64,13 +77,17 @@ class ColorDict(dict):
def __getitem__(self, key):
"""Override dict __getitem__.
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
Args:
key: The key to get from the dict.
If the key has a .fg. element in it, return color: X;.
If the key has a .bg. element in it, return background-color: X;.
Return:
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
In all other cases, return the plain value.
If the key has a .fg. element in it, return color: X;.
If the key has a .bg. element in it, return background-color: X;.
In all other cases, return the plain value.
"""
try:
@ -87,7 +104,11 @@ class ColorDict(dict):
def getraw(self, key):
"""Get a value without the transformations done in __getitem__.
Return a value, or None if the value wasn't found.
Args:
key: The key to get from the dict.
Return:
A value, or None if the value wasn't found.
"""
try:
@ -103,10 +124,14 @@ class FontDict(dict):
def __getitem__(self, key):
"""Override dict __getitem__.
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
Args:
key: The key to get from the dict.
In all other cases, return font: <value>.
Return:
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
In all other cases, return font: <value>.
"""
try:
@ -119,7 +144,11 @@ class FontDict(dict):
def getraw(self, key):
"""Get a value without the transformations done in __getitem__.
Return a value, or None if the value wasn't found.
Args:
key: The key to get from the dict.
Return:
A value, or None if the value wasn't found.
"""
try:
@ -143,11 +172,12 @@ class Config(ConfigParser):
always_save=False):
"""Config constructor.
configdir -- directory to store the config in.
fname -- Filename of the config file.
default_config -- Default config as string.
always_save -- Whether to always save the config, even when it wasn't
loaded.
Args:
configdir: Directory to store the config in.
fname: Filename of the config file.
default_config: Default config as string.
always_save: Whether to always save the config, even when it wasn't
loaded.
"""
super().__init__(interpolation=ExtendedInterpolation())
@ -174,6 +204,12 @@ class Config(ConfigParser):
Extend ConfigParser's __getitem__.
Args:
key: The key to get from the dict.
Return:
The value of the main or fallback ConfigParser.
"""
try:
return super().__getitem__(key)
@ -191,6 +227,16 @@ class Config(ConfigParser):
- If that's not available, try the fallback given as kwarg
- If that's not available, we're doomed.
Args:
*args: Passed to the other configparsers.
raw: Passed to the other configparsers (do not interpolate).
var: Passed to the other configparsers.
fallback: Fallback value if value wasn't found in any configparser.
Raise:
configparser.NoSectionError/configparser.NoOptionError if the
default configparser raised them and there is no fallback.
"""
# pylint: disable=redefined-builtin
# The arguments returned by the ConfigParsers actually are strings
@ -225,7 +271,12 @@ class Config(ConfigParser):
os.fsync(f.fileno())
def dump_userconfig(self):
"""Return the part of the config which was changed by the user."""
"""Get the part of the config which was changed by the user.
Return:
The changed config part as string.
"""
with io.StringIO() as f:
self.write(f)
return f.getvalue()

View File

@ -47,14 +47,27 @@ def set_trace():
def read_file(filename):
"""Return the contents of a file contained with qutebrowser."""
"""Get the contents of a file contained with qutebrowser.
Args:
filename: The filename to open as string.
Return:
The file contents as string.
"""
fn = os.path.join(qutebrowser.basedir, filename)
with open(fn, 'r', encoding='UTF-8') as f:
return f.read()
def trace_lines(do_trace):
"""Turn on/off printing each executed line."""
"""Turn on/off printing each executed line.
Args:
do_trace: Whether to start tracing (True) or stop it (False).
"""
def trace(frame, event, _):
"""Trace function passed to sys.settrace."""
print("{}, {}:{}".format(event, frame.f_code.co_filename,

View File

@ -25,16 +25,28 @@ from PyQt5.QtCore import QObject
def signal_name(sig):
"""Return a cleaned up name of a signal."""
"""Get a cleaned up name of a signal.
Args:
sig: The pyqtSignal
Return:
The cleaned up signal name.
"""
m = re.match(r'[0-9]+(.*)\(.*\)', sig.signal)
return m.group(1)
def dbg_signal(sig, args):
"""Return a string representation of a signal for debugging.
"""Get a string representation of a signal for debugging.
sig -- A pyqtSignal.
args -- The arguments as list of strings.
Args:
sig: A pyqtSignal.
args: The arguments as list of strings.
Return:
A human-readable string representation of signal/args.
"""
return '{}({})'.format(signal_name(sig), ', '.join(map(str, args)))
@ -53,8 +65,9 @@ class SignalCache(QObject):
def __init__(self, uncached=None):
"""Create a new SignalCache.
uncached -- A list of signal names (as string) which should never be
cached.
Args:
uncached: A list of signal names (as string) which should never be
cached.
"""
super().__init__()
@ -65,7 +78,7 @@ class SignalCache(QObject):
self._signal_dict = OrderedDict()
def _signal_needs_caching(self, signal):
"""Return True if a signal should be cached, false otherwise."""
"""Return True if a signal should be cached, False otherwise."""
return not signal_name(signal) in self._uncached
def add(self, sig, args):
@ -75,6 +88,13 @@ class SignalCache(QObject):
If it's already in the cache, it'll be updated and moved to the front.
If not, it will be added.
Args:
sig: The pyqtSignal.
args: A list of arguments.
Emit:
Cached signals.
"""
if not self._signal_needs_caching(sig):
return

View File

@ -48,6 +48,9 @@ class Style(QCommonStyle):
This simply calls the corresponding function in self._style.
Args:
style: The base/"parent" style.
"""
self._style = style
for method in ['drawComplexControl', 'drawControl', 'drawItemPixmap',
@ -66,6 +69,12 @@ class Style(QCommonStyle):
Call the genuine drawPrimitive of self._style, except when a focus
rectangle should be drawn.
Args:
element: PrimitiveElement pe
option: const QStyleOption * opt
painter: QPainter * p
widget: const QWidget * widget
"""
if element == QStyle.PE_FrameFocusRect:
return

View File

@ -28,7 +28,18 @@ import qutebrowser.utils.config as config
def _get_search_url(txt):
"""Return a search engine URL (QUrl) for a text."""
"""Get a search engine URL for a text.
Args:
txt: Text to search for.
Return:
The search URL as a QUrl.
Raise:
ValueError if there is no template or no search term was found.
"""
logging.debug('Finding search engine for "{}"'.format(txt))
r = re.compile(r'(^|\s+)!(\w+)($|\s+)')
m = r.search(txt)
@ -49,7 +60,15 @@ def _get_search_url(txt):
def _is_url_naive(url):
"""Naive check if given url (QUrl) is really an url."""
"""Naive check if given url is really an url.
Args:
url: The URL to check for.
Return:
True if the url really is an URL, False otherwise.
"""
PROTOCOLS = ['http://', 'https://']
u = urlstring(url)
return (any(u.startswith(proto) for proto in PROTOCOLS) or '.' in u or
@ -57,7 +76,15 @@ def _is_url_naive(url):
def _is_url_dns(url):
"""Check if an url (QUrl) is really an url via DNS."""
"""Check if an url (QUrl) is really an url via DNS.
Args:
url: The URL to check for.
Return:
True if the url really is an URL, False otherwise.
"""
# FIXME we could probably solve this in a nicer way by attempting to open
# the page in the webview, and then open the search if that fails.
host = url.host()
@ -73,23 +100,39 @@ def _is_url_dns(url):
def qurl(url):
"""Get a QUrl from an url string."""
"""Get a QUrl from an url string.
Args:
The URL as string or QUrl.
Return:
The URL as string.
"""
return url if isinstance(url, QUrl) else QUrl(url)
def urlstring(url):
"""Return an QUrl as string.
"""Get an QUrl as string.
qurl -- URL as string or QUrl.
Args:
qurl: URL as string or QUrl.
Return:
The URL as string
"""
return url.toString() if isinstance(url, QUrl) else url
def fuzzy_url(url):
"""Return a QUrl based on an user input which is URL or search term.
"""Get a QUrl based on an user input which is URL or search term.
url -- URL to load as QUrl or string.
Args:
url: URL to load as QUrl or string.
Return:
A target QUrl to a searchpage or the original URL.
"""
u = qurl(url)
@ -110,12 +153,23 @@ def fuzzy_url(url):
def is_about_url(url):
"""Return True if url (QUrl) is an about:... or other special URL."""
"""Return True if url is an about:... or other special URL."""
return urlstring(url).replace('http://', '').startswith('about:')
def is_url(url):
"""Return True if url (QUrl) seems to be a valid URL."""
"""Check if url seems to be a valid URL.
Args:
url: The URL as QUrl or string.
Return:
True if it is a valid url, False otherwise.
Raise:
ValueError if the autosearch config value is invalid.
"""
urlstr = urlstring(url)
try:

View File

@ -29,9 +29,11 @@ import qutebrowser
def _git_str():
"""Try to find out git version and return a string if possible.
"""Try to find out git version.
Return None if there was an error or we're not in a git repo.
Return:
string containing the git commit ID.
None if there was an error or we're not in a git repo.
"""
if hasattr(sys, "frozen"):

View File

@ -107,7 +107,15 @@ class TabbedBrowser(TabWidget):
self._space.activated.connect(lambda: self.cur_scroll_page(0, 1))
def _cb_tab_shutdown(self, tab):
"""Called after a tab has been shut down completely."""
"""Called after a tab has been shut down completely.
Args:
tab: The tab object which has been shut down.
Emit:
shutdown_complete: When the tab shutdown is done completely.
"""
try:
self._tabs.remove(tab)
except ValueError:
@ -118,7 +126,14 @@ class TabbedBrowser(TabWidget):
self.shutdown_complete.emit()
def _cur_scroll_percent(self, perc=None, count=None, orientation=None):
"""Inner logic for cur_scroll_percent_(x|y)."""
"""Inner logic for cur_scroll_percent_(x|y).
Args:
perc: How many percent to scroll, or None
count: How many percent to scroll, or None
orientation: Qt.Horizontal or Qt.Vertical
"""
if perc is None and count is None:
perc = 100
elif perc is None:
@ -134,7 +149,13 @@ class TabbedBrowser(TabWidget):
def _widget(self, count=None):
"""Return a widget based on a count/idx.
If count is None, return the current widget.
Args:
count: The tab index, or None.
Return:
The current widget if count is None.
The widget with the given tab ID if count is given.
None if no widget was found.
"""
if count is None:
@ -149,6 +170,9 @@ class TabbedBrowser(TabWidget):
Slot for the titleChanged signal of any tab.
Args:
text: The text to set.
"""
logging.debug('title changed to "{}"'.format(text))
if text:
@ -157,7 +181,15 @@ class TabbedBrowser(TabWidget):
logging.debug('ignoring title change')
def _filter_factory(self, signal):
"""Return a partial functon calling _filter_signals with a signal."""
"""Factory for partial _filter_signals functions.
Args:
signal: The pyqtSignal to filter.
Return:
A partial functon calling _filter_signals with a signal.
"""
return functools.partial(self._filter_signals, signal)
def _filter_signals(self, signal, *args):
@ -172,8 +204,12 @@ class TabbedBrowser(TabWidget):
The current value of the signal is also stored in tab.signal_cache so
it can be emitted later when the tab changes to the current tab.
signal -- The signal to emit if the sender was the current widget.
*args -- The args to pass to the signal.
Args:
signal: The signal to emit if the sender was the current widget.
*args: The args to pass to the signal.
Emit:
The target signal if the sender was the current widget.
"""
# FIXME BUG the signal cache ordering seems to be weird sometimes.
@ -202,7 +238,12 @@ class TabbedBrowser(TabWidget):
logging.debug(' ignoring')
def shutdown(self):
"""Try to shut down all tabs cleanly."""
"""Try to shut down all tabs cleanly.
Emit:
shutdown_complete if the shutdown completed successfully.
"""
try:
self.currentChanged.disconnect()
except TypeError:
@ -223,6 +264,9 @@ class TabbedBrowser(TabWidget):
Also connect all the signals we need to _filter_signals.
Args:
url: The URL to open.
"""
logging.debug("Opening {}".format(url))
url = urlutils.qurl(url)
@ -248,12 +292,22 @@ class TabbedBrowser(TabWidget):
tab.openurl(url)
def tabopencur(self):
"""Set the statusbar to :tabopen and the current URL."""
"""Set the statusbar to :tabopen and the current URL.
Emit:
set_cmd_text prefilled with :tabopen $URL
"""
url = urlutils.urlstring(self.currentWidget().url())
self.set_cmd_text.emit(':tabopen ' + url)
def opencur(self):
"""Set the statusbar to :open and the current URL."""
"""Set the statusbar to :open and the current URL.
Emit:
set_cmd_text prefilled with :open $URL
"""
url = urlutils.urlstring(self.currentWidget().url())
self.set_cmd_text.emit(':open ' + url)
@ -271,6 +325,13 @@ class TabbedBrowser(TabWidget):
Command handler for :close.
Args:
count: The tab index to close, or None
Emit:
quit: If last tab was closed and last_close in config is set to
quit.
"""
idx = self.currentIndex() if count is None else count - 1
tab = self._widget(count)
@ -292,7 +353,10 @@ class TabbedBrowser(TabWidget):
"""Open an url in the current/[count]th tab.
Command handler for :open.
url -- The URL to open.
Args:
url: The URL to open.
count: The tab index to open the URL in, or None.
"""
tab = self._widget(count)
@ -304,6 +368,9 @@ class TabbedBrowser(TabWidget):
Command handler for :reload.
Args:
count: The tab index to reload, or None.
"""
tab = self._widget(count)
if tab is not None:
@ -314,6 +381,9 @@ class TabbedBrowser(TabWidget):
Command handler for :stop.
Args:
count: The tab index to stop, or None.
"""
tab = self._widget(count)
if tab is not None:
@ -324,6 +394,9 @@ class TabbedBrowser(TabWidget):
Command handler for :print.
Args:
count: The tab index to print, or None.
"""
# FIXME that does not what I expect
tab = self._widget(count)
@ -335,9 +408,11 @@ class TabbedBrowser(TabWidget):
def cur_back(self, count=1):
"""Go back in the history of the current tab.
Go back for 1 page if count is unset, else go back [count] pages.
Command handler for :back.
Args:
count: How many pages to go back.
"""
# FIXME display warning if beginning of history
for i in range(count): # pylint: disable=unused-variable
@ -346,9 +421,11 @@ class TabbedBrowser(TabWidget):
def cur_forward(self, count=1):
"""Go forward in the history of the current tab.
Go forward for 1 page if count is unset, else go forward [count] pages.
Command handler for :forward.
Args:
count: How many pages to go forward.
"""
# FIXME display warning if end of history
for i in range(count): # pylint: disable=unused-variable
@ -358,8 +435,9 @@ class TabbedBrowser(TabWidget):
def cur_search(self, text, flags):
"""Search for text in the current page.
text -- The text to search for.
flags -- The QWebPage::FindFlags.
Args:
text: The text to search for.
flags: The QWebPage::FindFlags.
"""
self.currentWidget().findText(text, flags)
@ -369,6 +447,11 @@ class TabbedBrowser(TabWidget):
Command handler for :scroll.
Args:
dx: How much to scroll in x-direction.
dy: How much to scroll in x-direction.
count: multiplier
"""
dx = int(count) * float(dx)
dy = int(count) * float(dy)
@ -377,25 +460,36 @@ class TabbedBrowser(TabWidget):
def cur_scroll_percent_x(self, perc=None, count=None):
"""Scroll the current tab to a specific percent of the page.
Accepts percentage either as argument, or as count.
Command handler for :scroll_perc_x.
Args:
perc: Percentage to scroll.
count: Percentage to scroll.
"""
self._cur_scroll_percent(perc, count, Qt.Horizontal)
def cur_scroll_percent_y(self, perc=None, count=None):
"""Scroll the current tab to a specific percent of the page.
Accepts percentage either as argument, or as count.
Command handler for :scroll_perc_y
Args:
perc: Percentage to scroll.
count: Percentage to scroll.
"""
self._cur_scroll_percent(perc, count, Qt.Vertical)
def cur_scroll_page(self, mx, my, count=1):
"""Scroll the frame mx pages to the right and my pages down."""
"""Scroll the frame page-wise.
Args:
mx: How many pages to scroll to the right.
my: How many pages to scroll down.
count: multiplier
"""
# FIXME this might not work with HTML frames
page = self.currentWidget().page_
size = page.viewportSize()
@ -407,6 +501,9 @@ class TabbedBrowser(TabWidget):
Command handler for :yank.
Args:
sel: True to use primary selection, False to use clipboard
"""
clip = QApplication.clipboard()
url = urlutils.urlstring(self.currentWidget().url())
@ -419,6 +516,9 @@ class TabbedBrowser(TabWidget):
Command handler for :yanktitle.
Args:
sel: True to use primary selection, False to use clipboard
"""
clip = QApplication.clipboard()
title = self.tabText(self.currentIndex())
@ -431,6 +531,9 @@ class TabbedBrowser(TabWidget):
Command handler for :tabprev.
Args:
count: How many tabs to switch back.
"""
idx = self.currentIndex()
if idx - count >= 0:
@ -444,6 +547,9 @@ class TabbedBrowser(TabWidget):
Command handler for :tabnext.
Args:
count: How many tabs to switch forward.
"""
idx = self.currentIndex()
if idx + count < self.count():
@ -457,6 +563,9 @@ class TabbedBrowser(TabWidget):
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
"""
# FIXME what happens for invalid URLs?
clip = QApplication.clipboard()
@ -470,6 +579,9 @@ class TabbedBrowser(TabWidget):
Command handler for :paste.
Args:
sel: True to use primary selection, False to use clipboard
"""
# FIXME what happens for invalid URLs?
clip = QApplication.clipboard()
@ -479,14 +591,26 @@ class TabbedBrowser(TabWidget):
self.tabopen(url)
def keyPressEvent(self, e):
"""Extend TabWidget (QWidget)'s keyPressEvent to emit a signal."""
"""Extend TabWidget (QWidget)'s keyPressEvent to emit a signal.
Args:
e: The QKeyPressEvent
Emit:
keypress: Always emitted.
"""
self.keypress.emit(e)
super().keyPressEvent(e)
def resizeEvent(self, e):
"""Extend resizeEvent of QWidget to emit a resized signal afterwards.
e -- The QResizeEvent.
Args:
e: The QResizeEvent
Emit:
resize: Always emitted.
"""
super().resizeEvent(e)
@ -507,6 +631,7 @@ class BrowserTab(QWebView):
_open_new_tab: Whether to open a new tab for the next action.
_shutdown_callback: The callback to call after shutting down.
_destroyed: Dict of all items to be destroyed on shtudown.
Signals:
scroll_pos_changed: Scroll percentage of current tab changed.
arg 1: x-position in %.
@ -538,7 +663,14 @@ class BrowserTab(QWebView):
def openurl(self, url):
"""Open an URL in the browser.
url -- The URL to load, as string or QUrl.
Args:
url: The URL to load, as string or QUrl.
Return:
Return status of self.load
Emit:
titleChanged and urlChanged
"""
u = urlutils.fuzzy_url(url)
@ -563,7 +695,11 @@ class BrowserTab(QWebView):
Called from the linkClicked signal. Checks if it should open it in a
tab (middle-click or control) or not, and does so.
url -- The url to handle, as string or QUrl.
Args:
url: The url to handle, as string or QUrl.
Emit:
open_tab: Emitted if window should be opened in a new tab.
"""
if self._open_new_tab:
@ -578,6 +714,9 @@ class BrowserTab(QWebView):
[1] https://github.com/integricho/path-of-a-pyqter/tree/master/qttut08
Args:
callback: Function to call after shutting down.
"""
self._shutdown_callback = callback
try:
@ -606,7 +745,12 @@ class BrowserTab(QWebView):
logging.debug("Tab shutdown scheduled")
def _on_destroyed(self, sender):
"""Called when a subsystem has been destroyed during shutdown."""
"""Called when a subsystem has been destroyed during shutdown.
Args:
sender: The object which called the callback.
"""
self._destroyed[sender] = True
dbgout = '\n'.join(['{}: {}'.format(k.__class__.__name__, v)
for (k, v) in self._destroyed.items()])
@ -624,7 +768,11 @@ class BrowserTab(QWebView):
hope a repaint will always be requested when scrolling, and if the
scroll position actually changed, we emit a signal.
e -- The QPaintEvent.
Args:
e: The QPaintEvent.
Emit:
scroll_pos_changed; If the scroll position changed.
"""
frame = self.page_.mainFrame()
@ -650,7 +798,11 @@ class BrowserTab(QWebView):
This also is a bit of a hack, but it seems it's the only possible way.
Set the _open_new_tab attribute accordingly.
e -- The arrived event.
Args:
e: The arrived event.
Return:
The superclass event return value.
"""
if e.type() in [QEvent.MouseButtonPress, QEvent.MouseButtonDblClick]:
@ -683,6 +835,14 @@ class BrowserPage(QWebPage):
Loosly based on Helpviewer/HelpBrowserWV.py from eric5
(line 260 @ 5d937eb378dd)
Args:
opt: The QWebPage.ErrorPageExtensionOption instance.
out: The QWebPage.ErrorPageExtensionReturn instance to write return
values to.
Return:
False if no error page should be displayed, True otherwise.
"""
info = sip.cast(opt, QWebPage.ErrorPageExtensionOption)
errpage = sip.cast(out, QWebPage.ErrorPageExtensionReturn)
@ -697,11 +857,29 @@ class BrowserPage(QWebPage):
return True
def supportsExtension(self, ext):
"""Override QWebPage::supportsExtension to provide error pages."""
"""Override QWebPage::supportsExtension to provide error pages.
Args:
ext: The extension to check for.
Return:
True if the extension can be handled, False otherwise.
"""
return ext in self._extension_handlers
def extension(self, ext, opt, out):
"""Override QWebPage::extension to provide error pages."""
"""Override QWebPage::extension to provide error pages.
Args:
ext: The extension.
opt: Extension options instance.
out: Extension output instance.
Return:
Handler return value.
"""
try:
handler = self._extension_handlers[ext]
except KeyError:
@ -733,6 +911,14 @@ class NetworkManager(QNetworkAccessManager):
Extend QNetworkAccessManager::createRequest to save requests in
self._requests.
Args:
op: Operation op
req: const QNetworkRequest & req
outgoing_data: QIODevice * outgoingData
Return:
A QNetworkReply.
"""
reply = super().createRequest(op, req, outgoing_data)
self._requests[id(reply)] = reply

View File

@ -133,7 +133,11 @@ class CompletionView(QTreeView):
Used by tab_handler.
upwards -- Get previous item, not next.
Args:
upwards: Get previous item, not next.
Return:
A QModelIndex.
"""
idx = self.selectionModel().currentIndex()
@ -156,7 +160,8 @@ class CompletionView(QTreeView):
Called from cmd_text_changed().
model -- A QAbstractItemModel with available completions.
Args:
model: A QAbstractItemModel with available completions.
"""
self.model.srcmodel = self._completion_models[model]
@ -168,7 +173,12 @@ class CompletionView(QTreeView):
"""Resize the completion area to the statusbar geometry.
Slot for the resized signal of the statusbar.
geom -- A QRect containing the statusbar geometry.
Args:
geom: A QRect containing the statusbar geometry.
Raises:
AssertionError if new geometry is invalid.
"""
bottomleft = geom.topLeft()
@ -185,6 +195,9 @@ class CompletionView(QTreeView):
Adjust the height of the completion if it was configured as a
percentage.
Args:
geom: A QRect containing the browser geometry.
"""
if self._height_perc is None:
return
@ -197,7 +210,9 @@ class CompletionView(QTreeView):
"""Move the completion area to the statusbar geometry.
Slot for the moved signal of the statusbar.
pos -- A QPoint containing the statusbar position.
Args:
pos: A QPoint containing the statusbar position.
"""
self.move(pos - self._height)
@ -207,7 +222,9 @@ class CompletionView(QTreeView):
"""Check if completions are available and activate them.
Slot for the textChanged signal of the statusbar command widget.
text -- The new text
Args:
text: The new text
"""
if self._ignore_next:
@ -235,7 +252,11 @@ class CompletionView(QTreeView):
Select the previous/next item and write the new text to the
statusbar. Called by key_(s)tab_handler in statusbar.command.
shift -- Whether shift is pressed or not.
Args:
shift: Whether shift is pressed or not.
Emit:
append_cmd_text: When a command text should be set/appended.
"""
if not self._completing:
@ -300,7 +321,8 @@ class _CompletionItemDelegate(QStyledItemDelegate):
This is the main part where we differ from the original implementation
in Qt: We use a QTextDocument to draw text.
index of the item of the item -- The QModelIndex of the item to draw.
Args:
index -- The QModelIndex of the item to draw.
"""
if not self._opt.text:
@ -347,7 +369,8 @@ class _CompletionItemDelegate(QStyledItemDelegate):
def _draw_textdoc(self, text_rect):
"""Draw the QTextDocument of an item.
text_rect -- The QRect to clip the drawing to.
Args:
text_rect: The QRect to clip the drawing to.
"""
clip = QRectF(0, 0, text_rect.width(), text_rect.height())
@ -356,7 +379,8 @@ class _CompletionItemDelegate(QStyledItemDelegate):
def _get_textdoc(self, index):
"""Create the QTextDocument of an item.
index -- The QModelIndex of the item to draw.
Args:
index: The QModelIndex of the item to draw.
"""
# FIXME we probably should do eliding here. See
@ -422,6 +446,13 @@ class _CompletionItemDelegate(QStyledItemDelegate):
Return the cell size based on the QTextDocument size, but might not
work correctly yet.
Args:
option: const QStyleOptionViewItem & option
index: const QModelIndex & index
Return:
A QSize with the recommended size.
"""
value = index.data(Qt.SizeHintRole)
if value is not None:
@ -436,7 +467,14 @@ class _CompletionItemDelegate(QStyledItemDelegate):
return size + QSize(10, 1)
def paint(self, painter, option, index):
"""Override the QStyledItemDelegate paint function."""
"""Override the QStyledItemDelegate paint function.
Args:
painter: QPainter * painter
option: const QStyleOptionViewItem & option
index: const QModelIndex & index
"""
self._painter = painter
self._painter.save()
self._opt = QStyleOptionViewItem(option)

View File

@ -43,6 +43,14 @@ class CrashDialog(QDialog):
"""
def __init__(self, pages, cmdhist, exc):
"""Constructor for CrashDialog.
Args:
pages: A list of the open pages (URLs as strings)
cmdhist: A list with the command history (as strings)
exc: An exception tuple (type, value, traceback)
"""
super().__init__()
self.setFixedSize(500, 350)
self.setWindowTitle('Whoops!')
@ -82,7 +90,17 @@ class CrashDialog(QDialog):
self._vbox.addLayout(self._hbox)
def _crash_info(self, pages, cmdhist, exc):
"""Gather crash information to display."""
"""Gather crash information to display.
Args:
pages: A list of the open pages (URLs as strings)
cmdhist: A list with the command history (as strings)
exc: An exception tuple (type, value, traceback)
Return:
The string to display.
"""
outputs = [
('Version info', version()),
('Exception', ''.join(traceback.format_exception(*exc))),

View File

@ -116,7 +116,7 @@ class StatusBar(QWidget):
def error(self, val):
"""Setter for self.error, so it can be used as Qt property.
Re-sets the stylesheet after setting the value, so everything gets
Re-set the stylesheet after setting the value, so everything gets
updated by Qt properly.
"""
@ -137,7 +137,11 @@ class StatusBar(QWidget):
def resizeEvent(self, e):
"""Extend resizeEvent of QWidget to emit a resized signal afterwards.
e -- The QResizeEvent.
Args:
e: The QResizeEvent.
Emit:
resized: Always emitted.
"""
super().resizeEvent(e)
@ -146,7 +150,11 @@ class StatusBar(QWidget):
def moveEvent(self, e):
"""Extend moveEvent of QWidget to emit a moved signal afterwards.
e -- The QMoveEvent.
Args:
e: The QMoveEvent.
Emit:
moved: Always emitted.
"""
super().moveEvent(e)
@ -278,7 +286,14 @@ class _Command(QLineEdit):
@pyqtSlot()
def _on_return_pressed(self):
"""Handle the command in the status bar."""
"""Handle the command in the status bar.
Emit:
got_cmd: If a new cmd was entered.
got_search: If a new search was entered.
got_search_rev: If a new reverse search was entered.
"""
signals = {
':': self.got_cmd,
'/': self.got_search,
@ -294,19 +309,37 @@ class _Command(QLineEdit):
@pyqtSlot(str)
def set_cmd_text(self, text):
"""Preset the statusbar to some text."""
"""Preset the statusbar to some text.
Args:
text: The text to set (string).
"""
self.setText(text)
self.setFocus()
@pyqtSlot(str)
def on_append_cmd_text(self, text):
"""Append text to the commandline."""
"""Append text to the commandline.
Args:
text: The text to set (string).
"""
# FIXME do the right thing here
self.setText(':' + text)
self.setFocus()
def focusOutEvent(self, e):
"""Clear the statusbar text if it's explicitely unfocused."""
"""Clear the statusbar text if it's explicitely unfocused.
Args:
e: The QFocusEvent.
Emit:
hide_completion: Always emitted so the completion is hidden.
"""
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
self.setText('')
@ -315,7 +348,12 @@ class _Command(QLineEdit):
super().focusOutEvent(e)
def focusInEvent(self, e):
"""Clear error message when the statusbar is focused."""
"""Clear error message when the statusbar is focused.
Args:
e: The QFocusEvent.
"""
self._statusbar.clear_error()
super().focusInEvent(e)
@ -327,10 +365,12 @@ class _CommandValidator(QValidator):
def validate(self, string, pos):
"""Override QValidator::validate.
string -- The string to validate.
pos -- The current curser position.
Args:
string: The string to validate.
pos: The current curser position.
Return a tuple (status, string, pos) as a QValidator should.
Return:
A tuple (status, string, pos) as a QValidator should.
"""
if any(string.startswith(c) for c in keys.startchars):
@ -400,14 +440,20 @@ class TextBase(QLabel):
def _update_elided_text(self, width):
"""Update the elided text when necessary.
width -- The maximal width the text should take.
Args:
width: The maximal width the text should take.
"""
self._elided_text = self.fontMetrics().elidedText(
self.text(), self._elidemode, width, Qt.TextShowMnemonic)
def setText(self, txt):
"""Extend QLabel::setText to update the elided text afterwards."""
"""Extend QLabel::setText to update the elided text afterwards.
Args:
txt: The text to set (string).
"""
super().setText(txt)
self._update_elided_text(self.geometry().width())
@ -441,7 +487,12 @@ class _Text(TextBase):
self._old_text = ''
def set_error(self, text):
"""Display an error message and save current text in old_text."""
"""Display an error message and save current text in old_text.
Args:
text: The text to set (string).
"""
self._old_text = self.text()
self.setText(text)
@ -463,7 +514,13 @@ class _Percentage(TextBase):
@pyqtSlot(int, int)
def set_perc(self, _, y):
"""Setter to be used as a Qt slot."""
"""Setter to be used as a Qt slot.
Args:
_: The x percentage (int), currently ignored.
y: The y percentage (int)
"""
if y == 0:
self.setText('[top]')
elif y == 100:
@ -508,7 +565,13 @@ class _Url(TextBase):
"""
def __init__(self, bar, elidemode=Qt.ElideMiddle):
"""Override TextBase::__init__ to elide in the middle by default."""
"""Override TextBase::__init__ to elide in the middle by default.
Args:
bar: The statusbar (parent) object.
elidemode: How to elide the text.
"""
super().__init__(bar, elidemode)
self.setObjectName(self.__class__.__name__)
self.setStyleSheet(config.get_stylesheet(self._STYLESHEET))
@ -530,13 +593,23 @@ class _Url(TextBase):
@pyqtSlot(bool)
def on_loading_finished(self, ok):
"""Slot for cur_loading_finished. Colors the URL according to ok."""
"""Slot for cur_loading_finished. Colors the URL according to ok.
Args:
ok: Whether loading finished successfully (True) or not (False).
"""
# FIXME: set color to warn if there was an SSL error
self.urltype = 'success' if ok else 'error'
@pyqtSlot(str)
def set_url(self, s):
"""Setter to be used as a Qt slot."""
"""Setter to be used as a Qt slot.
Args:
s: The URL to set.
"""
self.setText(urlstring(s))
self.urltype = 'normal'
@ -548,6 +621,11 @@ class _Url(TextBase):
Saves old shown URL in self._old_url and restores it later if a link is
"un-hovered" when it gets called with empty parameters.
Args:
link: The link which was hovered (string)
title: The title of the hovered link (string)
text: The text of the hovered link (string)
"""
if link:
if self._old_url is None: