Get rid of most @property's.

They were problematic because they're executing hidden code, and also PyQt
hides exceptions happening inside them.
This commit is contained in:
Florian Bruhin 2014-09-02 21:54:07 +02:00
parent a2e457ccc3
commit ccfc0b3c19
25 changed files with 274 additions and 425 deletions

View File

@ -471,7 +471,7 @@ class Application(QApplication):
return pages
if self.mainwindow.tabs is None:
return pages
for tab in self.mainwindow.tabs.widgets:
for tab in self.mainwindow.tabs.widgets():
try:
url = tab.cur_url.toString(
QUrl.RemovePassword | QUrl.FullyEncoded)
@ -586,7 +586,7 @@ class Application(QApplication):
# exceptions occur.
if pages is None:
pages = []
for tab in self.mainwindow.tabs.widgets:
for tab in self.mainwindow.tabs.widgets():
urlstr = tab.cur_url.toString(
QUrl.RemovePassword | QUrl.FullyEncoded)
if urlstr:

View File

@ -491,7 +491,7 @@ class CommandDispatcher:
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_only(self):
"""Close all tabs except for the current one."""
for tab in self._tabs.widgets:
for tab in self._tabs.widgets():
if tab is self._tabs.currentWidget():
continue
self._tabs.close_tab(tab)

View File

@ -43,14 +43,10 @@ class DownloadItem(QObject):
Attributes:
reply: The QNetworkReply associated with this download.
percentage: How many percent were downloaded successfully.
None if unknown.
bytes_done: How many bytes there are already downloaded.
bytes_total: The total count of bytes.
None if the total is unknown.
speed: The current download speed, in bytes per second.
remaining_time: The time remaining for the download.
None if not enough data is available yet.
fileobj: The file object to download the file to.
filename: The filename of the download.
is_cancelled: Whether the download was cancelled.
@ -120,13 +116,19 @@ class DownloadItem(QObject):
"""
speed = utils.format_size(self.speed, suffix='B/s')
down = utils.format_size(self.bytes_done, suffix='B')
if all(e is None for e in (self.percentage, self.remaining_time,
self.bytes_total)):
perc = self._percentage()
remaining = self._remaining_time()
if all(e is None for e in (perc, remaining, self.bytes_total)):
return ('{name} [{speed:>10}|{down}]'.format(
name=self.basename, speed=speed, down=down))
perc = '??' if self.percentage is None else round(self.percentage)
remaining = (utils.format_seconds(self.remaining_time)
if self.remaining_time is not None else '?')
if perc is None:
perc = '??'
else:
perc = round(perc)
if remaining is None:
remaining = '?'
else:
remaining = utils.format_seconds(remaining)
total = utils.format_size(self.bytes_total, suffix='B')
return ('{name} [{speed:>10}|{remaining:>5}|{perc:>2}%|'
'{down}/{total}]'.format(name=self.basename, speed=speed,
@ -145,17 +147,15 @@ class DownloadItem(QObject):
self.error.emit(e.strerror)
self.finished.emit()
@property
def percentage(self):
"""Property to get the current download percentage."""
def _percentage(self):
"""The current download percentage, or None if unknown."""
if self.bytes_total == 0 or self.bytes_total is None:
return None
else:
return 100 * self.bytes_done / self.bytes_total
@property
def remaining_time(self):
"""Property to get the remaining download time in seconds."""
def _remaining_time(self):
"""The remaining download time in seconds, or None."""
if self.bytes_total is None or not self.speed_avg:
# No average yet or we don't know the total size.
return None
@ -172,10 +172,10 @@ class DownloadItem(QObject):
start = config.get('colors', 'downloads.bg.start')
stop = config.get('colors', 'downloads.bg.stop')
system = config.get('colors', 'downloads.bg.system')
if self.percentage is None:
if self._percentage() is None:
return start
else:
return utils.interpolate_color(start, stop, self.percentage,
return utils.interpolate_color(start, stop, self._percentage(),
system)
def cancel(self):

View File

@ -65,25 +65,13 @@ class HintContext:
def __init__(self):
self.elems = {}
self._target = None
self.target = None
self.baseurl = None
self.to_follow = None
self.frames = []
self.connected_frames = []
self.args = []
@property
def target(self):
"""Getter for target so we can define a setter."""
return self._target
@target.setter
def target(self, val):
"""Setter for target to do type checking."""
if not isinstance(val, Target):
raise TypeError("Target {} is no Target member!".format(val))
self._target = val
def get_args(self, urlstr):
"""Get the arguments, with {hint-url} replaced by the given URL."""
args = []

View File

@ -79,7 +79,7 @@ class Command:
"""
# We don't use modeman.instance() here to avoid a circular import
# of qutebrowser.keyinput.modeman.
curmode = QCoreApplication.instance().modeman.mode
curmode = QCoreApplication.instance().modeman.mode()
if self.modes is not None and curmode not in self.modes:
mode_names = '/'.join(mode.name for mode in self.modes)
raise cmdexc.PrerequisitesError(

View File

@ -198,7 +198,7 @@ class ConfigManager(QObject):
"""Get the option items as string for sect."""
lines = []
for optname, option in sect.items():
value = option.get_first_value(startlayer='conf')
value = option.value(startlayer='conf')
for c in self.KEY_ESCAPE:
if optname.startswith(c):
optname = optname.replace(c, self.ESCAPE_CHAR + c, 1)
@ -243,7 +243,7 @@ class ConfigManager(QObject):
if not raw:
raise ValueError("items() with raw=True is not implemented!")
for optname, option in self.sections[sectname].items():
items.append((optname, option.value))
items.append((optname, option.value()))
return items
def has_option(self, sectname, optname):
@ -325,10 +325,10 @@ class ConfigManager(QObject):
except KeyError:
raise NoOptionError(optname, sectname)
if raw:
return val.value
mapping = {key: val.value for key, val in sect.values.items()}
return val.value()
mapping = {key: val.value() for key, val in sect.values.items()}
newval = self._interpolation.before_get(self, sectname, optname,
val.value, mapping)
val.value(), mapping)
if transformed:
newval = val.typ.transform(newval)
return newval
@ -403,7 +403,7 @@ class ConfigManager(QObject):
sect = self.sections[sectname]
except KeyError:
raise NoSectionError(sectname)
mapping = {key: val.value for key, val in sect.values.items()}
mapping = {key: val.value() for key, val in sect.values.items()}
interpolated = self._interpolation.before_get(self, sectname, optname,
value, mapping)
try:
@ -462,27 +462,27 @@ class SectionProxy(collections.abc.MutableMapping):
conf: The Config object.
name: The section name.
"""
self._conf = conf
self._name = name
self.conf = conf
self.name = name
def __repr__(self):
return '<{} {}>'.format(self.__class__.__name__, self._name)
return '<{} {}>'.format(self.__class__.__name__, self.name)
def __getitem__(self, key):
if not self._conf.has_option(self._name, key):
if not self.conf.has_option(self.name, key):
raise KeyError(key)
return self._conf.get(self._name, key)
return self.conf.get(self.name, key)
def __setitem__(self, key, value):
return self._conf.set('conf', self._name, key, value)
return self.conf.set('conf', self.name, key, value)
def __delitem__(self, key):
if not (self._conf.has_option(self._name, key) and
self._conf.remove_option(self._name, key)):
if not (self.conf.has_option(self.name, key) and
self.conf.remove_option(self.name, key)):
raise KeyError(key)
def __contains__(self, key):
return self._conf.has_option(self._name, key)
return self.conf.has_option(self.name, key)
def __len__(self):
return len(self._options())
@ -492,7 +492,7 @@ class SectionProxy(collections.abc.MutableMapping):
def _options(self):
"""Get the option keys from this section."""
return self._conf.sections[self._name].keys()
return self.conf.sections[self.name].keys()
def get(self, optname, *, raw=False): # pylint: disable=arguments-differ
"""Get a value from this section.
@ -504,14 +504,4 @@ class SectionProxy(collections.abc.MutableMapping):
optname: The option name to get.
raw: Whether to get a raw value or not.
"""
return self._conf.get(self._name, optname, raw=raw)
@property
def conf(self):
"""The conf object of the proxy is read-only."""
return self._conf
@property
def name(self):
"""The name of the section on a proxy is read-only."""
return self._name
return self.conf.get(self.name, optname, raw=raw)

View File

@ -120,12 +120,11 @@ class KeyValue(Section):
def dump_userconfig(self):
changed = []
for k, v in self.items():
if (v.values['temp'] is not None and
v.values['temp'] != v.values['default']):
changed.append((k, v.values['temp']))
elif (v.values['conf'] is not None and
v.values['conf'] != v.values['default']):
changed.append((k, v.values['conf']))
vals = v.values
if vals['temp'] is not None and vals['temp'] != vals['default']:
changed.append((k, vals['temp']))
elif vals['conf'] is not None and vals['conf'] != vals['default']:
changed.append((k, vals['conf']))
return changed
@ -172,8 +171,7 @@ class ValueList(Section):
self.values = collections.ChainMap(
self.layers['temp'], self.layers['conf'], self.layers['default'])
@property
def ordered_values(self):
def _ordered_values(self):
"""Get ordered values in layers.
This is more expensive than the ChainMap, but we need this for
@ -201,20 +199,20 @@ class ValueList(Section):
self.layers['temp'], self.layers['conf'])
for k, v in mapping.items():
try:
if v.value != self.layers['default'][k].value:
changed.append((k, v.value))
if v.value() != self.layers['default'][k].value():
changed.append((k, v.value()))
except KeyError:
changed.append((k, v.value))
changed.append((k, v.value()))
return changed
def __iter__(self):
"""Iterate over all set values."""
return self.ordered_values.__iter__()
return self._ordered_values().__iter__()
def items(self):
"""Get dict items."""
return self.ordered_values.items()
return self._ordered_values().items()
def keys(self):
"""Get value keys."""
return self.ordered_values.keys()
return self._ordered_values().keys()

View File

@ -31,8 +31,8 @@ class SettingValue:
Attributes:
typ: A BaseType subclass instance.
value: (readonly property) The currently valid, most important value.
_values: An OrderedDict with the values on different layers, with the
most significant layer first.
values: An OrderedDict with the values on different layers, with the
most significant layer first.
"""
def __init__(self, typ, default=None):
@ -43,28 +43,17 @@ class SettingValue:
default: Raw value to set.
"""
self.typ = typ
self._values = collections.OrderedDict.fromkeys(
self.values = collections.OrderedDict.fromkeys(
['temp', 'conf', 'default'])
self._values['default'] = default
self.values['default'] = default
def __str__(self):
"""Get raw string value."""
return self.value
@property
def value(self):
"""Get the currently valid value."""
return self.get_first_value()
@property
def default(self):
"""Get the default value."""
return self._values['default']
@property
def values(self):
"""Readonly property for _values."""
return self._values
return self.values['default']
def getlayers(self, startlayer):
"""Get a dict of values starting with startlayer.
@ -72,18 +61,18 @@ class SettingValue:
Args:
startlayer: The first layer to include.
"""
idx = list(self._values.keys()).index(startlayer)
d = collections.OrderedDict(list(self._values.items())[idx:])
idx = list(self.values.keys()).index(startlayer)
d = collections.OrderedDict(list(self.values.items())[idx:])
return d
def get_first_value(self, startlayer=None):
def value(self, startlayer=None):
"""Get the first valid value starting from startlayer.
Args:
startlayer: The first layer to include.
"""
if startlayer is None:
d = self._values
d = self.values
else:
d = self.getlayers(startlayer)
for val in d.values():
@ -94,8 +83,7 @@ class SettingValue:
def transformed(self):
"""Get the transformed value."""
v = self.value
return self.typ.transform(v)
return self.typ.transform(self.value())
def setv(self, layer, value, interpolated):
"""Set the value on a layer.
@ -107,4 +95,4 @@ class SettingValue:
interpolated: The interpolated value, for typechecking.
"""
self.typ.validate(interpolated)
self._values[layer] = value
self.values[layer] = value

View File

@ -73,7 +73,6 @@ class ModeManager(QObject):
"""Manager for keyboard modes.
Attributes:
mode: The current mode (readonly property).
passthrough: A list of modes in which to pass through events.
mainwindow: The mainwindow object
locked: Whether current mode is locked. This means the current mode can
@ -109,11 +108,10 @@ class ModeManager(QObject):
'forward-unbound-keys')
def __repr__(self):
return '<{} mode={}>'.format(self.__class__.__name__, self.mode)
return '<{} mode={}>'.format(self.__class__.__name__, self.mode())
@property
def mode(self):
"""Read-only property for the current mode."""
"""Get the current mode.."""
if not self._mode_stack:
return None
return self._mode_stack[-1]
@ -127,17 +125,18 @@ class ModeManager(QObject):
Return:
True if event should be filtered, False otherwise.
"""
handler = self._handlers[self.mode]
if self.mode != usertypes.KeyMode.insert:
curmode = self.mode()
handler = self._handlers[curmode]
if curmode != usertypes.KeyMode.insert:
log.modes.debug("got keypress in mode {} - calling handler "
"{}".format(self.mode, handler.__qualname__))
"{}".format(curmode, handler.__qualname__))
handled = handler(event) if handler is not None else False
is_non_alnum = bool(event.modifiers()) or not event.text().strip()
if handled:
filter_this = True
elif (self.mode in self.passthrough or
elif (curmode in self.passthrough or
self._forward_unbound_keys == 'all' or
(self._forward_unbound_keys == 'auto' and is_non_alnum)):
filter_this = False
@ -147,11 +146,11 @@ class ModeManager(QObject):
if not filter_this:
self._releaseevents_to_pass.append(event)
if self.mode != usertypes.KeyMode.insert:
if curmode != usertypes.KeyMode.insert:
log.modes.debug("handled: {}, forward-unbound-keys: {}, "
"passthrough: {}, is_non_alnum: {} --> filter: "
"{}".format(handled, self._forward_unbound_keys,
self.mode in self.passthrough,
curmode in self.passthrough,
is_non_alnum, filter_this))
return filter_this
@ -172,7 +171,7 @@ class ModeManager(QObject):
filter_this = False
else:
filter_this = True
if self.mode != usertypes.KeyMode.insert:
if self.mode() != usertypes.KeyMode.insert:
log.modes.debug("filter: {}".format(filter_this))
return filter_this
@ -205,9 +204,9 @@ class ModeManager(QObject):
raise TypeError("Mode {} is no KeyMode member!".format(mode))
if self.locked:
log.modes.debug("Not entering mode {} because mode is locked to "
"{}.".format(mode, self.mode))
"{}.".format(mode, self.mode()))
raise ModeLockedError("Mode is currently locked to {}".format(
self.mode))
self.mode()))
log.modes.debug("Entering mode {}{}".format(
mode, '' if reason is None else ' (reason: {})'.format(reason)))
if mode not in self._handlers:
@ -256,9 +255,9 @@ class ModeManager(QObject):
not_modes=[usertypes.KeyMode.normal], hide=True)
def leave_current_mode(self):
"""Leave the mode we're currently in."""
if self.mode == usertypes.KeyMode.normal:
if self.mode() == usertypes.KeyMode.normal:
raise ValueError("Can't leave normal mode!")
self.leave(self.mode, 'leave current')
self.leave(self.mode(), 'leave current')
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
@ -278,7 +277,7 @@ class ModeManager(QObject):
Return:
True if event should be filtered, False otherwise.
"""
if self.mode is None:
if self.mode() is None:
# We got events before mode is set, so just pass them through.
return False
typ = event.type()

View File

@ -88,7 +88,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
Attributes:
_filtertext: The text to filter with.
last_press: The nature of the last keypress, a LastPress member.
_last_press: The nature of the last keypress, a LastPress member.
"""
fire_hint = pyqtSignal(str)
@ -97,22 +97,9 @@ class HintKeyParser(keyparser.CommandKeyParser):
def __init__(self, parent=None):
super().__init__(parent, supports_count=False, supports_chains=True)
self._filtertext = ''
self._last_press = None
self.last_press = LastPress.none
self._last_press = LastPress.none
self.read_config('keybind.hint')
@property
def last_press(self):
"""Getter for last_press so we can define a setter."""
return self._last_press
@last_press.setter
def last_press(self, val):
"""Setter for last_press to do typechecking."""
if not isinstance(val, LastPress):
raise TypeError("Value {} is no LastPress member!".format(val))
self._last_press = val
def _handle_special_key(self, e):
"""Override _handle_special_key to handle string filtering.
@ -132,14 +119,14 @@ class HintKeyParser(keyparser.CommandKeyParser):
e.key(), e.text()))
if e.key() == Qt.Key_Backspace:
log.keyboard.debug("Got backspace, mode {}, filtertext '{}', "
"keystring '{}'".format(self.last_press,
"keystring '{}'".format(self._last_press,
self._filtertext,
self._keystring))
if self.last_press == LastPress.filtertext and self._filtertext:
if self._last_press == LastPress.filtertext and self._filtertext:
self._filtertext = self._filtertext[:-1]
self.filter_hints.emit(self._filtertext)
return True
elif self.last_press == LastPress.keystring and self._keystring:
elif self._last_press == LastPress.keystring and self._keystring:
self._keystring = self._keystring[:-1]
self.keystring_updated.emit(self._keystring)
return True
@ -152,7 +139,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
else:
self._filtertext += e.text()
self.filter_hints.emit(self._filtertext)
self.last_press = LastPress.filtertext
self._last_press = LastPress.filtertext
return True
def handle(self, e):
@ -168,12 +155,12 @@ class HintKeyParser(keyparser.CommandKeyParser):
if handled and self._keystring:
# A key has been added to the keystring (Match.partial)
self.keystring_updated.emit(self._keystring)
self.last_press = LastPress.keystring
self._last_press = LastPress.keystring
return handled
elif handled:
# We handled the key but the keystring is empty. This happens when
# match is Match.definitive, so a keychain has been completed.
self.last_press = LastPress.none
self._last_press = LastPress.none
return handled
else:
# We couldn't find a keychain so we check if it's a special key.

View File

@ -43,7 +43,6 @@ class History:
"""Command history.
Attributes:
browsing: If we're currently browsing the history (property).
history: A list of executed commands, with newer commands at the end.
_tmphist: Temporary history for history browsing (as NeighborList)
"""
@ -63,8 +62,7 @@ class History:
def __getitem__(self, idx):
return self.history[idx]
@property
def browsing(self):
def is_browsing(self):
"""Check _tmphist to see if we're browsing."""
return self._tmphist is not None
@ -101,7 +99,7 @@ class History:
ValueError if start() wasn't called.
HistoryEndReachedError if the first item was reached.
"""
if not self.browsing:
if not self.is_browsing():
raise ValueError("Currently not browsing history")
try:
return self._tmphist.previtem()
@ -117,7 +115,7 @@ class History:
ValueError if start() wasn't called.
HistoryEndReachedError if the last item was reached.
"""
if not self.browsing:
if not self.is_browsing():
raise ValueError("Currently not browsing history")
try:
return self._tmphist.nextitem()

View File

@ -35,7 +35,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
Attributes:
srcmodel: The source model of this QSFPM.
_pattern: The pattern to filter with, used in pattern property.
_pattern: The pattern to filter with.
"""
def __init__(self, source, parent=None):
@ -44,13 +44,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
self.srcmodel = source
self._pattern = ''
@property
def pattern(self):
"""Getter for pattern."""
return self._pattern
@pattern.setter
def pattern(self, val):
def set_pattern(self, val):
"""Setter for pattern.
Invalidates the filter and re-sorts the model.
@ -70,8 +64,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
self.sort(sortcol)
self.invalidate()
@property
def item_count(self):
def count(self):
"""Get the count of non-toplevel items currently visible.
Note this only iterates one level deep, as we only need root items
@ -121,7 +114,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
def setSourceModel(self, model):
"""Override QSortFilterProxyModel's setSourceModel to clear pattern."""
log.completion.debug("Setting source model: {}".format(model))
self.pattern = ''
self.set_pattern('')
self.srcmodel = model
super().setSourceModel(model)
@ -135,7 +128,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
parent: The parent item QModelIndex.
Return:
True if self.pattern is contained in item, or if it's a root item
True if self._pattern is contained in item, or if it's a root item
(category). False in all other cases
"""
if parent == QModelIndex():
@ -144,14 +137,14 @@ class CompletionFilterModel(QSortFilterProxyModel):
qtutils.ensure_valid(idx)
data = self.srcmodel.data(idx)
# TODO more sophisticated filtering
if not self.pattern:
if not self._pattern:
return True
return self.pattern in data
return self._pattern in data
def lessThan(self, lindex, rindex):
"""Custom sorting implementation.
Prefers all items which start with self.pattern. Other than that, uses
Prefers all items which start with self._pattern. Other than that, uses
normal Python string sorting.
Args:
@ -173,8 +166,8 @@ class CompletionFilterModel(QSortFilterProxyModel):
left = self.srcmodel.data(lindex)
right = self.srcmodel.data(rindex)
leftstart = left.startswith(self.pattern)
rightstart = right.startswith(self.pattern)
leftstart = left.startswith(self._pattern)
rightstart = right.startswith(self._pattern)
if leftstart and rightstart:
return left < right

View File

@ -148,8 +148,7 @@ class Completer(QObject):
data = model.data(indexes[0])
if data is None:
return
if model.item_count == 1 and config.get('completion',
'quick-complete'):
if model.count() == 1 and config.get('completion', 'quick-complete'):
# If we only have one item, we want to apply it immediately
# and go on to the next part.
self.change_completed_part.emit(data, True)
@ -192,13 +191,13 @@ class Completer(QObject):
return
pattern = parts[cursor_part] if parts else ''
self.view.model().pattern = pattern
self.view.model().set_pattern(pattern)
log.completion.debug(
"New completion for {}: {}, with pattern '{}'".format(
parts, model.srcmodel.__class__.__name__, pattern))
if self.view.model().item_count == 0:
if self.view.model().count() == 0:
self.view.hide()
return

View File

@ -46,13 +46,13 @@ def parse_content_disposition(reply):
try:
content_disposition = rfc6266.parse_headers(
bytes(reply.rawHeader('Content-Disposition')))
filename = content_disposition.filename_unsafe
filename = content_disposition.filename()
except UnicodeDecodeError as e:
log.misc.warning("Error while getting filename: {}: {}".format(
e.__class__.__name__, e))
filename = None
else:
is_inline = content_disposition.is_inline
is_inline = content_disposition.is_inline()
# Then try to get filename from url
if not filename:
filename = reply.url().path()

View File

@ -36,8 +36,7 @@ class ReadlineBridge:
def __init__(self):
self.deleted = {}
@property
def widget(self):
def _widget(self):
"""Get the currently active QLineEdit."""
w = QApplication.instance().focusWidget()
if isinstance(w, QLineEdit):
@ -52,9 +51,10 @@ class ReadlineBridge:
This acts like readline's backward-char.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorBackward(False)
widget.cursorBackward(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -63,9 +63,10 @@ class ReadlineBridge:
This acts like readline's forward-char.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorForward(False)
widget.cursorForward(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -74,9 +75,10 @@ class ReadlineBridge:
This acts like readline's backward-word.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorWordBackward(False)
widget.cursorWordBackward(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -85,9 +87,10 @@ class ReadlineBridge:
This acts like readline's forward-word.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorWordForward(False)
widget.cursorWordForward(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -96,9 +99,10 @@ class ReadlineBridge:
This acts like readline's beginning-of-line.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.home(False)
widget.home(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -107,9 +111,10 @@ class ReadlineBridge:
This acts like readline's end-of-line.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.end(False)
widget.end(False)
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -118,11 +123,12 @@ class ReadlineBridge:
This acts like readline's unix-line-discard.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.home(True)
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
widget.home(True)
self.deleted[widget] = widget.selectedText()
widget.del_()
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -131,11 +137,12 @@ class ReadlineBridge:
This acts like readline's kill-line.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.end(True)
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
widget.end(True)
self.deleted[widget] = widget.selectedText()
widget.del_()
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -144,11 +151,12 @@ class ReadlineBridge:
This acts like readline's unix-word-rubout.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorWordBackward(True)
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
widget.cursorWordBackward(True)
self.deleted[widget] = widget.selectedText()
widget.del_()
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -157,11 +165,12 @@ class ReadlineBridge:
This acts like readline's kill-word.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.cursorWordForward(True)
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
widget.cursorWordForward(True)
self.deleted[widget] = widget.selectedText()
widget.del_()
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -170,9 +179,10 @@ class ReadlineBridge:
This acts like readline's yank.
"""
if self.widget is None or self.widget not in self.deleted:
widget = self._widget()
if widget is None or widget not in self.deleted:
return
self.widget.insert(self.deleted[self.widget])
widget.insert(self.deleted[widget])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -181,9 +191,10 @@ class ReadlineBridge:
This acts like readline's delete-char.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.del_()
widget.del_()
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
@ -192,6 +203,7 @@ class ReadlineBridge:
This acts like readline's backward-delete-char.
"""
if self.widget is None:
widget = self._widget()
if widget is None:
return
self.widget.backspace()
widget.backspace()

View File

@ -250,18 +250,17 @@ class ContentDisposition:
assert isinstance(param, ExtDispositionParm)
self.assocs['filename*'] = parse_ext_value(param.value).string
@property
def filename_unsafe(self):
def filename(self):
"""The filename from the Content-Disposition header or None.
On safety:
This property records the intent of the sender.
You shouldn't use this sender-controlled value as a filesystem
path, it can be insecure. Serving files with this filename can be
dangerous as well, due to a certain browser using the part after the
dot for mime-sniffing.
Saving it to a database is fine by itself though.
This property records the intent of the sender.
You shouldn't use this sender-controlled value as a filesystem path, it
can be insecure. Serving files with this filename can be dangerous as
well, due to a certain browser using the part after the dot for
mime-sniffing. Saving it to a database is fine by itself though.
"""
if 'filename*' in self.assocs:
@ -270,11 +269,10 @@ class ContentDisposition:
# XXX Reject non-ascii (parsed via qdtext) here?
return self.assocs['filename']
@property
def is_inline(self):
"""If this property is true, the file should be handled inline.
"""Return if the file should be handled inline.
Otherwise, and unless your application supports other dispositions
If not, and unless your application supports other dispositions
than the standard inline and attachment, it should be handled
as an attachment.
"""

View File

@ -60,8 +60,7 @@ class ConsoleLineEdit(misc.CommandLineEdit):
self.returnPressed.connect(self.execute)
self.setText('')
@property
def curprompt(self):
def _curprompt(self):
"""Get the prompt which is visible currently."""
return sys.ps2 if self._more else sys.ps1
@ -79,7 +78,7 @@ class ConsoleLineEdit(misc.CommandLineEdit):
"""Push a line to the interpreter."""
self._buffer.append(line)
source = '\n'.join(self._buffer)
self.write.emit(self.curprompt + line)
self.write.emit(self._curprompt() + line)
# We do two special things with the contextmanagers here:
# - We replace stdout/stderr to capture output. Even if we could
# override InteractiveInterpreter's write method, most things are
@ -89,14 +88,14 @@ class ConsoleLineEdit(misc.CommandLineEdit):
# printed and don't ooen a crashdialog.
with utils.fake_io(self.write.emit), utils.disabled_excepthook():
self._more = self._interpreter.runsource(source, '<console>')
self.set_prompt(self.curprompt)
self.set_prompt(self._curprompt())
if not self._more:
self._buffer = []
def history_prev(self):
"""Go back in the history."""
try:
if not self.history.browsing:
if not self.history.is_browsing():
item = self.history.start(self.text().strip())
else:
item = self.history.previtem()
@ -107,7 +106,7 @@ class ConsoleLineEdit(misc.CommandLineEdit):
def history_next(self):
"""Go forward in the history."""
if not self.history.browsing:
if not self.history.is_browsing():
return
try:
item = self.history.nextitem()
@ -117,12 +116,12 @@ class ConsoleLineEdit(misc.CommandLineEdit):
def setText(self, text):
"""Override setText to always prepend the prompt."""
super().setText(self.curprompt + text)
super().setText(self._curprompt() + text)
def text(self):
"""Override text to strip the prompt."""
text = super().text()
return text[len(self.curprompt):]
return text[len(self._curprompt()):]
def keyPressEvent(self, e):
"""Override keyPressEvent to handle up/down keypresses."""

View File

@ -65,14 +65,12 @@ class StatusBar(QWidget):
For some reason we need to have this as class attribute so
pyqtProperty works correctly.
_prompt_active: If we're currently in prompt-mode, accessed through the
prompt_active property.
_prompt_active: If we're currently in prompt-mode.
For some reason we need to have this as class attribute
so pyqtProperty works correctly.
_insert_active: If we're currently in insert mode, accessed through the
insert_active property.
_insert_active: If we're currently in insert mode.
For some reason we need to have this as class attribute
so pyqtProperty works correctly.
@ -180,8 +178,7 @@ class StatusBar(QWidget):
# pylint: disable=method-hidden
return self._error
@error.setter
def error(self, val):
def _set_error(self, val):
"""Setter for self.error, so it can be used as Qt property.
Re-set the stylesheet after setting the value, so everything gets
@ -206,9 +203,8 @@ class StatusBar(QWidget):
# pylint: disable=method-hidden
return self._prompt_active
@prompt_active.setter
def prompt_active(self, val):
"""Setter for self.prompt_active, so it can be used as Qt property.
def _set_prompt_active(self, val):
"""Setter for self.prompt_active.
Re-set the stylesheet after setting the value, so everything gets
updated by Qt properly.
@ -223,9 +219,8 @@ class StatusBar(QWidget):
# pylint: disable=method-hidden
return self._insert_active
@insert_active.setter
def insert_active(self, val):
"""Setter for self.insert_active, so it can be used as Qt property.
def _set_insert_active(self, val):
"""Setter for self.insert_active.
Re-set the stylesheet after setting the value, so everything gets
updated by Qt properly.
@ -239,8 +234,8 @@ class StatusBar(QWidget):
try:
error, text = self._text_queue.popleft()
except IndexError:
self.error = False
self.txt.temptext = ''
self._set_error(False)
self.txt.set_text(self.txt.Text.temp, '')
self._text_pop_timer.stop()
# If a previous widget was interrupted by an error, restore it.
if self._previous_widget == PreviousWidget.prompt:
@ -255,12 +250,12 @@ class StatusBar(QWidget):
log.statusbar.debug("Displaying {} message: {}".format(
'error' if error else 'text', text))
log.statusbar.debug("Remaining: {}".format(self._text_queue))
self.error = error
self.txt.temptext = text
self._set_error(error)
self.txt.set_text(self.txt.Text.temp, text)
def _show_cmd_widget(self):
"""Show command widget instead of temporary text."""
self.error = False
self._set_error(False)
self._previous_widget = PreviousWidget.prompt
if self._text_pop_timer.isActive():
self._timer_was_active = True
@ -281,8 +276,8 @@ class StatusBar(QWidget):
def _show_prompt_widget(self):
"""Show prompt widget instead of temporary text."""
self.error = False
self.prompt_active = True
self._set_error(False)
self._set_prompt_active(True)
self._previous_widget = PreviousWidget.prompt
if self._text_pop_timer.isActive():
self._timer_was_active = True
@ -291,7 +286,7 @@ class StatusBar(QWidget):
def _hide_prompt_widget(self):
"""Show temporary text instead of prompt widget."""
self.prompt_active = False
self._set_prompt_active(False)
self._previous_widget = PreviousWidget.none
log.statusbar.debug("Hiding prompt widget, queue: {}".format(
self._text_queue))
@ -328,8 +323,8 @@ class StatusBar(QWidget):
# immediately. We then start the pop_timer only to restore the
# normal state in 2 seconds.
log.statusbar.debug("Displaying immediately")
self.error = error
self.txt.temptext = text
self._set_error(error)
self.txt.set_text(self.txt.Text.temp, text)
self._text_pop_timer.start()
elif self._text_queue and self._text_queue[-1] == (error, text):
# If we get the same message multiple times in a row and we're
@ -341,8 +336,8 @@ class StatusBar(QWidget):
# We display this immediately and restart the timer.to clear it and
# display the rest of the queue later.
log.statusbar.debug("Moving to beginning of queue")
self.error = error
self.txt.temptext = text
self._set_error(error)
self.txt.set_text(self.txt.Text.temp, text)
self._text_pop_timer.start()
else:
# There are still some messages to be displayed, so we queue this
@ -376,23 +371,24 @@ class StatusBar(QWidget):
@pyqtSlot(str)
def set_text(self, val):
"""Set a normal (persistent) text in the status bar."""
self.txt.normaltext = val
self.txt.set_text(self.txt.Text.normal, val)
@pyqtSlot(usertypes.KeyMode)
def on_mode_entered(self, mode):
"""Mark certain modes in the commandline."""
if mode in modeman.instance().passthrough:
self.txt.normaltext = "-- {} MODE --".format(mode.name.upper())
text = "-- {} MODE --".format(mode.name.upper())
self.txt.set_text(self.txt.Text.normal, text)
if mode == usertypes.KeyMode.insert:
self.insert_active = True
self._set_insert_active(True)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Clear marked mode."""
if mode in modeman.instance().passthrough:
self.txt.normaltext = ""
self.txt.set_text(self.txt.Text.normal, '')
if mode == usertypes.KeyMode.insert:
self.insert_active = False
self._set_insert_active(False)
@pyqtSlot(str, str)
def on_config_changed(self, section, option):

View File

@ -81,9 +81,8 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
self.cursorPositionChanged.connect(self.on_cursor_position_changed)
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored)
@property
def prefix(self):
"""Property to get the current command prefix entered."""
"""Get the currently entered command prefix."""
text = self.text()
if not text:
return ''
@ -92,10 +91,9 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
else:
return ''
@property
def parts(self):
"""Property to get the text split up in parts."""
text = self.text()[len(self.prefix):]
def split(self):
"""Get the text split up in parts."""
text = self.text()[len(self.prefix()):]
if not text:
# When only ":" is entered, we already have one imaginary part,
# which just is empty at the moment.
@ -122,8 +120,8 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
spaces = True
else:
spaces = False
cursor_pos -= len(self.prefix)
for i, part in enumerate(self.parts):
cursor_pos -= len(self.prefix())
for i, part in enumerate(self.split()):
if cursor_pos <= len(part):
# foo| bar
self.cursor_part = i
@ -140,7 +138,8 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
@pyqtSlot()
def on_cursor_position_changed(self):
"""Update completion when the cursor position changed."""
self.update_completion.emit(self.prefix, self.parts, self.cursor_part)
self.update_completion.emit(self.prefix(), self.split(),
self.cursor_part)
@pyqtSlot(str)
def set_cmd_text(self, text):
@ -156,7 +155,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
self.setText(text)
if old_text != text:
# We want the completion to pop out here.
self.update_completion.emit(self.prefix, self.parts,
self.update_completion.emit(self.prefix(), self.split(),
self.cursor_part)
self.setFocus()
self.show_cmd.emit()
@ -189,17 +188,17 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
including a trailing space and we shouldn't continue
completing the current item.
"""
parts = self.parts[:]
parts = self.split()
log.completion.debug("changing part {} to '{}'".format(
self.cursor_part, newtext))
parts[self.cursor_part] = newtext
# We want to place the cursor directly after the part we just changed.
cursor_str = self.prefix + ' '.join(parts[:self.cursor_part + 1])
cursor_str = self.prefix() + ' '.join(parts[:self.cursor_part + 1])
if immediate:
# If we should complete immediately, we want to move the cursor by
# one more char, to get to the next field.
cursor_str += ' '
text = self.prefix + ' '.join(parts)
text = self.prefix() + ' '.join(parts)
if immediate and self.cursor_part == len(parts) - 1:
# If we should complete immediately and we're completing the last
# part in the commandline, we automatically add a space.
@ -215,7 +214,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
def command_history_prev(self):
"""Go back in the commandline history."""
try:
if not self.history.browsing:
if not self.history.is_browsing():
item = self.history.start(self.text().strip())
else:
item = self.history.previtem()
@ -229,7 +228,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
modes=[usertypes.KeyMode.command])
def command_history_next(self):
"""Go forward in the commandline history."""
if not self.history.browsing:
if not self.history.is_browsing():
return
try:
item = self.history.nextitem()

View File

@ -283,7 +283,7 @@ class Prompter:
try:
modeman.enter(mode, 'question asked')
except modeman.ModeLockedError:
if modeman.instance().mode != usertypes.KeyMode.prompt:
if modeman.instance().mode() != usertypes.KeyMode.prompt:
question.abort()
return None
modeman.instance().locked = True

View File

@ -23,6 +23,7 @@ from PyQt5.QtCore import pyqtSlot
from qutebrowser.config import config
from qutebrowser.widgets.statusbar import textbase
from qutebrowser.utils import usertypes
class Text(textbase.TextBase):
@ -31,80 +32,63 @@ class Text(textbase.TextBase):
Attributes:
_normaltext: The "permanent" text. Never automatically cleared.
Accessed via normaltext property.
_temptext: The temporary text to display.
Accessed via temptext property.
_jstext: The text javascript wants to display.
Accessed via jstext property.
The temptext is shown from StatusBar when a temporary text or error is
available. If not, the permanent text is shown.
"""
Text = usertypes.enum('Text', 'normal', 'temp', 'js')
def __init__(self, parent=None):
super().__init__(parent)
self._normaltext = ''
self._temptext = ''
self._jstext = ''
@property
def normaltext(self):
"""Getter for normaltext so we can define a setter."""
return self._normaltext
def set_text(self, which, text):
"""Set a text.
@normaltext.setter
def normaltext(self, val):
"""Setter for normaltext to update text display after setting."""
self._normaltext = val
self._update_text()
@property
def temptext(self):
"""Getter for temptext so we can define a setter."""
return self._temptext
@temptext.setter
def temptext(self, val):
"""Setter for temptext to update text display after setting."""
self._temptext = val
self._update_text()
@property
def jstext(self):
"""Getter for jstext so we can define a setter."""
return self._jstext
@jstext.setter
def jstext(self, val):
"""Setter for jstext to update text display after setting."""
self._jstext = val
Args:
which: Which text to set, a self.Text instance.
text: The text to set.
"""
if which is self.Text.normal:
self._normaltext = text
elif which is self.Text.temp:
self._temptext = text
elif which is self.Text.js:
self._jstext = text
else:
raise ValueError("Invalid value {} for which!".format(which))
self._update_text()
def _update_text(self):
"""Update QLabel text when needed."""
if self.temptext:
self.setText(self.temptext)
elif self.jstext and config.get('ui', 'display-statusbar-messages'):
self.setText(self.jstext)
elif self.normaltext:
self.setText(self.normaltext)
if self._temptext:
self.setText(self._temptext)
elif self._jstext and config.get('ui', 'display-statusbar-messages'):
self.setText(self._jstext)
elif self._normaltext:
self.setText(self._normaltext)
else:
self.setText('')
@pyqtSlot(str)
def on_statusbar_message(self, val):
"""Called when javascript tries to set a statusbar message."""
self.jstext = val
self._jstext = val
@pyqtSlot()
def on_load_started(self):
"""Clear jstext when page loading started."""
self.jstext = ''
self._jstext = ''
@pyqtSlot(int)
def on_tab_changed(self, tab):
"""Set the correct jstext when the current tab changed."""
self.jstext = tab.statusbar_message
self._jstext = tab.statusbar_message
@pyqtSlot(str, str)
def on_config_changed(self, section, option):

View File

@ -37,9 +37,9 @@ class UrlText(textbase.TextBase):
"""URL displayed in the statusbar.
Attributes:
normal_url: The normal URL to be displayed as a UrlType instance.
normal_url_type: The type of the normal URL as a UrlType instance.
hover_url: The URL we're currently hovering over.
_normal_url: The normal URL to be displayed as a UrlType instance.
_normal_url_type: The type of the normal URL as a UrlType instance.
_hover_url: The URL we're currently hovering over.
_ssl_errors: Whether SSL errors occured while loading.
Class attributes:
@ -96,64 +96,18 @@ class UrlText(textbase.TextBase):
else:
return self._urltype.name
@urltype.setter
def urltype(self, val):
"""Setter for self.urltype to update stylesheets after it is set."""
if not isinstance(val, UrlType):
raise TypeError("Type {} is no UrlType member!".format(val))
self._urltype = val
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
@property
def hover_url(self):
"""Getter so we can define a setter."""
return self._hover_url
@hover_url.setter
def hover_url(self, val):
"""Setter to update displayed URL when hover_url was set."""
self._hover_url = val
self._update_url()
@property
def normal_url(self):
"""Getter so we can define a setter."""
return self._normal_url
@normal_url.setter
def normal_url(self, val):
"""Setter to update displayed URL when normal_url was set."""
self._normal_url = val
self._update_url()
@property
def normal_url_type(self):
"""Getter so we can define a setter."""
return self._normal_url_type
@normal_url_type.setter
def normal_url_type(self, val):
"""Setter to update displayed URL when normal_url_type was set.
Args:
val: The value as an UrlType instance.
"""
if not isinstance(val, UrlType):
raise TypeError("Type {} is no UrlType member!".format(val))
self._normal_url_type = val
self._update_url()
def _update_url(self):
"""Update the displayed URL if the url or the hover url changed."""
if self.hover_url is not None:
self.setText(self.hover_url)
self.urltype = UrlType.hover
elif self.normal_url is not None:
self.setText(self.normal_url)
self.urltype = self.normal_url_type
if self._hover_url is not None:
self.setText(self._hover_url)
self._urltype = UrlType.hover
elif self._normal_url is not None:
self.setText(self._normal_url)
self._urltype = self._normal_url_type
else:
self.setText('')
self.urltype = UrlType.normal
self._urltype = UrlType.normal
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
@pyqtSlot(str)
def on_load_status_changed(self, status_str):
@ -165,9 +119,10 @@ class UrlText(textbase.TextBase):
status = webview.LoadStatus[status_str]
if status in (webview.LoadStatus.success, webview.LoadStatus.error,
webview.LoadStatus.warn):
self.normal_url_type = UrlType[status_str]
self._normal_url_type = UrlType[status_str]
else:
self.normal_url_type = UrlType.normal
self._normal_url_type = UrlType.normal
self._update_url()
@pyqtSlot(str)
def set_url(self, s):
@ -176,8 +131,9 @@ class UrlText(textbase.TextBase):
Args:
s: The URL to set as string.
"""
self.normal_url = s
self.normal_url_type = UrlType.normal
self._normal_url = s
self._normal_url_type = UrlType.normal
self._update_url()
@pyqtSlot(str, str, str)
def set_hover_url(self, link, _title, _text):
@ -192,13 +148,15 @@ class UrlText(textbase.TextBase):
_text: The text of the hovered link (string)
"""
if link:
self.hover_url = link
self._hover_url = link
else:
self.hover_url = None
self._hover_url = None
self._update_url()
@pyqtSlot(int)
def on_tab_changed(self, tab):
"""Update URL if the tab changed."""
self.hover_url = None
self.normal_url = tab.cur_url.toDisplayString()
self._hover_url = None
self._normal_url = tab.cur_url.toDisplayString()
self.on_load_status_changed(tab.load_status.name)
self._update_url()

View File

@ -120,12 +120,12 @@ class TabbedBrowser(tabwidget.TabWidget):
return '<{} with {} tabs>'.format(self.__class__.__name__,
self.count())
@property
def widgets(self):
"""Get a list of open tab widgets.
We don't implement this as generator so we can delete tabs while
iterating over the list."""
iterating over the list.
"""
w = []
for i in range(self.count()):
w.append(self.widget(i))
@ -227,7 +227,7 @@ class TabbedBrowser(tabwidget.TabWidget):
except TypeError as e:
log.destroy.debug("Error while shutting down tabs: {}: {}".format(
e.__class__.__name__, e))
for tab in self.widgets:
for tab in self.widgets():
self._remove_tab(tab)
def close_tab(self, tab):
@ -413,7 +413,7 @@ class TabbedBrowser(tabwidget.TabWidget):
tab.on_config_changed(section, option)
if (section, option) == ('tabbar', 'show-favicons'):
show = config.get('tabs', 'show-favicons')
for i, tab in enumerate(self.widgets):
for i, tab in enumerate(self.widgets()):
if show:
self.setTabIcon(i, tab.icon())
else:

View File

@ -50,15 +50,14 @@ class WebView(QWebView):
scroll_pos: The current scroll position as (x%, y%) tuple.
statusbar_message: The current javscript statusbar message.
inspector: The QWebInspector used for this webview.
load_status: loading status of this page (index into LoadStatus)
open_target: Where to open the next tab ("normal", "tab", "tab_bg")
_page: The QWebPage behind the view
_cur_url: The current URL (accessed via cur_url property).
_load_status: loading status of this page (index into LoadStatus)
Accessed via load_status property.
_has_ssl_errors: Whether SSL errors occured during loading.
_zoom: A NeighborList with the zoom levels.
_old_scroll_pos: The old scroll position.
_force_open_target: Override for _open_target.
_force_open_target: Override for open_target.
_check_insertmode: If True, in mouseReleaseEvent we should check if we
need to enter/leave insert mode.
@ -78,7 +77,6 @@ class WebView(QWebView):
def __init__(self, parent):
super().__init__(parent)
self._load_status = None
self.load_status = LoadStatus.none
self._check_insertmode = False
self.tabbedbrowser = parent
@ -86,7 +84,6 @@ class WebView(QWebView):
self.scroll_pos = (-1, -1)
self.statusbar_message = ''
self._old_scroll_pos = (-1, -1)
self._open_target = None
self.open_target = usertypes.ClickTarget.normal
self._force_open_target = None
self._zoom = None
@ -116,25 +113,7 @@ class WebView(QWebView):
url = self.url().toDisplayString()
return "WebView(url='{}')".format(utils.elide(url, 50))
@property
def open_target(self):
"""Getter for open_target so we can define a setter."""
return self._open_target
@open_target.setter
def open_target(self, val):
"""Setter for open_target to do type checking."""
if not isinstance(val, usertypes.ClickTarget):
raise TypeError("Target {} is no ClickTarget member!".format(val))
self._open_target = val
@property
def load_status(self):
"""Getter for load_status."""
return self._load_status
@load_status.setter
def load_status(self, val):
def _set_load_status(self, val):
"""Setter for load_status.
Emit:
@ -143,27 +122,9 @@ class WebView(QWebView):
if not isinstance(val, LoadStatus):
raise TypeError("Type {} is no LoadStatus member!".format(val))
log.webview.debug("load status for {}: {}".format(repr(self), val))
self._load_status = val
self.load_status = val
self.load_status_changed.emit(val.name)
@property
def cur_url(self):
"""Getter for cur_url so we can define a setter."""
return self._cur_url
@cur_url.setter
def cur_url(self, url):
"""Setter for cur_url to emit a signal..
Arg:
url: The new URL as a QUrl.
Emit:
url_text_changed: Always emitted.
"""
self._cur_url = url
self.url_text_changed.emit(url.toDisplayString())
def _init_neighborlist(self):
"""Initialize the _zoom neighborlist."""
levels = config.get('ui', 'zoom-levels')
@ -302,6 +263,7 @@ class WebView(QWebView):
log.webview.debug("New title: {}".format(urlstr))
self.titleChanged.emit(urlstr)
self.cur_url = url
self.url_text_changed.emit(url.toDisplayString())
return self.load(url)
def zoom_perc(self, perc, fuzzyval=True):
@ -356,6 +318,7 @@ class WebView(QWebView):
"""Update cur_url when URL has changed."""
qtutils.ensure_valid(url)
self.cur_url = url
self.url_text_changed.emit(url.toDisplayString())
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
@ -374,20 +337,20 @@ class WebView(QWebView):
"""Leave insert/hint mode and set vars when a new page is loading."""
self.progress = 0
self._has_ssl_errors = False
self.load_status = LoadStatus.loading
self._set_load_status(LoadStatus.loading)
@pyqtSlot(bool)
def on_load_finished(self, ok):
"""Handle auto-insert-mode after loading finished."""
if ok and not self._has_ssl_errors:
self.load_status = LoadStatus.success
self._set_load_status(LoadStatus.success)
elif ok:
self.load_status = LoadStatus.warn
self._set_load_status(LoadStatus.warn)
else:
self.load_status = LoadStatus.error
self._set_load_status(LoadStatus.error)
if not config.get('input', 'auto-insert-mode'):
return
if modeman.instance().mode == usertypes.KeyMode.insert or not ok:
if modeman.instance().mode() == usertypes.KeyMode.insert or not ok:
return
frame = self.page().currentFrame()
elem = frame.findFirstElement(':focus')
@ -467,7 +430,7 @@ class WebView(QWebView):
This does the following things:
- Check if a link was clicked with the middle button or Ctrl and
set the _open_target attribute accordingly.
set the open_target attribute accordingly.
- Emit the editable_elem_selected signal if an editable element was
clicked.

View File

@ -376,9 +376,9 @@ def generate_settings(f):
except KeyError:
f.write(" * +{}+".format(val) + "\n")
f.write("\n")
if option.default:
if option.default():
f.write("Default: +pass:[{}]+\n".format(html.escape(
option.default)))
option.default())))
else:
f.write("Default: empty\n")