Use simple enums for constants
This commit is contained in:
parent
91e7565d1e
commit
4ebe643ea6
1
THANKS
1
THANKS
@ -27,6 +27,7 @@ valuable ones:
|
|||||||
- Bleeding Fingers
|
- Bleeding Fingers
|
||||||
- artyom.stv
|
- artyom.stv
|
||||||
- hank
|
- hank
|
||||||
|
- Alec Thomas
|
||||||
|
|
||||||
Thanks to these people for helpful bits and pieces in the Qt bugtracker and IRC
|
Thanks to these people for helpful bits and pieces in the Qt bugtracker and IRC
|
||||||
channels:
|
channels:
|
||||||
|
1
TODO
1
TODO
@ -7,7 +7,6 @@ Style
|
|||||||
=====
|
=====
|
||||||
|
|
||||||
_foo = QApplication.instance().obj.foo for global singletons?
|
_foo = QApplication.instance().obj.foo for global singletons?
|
||||||
Use py3.4 Enums with a backport to qutebrowser.utils?
|
|
||||||
initialize completion models at some nicer place (not in widget)
|
initialize completion models at some nicer place (not in widget)
|
||||||
|
|
||||||
Major features
|
Major features
|
||||||
|
@ -33,6 +33,7 @@ import qutebrowser.utils.message as message
|
|||||||
import qutebrowser.commands.utils as cmdutils
|
import qutebrowser.commands.utils as cmdutils
|
||||||
import qutebrowser.utils.webelem as webelem
|
import qutebrowser.utils.webelem as webelem
|
||||||
import qutebrowser.config.config as config
|
import qutebrowser.config.config as config
|
||||||
|
import qutebrowser.browser.hints as hints
|
||||||
from qutebrowser.utils.misc import shell_escape
|
from qutebrowser.utils.misc import shell_escape
|
||||||
|
|
||||||
|
|
||||||
@ -216,21 +217,31 @@ class CurCommandDispatcher(QObject):
|
|||||||
break
|
break
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cur')
|
@cmdutils.register(instance='mainwindow.tabs.cur')
|
||||||
def hint(self, mode='all', target='normal'):
|
def hint(self, groupstr='all', targetstr='normal'):
|
||||||
"""Start hinting.
|
"""Start hinting.
|
||||||
|
|
||||||
Command handler for :hint.
|
Command handler for :hint.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode: The hinting mode to use.
|
groupstr: The hinting mode to use.
|
||||||
target: Where to open the links.
|
targetstr: Where to open the links.
|
||||||
"""
|
"""
|
||||||
widget = self._tabs.currentWidget()
|
widget = self._tabs.currentWidget()
|
||||||
frame = widget.page_.currentFrame()
|
frame = widget.page_.currentFrame()
|
||||||
if frame is None:
|
if frame is None:
|
||||||
message.error("No frame focused!")
|
message.error("No frame focused!")
|
||||||
else:
|
return
|
||||||
widget.hintmanager.start(frame, widget.url(), mode, target)
|
try:
|
||||||
|
group = getattr(webelem.Group, groupstr)
|
||||||
|
except AttributeError:
|
||||||
|
message.error("Unknown hinting group {}!".format(groupstr))
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
target = getattr(hints.Target, targetstr)
|
||||||
|
except AttributeError:
|
||||||
|
message.error("Unknown hinting target {}!".format(targetstr))
|
||||||
|
return
|
||||||
|
widget.hintmanager.start(frame, widget.url(), group, target)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cur', hide=True)
|
@cmdutils.register(instance='mainwindow.tabs.cur', hide=True)
|
||||||
def follow_hint(self):
|
def follow_hint(self):
|
||||||
|
@ -30,11 +30,16 @@ import qutebrowser.keyinput.modeman as modeman
|
|||||||
import qutebrowser.utils.message as message
|
import qutebrowser.utils.message as message
|
||||||
import qutebrowser.utils.url as urlutils
|
import qutebrowser.utils.url as urlutils
|
||||||
import qutebrowser.utils.webelem as webelem
|
import qutebrowser.utils.webelem as webelem
|
||||||
|
from qutebrowser.utils.usertypes import enum
|
||||||
|
|
||||||
|
|
||||||
ElemTuple = namedtuple('ElemTuple', 'elem, label')
|
ElemTuple = namedtuple('ElemTuple', 'elem, label')
|
||||||
|
|
||||||
|
|
||||||
|
Target = enum('normal', 'tab', 'bgtab', 'yank', 'yank_primary', 'cmd',
|
||||||
|
'cmd_tab', 'cmd_bgtab', 'rapid')
|
||||||
|
|
||||||
|
|
||||||
class HintManager(QObject):
|
class HintManager(QObject):
|
||||||
|
|
||||||
"""Manage drawing hints over links or other elements.
|
"""Manage drawing hints over links or other elements.
|
||||||
@ -47,10 +52,10 @@ class HintManager(QObject):
|
|||||||
_elems: A mapping from keystrings to (elem, label) namedtuples.
|
_elems: A mapping from keystrings to (elem, label) namedtuples.
|
||||||
_baseurl: The URL of the current page.
|
_baseurl: The URL of the current page.
|
||||||
_target: What to do with the opened links.
|
_target: What to do with the opened links.
|
||||||
'normal'/'tab'/'bgtab': Get passed to BrowserTab.
|
normal/tab/bgtab: Get passed to BrowserTab.
|
||||||
'yank'/'yank_primary': Yank to clipboard/primary selection
|
yank/yank_primary: Yank to clipboard/primary selection
|
||||||
'cmd'/'cmd_tab'/'cmd_bgtab': Enter link to commandline
|
cmd/cmd_tab/cmd_bgtab: Enter link to commandline
|
||||||
'rapid': Rapid mode with background tabs
|
rapid: Rapid mode with background tabs
|
||||||
_to_follow: The link to follow when enter is pressed.
|
_to_follow: The link to follow when enter is pressed.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
@ -217,11 +222,11 @@ class HintManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
elem: The QWebElement to click.
|
elem: The QWebElement to click.
|
||||||
"""
|
"""
|
||||||
if self._target == 'rapid':
|
if self._target == Target.rapid:
|
||||||
target = 'bgtab'
|
target = Target.bgtab
|
||||||
else:
|
else:
|
||||||
target = self._target
|
target = self._target
|
||||||
self.set_open_target.emit(target)
|
self.set_open_target.emit(Target.reverse_mapping[target])
|
||||||
point = elem.geometry().topLeft()
|
point = elem.geometry().topLeft()
|
||||||
scrollpos = self._frame.scrollPosition()
|
scrollpos = self._frame.scrollPosition()
|
||||||
logging.debug("Clicking on \"{}\" at {}/{} - {}/{}".format(
|
logging.debug("Clicking on \"{}\" at {}/{} - {}/{}".format(
|
||||||
@ -245,7 +250,7 @@ class HintManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
link: The URL to open.
|
link: The URL to open.
|
||||||
"""
|
"""
|
||||||
sel = self._target == 'yank_primary'
|
sel = self._target == Target.yank_primary
|
||||||
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
||||||
QApplication.clipboard().setText(urlutils.urlstring(link), mode)
|
QApplication.clipboard().setText(urlutils.urlstring(link), mode)
|
||||||
message.info("URL yanked to {}".format("primary selection" if sel
|
message.info("URL yanked to {}".format("primary selection" if sel
|
||||||
@ -258,9 +263,9 @@ class HintManager(QObject):
|
|||||||
link: The link to open.
|
link: The link to open.
|
||||||
"""
|
"""
|
||||||
commands = {
|
commands = {
|
||||||
'cmd': 'open',
|
Target.cmd: 'open',
|
||||||
'cmd_tab': 'tabopen',
|
Target.cmd_tab: 'tabopen',
|
||||||
'cmd_bgtab': 'backtabopen',
|
Target.cmd_bgtab: 'backtabopen',
|
||||||
}
|
}
|
||||||
message.set_cmd_text(':{} {}'.format(commands[self._target],
|
message.set_cmd_text(':{} {}'.format(commands[self._target],
|
||||||
urlutils.urlstring(link)))
|
urlutils.urlstring(link)))
|
||||||
@ -325,23 +330,20 @@ class HintManager(QObject):
|
|||||||
return
|
return
|
||||||
self.openurl.emit(link, newtab)
|
self.openurl.emit(link, newtab)
|
||||||
|
|
||||||
def start(self, frame, baseurl, mode='all', target='normal'):
|
def start(self, frame, baseurl, group=webelem.Group.all,
|
||||||
|
target=Target.normal):
|
||||||
"""Start hinting.
|
"""Start hinting.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
frame: The QWebFrame to place hints in.
|
frame: The QWebFrame to place hints in.
|
||||||
baseurl: URL of the current page.
|
baseurl: URL of the current page.
|
||||||
mode: The mode to be used.
|
group: Which group of elements to hint.
|
||||||
target: What to do with the link. See attribute docstring.
|
target: What to do with the link. See attribute docstring.
|
||||||
|
|
||||||
Emit:
|
Emit:
|
||||||
hint_strings_updated: Emitted to update keypraser.
|
hint_strings_updated: Emitted to update keypraser.
|
||||||
"""
|
"""
|
||||||
try:
|
elems = frame.findAllElements(webelem.SELECTORS[group])
|
||||||
elems = frame.findAllElements(webelem.SELECTORS[mode])
|
|
||||||
except KeyError:
|
|
||||||
message.error("Hinting mode '{}' does not exist!".format(mode))
|
|
||||||
return
|
|
||||||
self._target = target
|
self._target = target
|
||||||
self._baseurl = baseurl
|
self._baseurl = baseurl
|
||||||
if frame is None:
|
if frame is None:
|
||||||
@ -350,7 +352,7 @@ class HintManager(QObject):
|
|||||||
# on_mode_left, we are extra careful here.
|
# on_mode_left, we are extra careful here.
|
||||||
raise ValueError("start() was called with frame=None")
|
raise ValueError("start() was called with frame=None")
|
||||||
self._frame = frame
|
self._frame = frame
|
||||||
filterfunc = webelem.FILTERS.get(mode, lambda e: True)
|
filterfunc = webelem.FILTERS.get(group, lambda e: True)
|
||||||
visible_elems = []
|
visible_elems = []
|
||||||
for e in elems:
|
for e in elems:
|
||||||
if filterfunc(e) and webelem.is_visible(e, self._frame):
|
if filterfunc(e) and webelem.is_visible(e, self._frame):
|
||||||
@ -359,21 +361,17 @@ class HintManager(QObject):
|
|||||||
message.error("No elements found.")
|
message.error("No elements found.")
|
||||||
return
|
return
|
||||||
texts = {
|
texts = {
|
||||||
'normal': "Follow hint...",
|
Target.normal: "Follow hint...",
|
||||||
'tab': "Follow hint in new tab...",
|
Target.tab: "Follow hint in new tab...",
|
||||||
'bgtab': "Follow hint in background tab...",
|
Target.bgtab: "Follow hint in background tab...",
|
||||||
'yank': "Yank hint to clipboard...",
|
Target.yank: "Yank hint to clipboard...",
|
||||||
'yank_primary': "Yank hint to primary selection...",
|
Target.yank_primary: "Yank hint to primary selection...",
|
||||||
'cmd': "Set hint in commandline...",
|
Target.cmd: "Set hint in commandline...",
|
||||||
'cmd_tab': "Set hint in commandline as new tab...",
|
Target.cmd_tab: "Set hint in commandline as new tab...",
|
||||||
'cmd_bgtab': "Set hint in commandline as background tab...",
|
Target.cmd_bgtab: "Set hint in commandline as background tab...",
|
||||||
'rapid': "Follow hint (rapid mode)...",
|
Target.rapid: "Follow hint (rapid mode)...",
|
||||||
}
|
}
|
||||||
try:
|
|
||||||
message.text(texts[target])
|
message.text(texts[target])
|
||||||
except KeyError:
|
|
||||||
message.error("Hinting target '{}' does not exist!".format(target))
|
|
||||||
return
|
|
||||||
strings = self._hint_strings(visible_elems)
|
strings = self._hint_strings(visible_elems)
|
||||||
for e, string in zip(visible_elems, strings):
|
for e, string in zip(visible_elems, strings):
|
||||||
label = self._draw_label(e, string)
|
label = self._draw_label(e, string)
|
||||||
@ -426,18 +424,18 @@ class HintManager(QObject):
|
|||||||
return
|
return
|
||||||
# Handlers which take a QWebElement
|
# Handlers which take a QWebElement
|
||||||
elem_handlers = {
|
elem_handlers = {
|
||||||
'normal': self._click,
|
Target.normal: self._click,
|
||||||
'tab': self._click,
|
Target.tab: self._click,
|
||||||
'bgtab': self._click,
|
Target.bgtab: self._click,
|
||||||
'rapid': self._click,
|
Target.rapid: self._click,
|
||||||
}
|
}
|
||||||
# Handlers which take a link string
|
# Handlers which take a link string
|
||||||
link_handlers = {
|
link_handlers = {
|
||||||
'yank': self._yank,
|
Target.yank: self._yank,
|
||||||
'yank_primary': self._yank,
|
Target.yank_primary: self._yank,
|
||||||
'cmd': self._preset_cmd_text,
|
Target.cmd: self._preset_cmd_text,
|
||||||
'cmd_tab': self._preset_cmd_text,
|
Target.cmd_tab: self._preset_cmd_text,
|
||||||
'cmd_bgtab': self._preset_cmd_text,
|
Target.cmd_bgtab: self._preset_cmd_text,
|
||||||
}
|
}
|
||||||
elem = self._elems[keystr].elem
|
elem = self._elems[keystr].elem
|
||||||
if self._target in elem_handlers:
|
if self._target in elem_handlers:
|
||||||
@ -448,7 +446,9 @@ class HintManager(QObject):
|
|||||||
message.error("No suitable link found for this element.")
|
message.error("No suitable link found for this element.")
|
||||||
return
|
return
|
||||||
link_handlers[self._target](link)
|
link_handlers[self._target](link)
|
||||||
if self._target != 'rapid':
|
else:
|
||||||
|
raise ValueError("No suitable handler found!")
|
||||||
|
if self._target != Target.rapid:
|
||||||
modeman.leave('hint')
|
modeman.leave('hint')
|
||||||
|
|
||||||
def follow_hint(self):
|
def follow_hint(self):
|
||||||
|
@ -30,95 +30,96 @@ from PyQt5.QtCore import pyqtSlot
|
|||||||
from PyQt5.QtWebKit import QWebSettings
|
from PyQt5.QtWebKit import QWebSettings
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
import qutebrowser.config.config as config
|
||||||
|
from qutebrowser.utils.usertypes import enum
|
||||||
|
|
||||||
ATTRIBUTE = 0
|
MapType = enum('attribute', 'setter', 'static_setter')
|
||||||
SETTER = 1
|
|
||||||
STATIC_SETTER = 2
|
|
||||||
|
|
||||||
|
|
||||||
MAPPINGS = {
|
MAPPINGS = {
|
||||||
# noqa
|
# noqa
|
||||||
'auto-load-images':
|
'auto-load-images':
|
||||||
(ATTRIBUTE, QWebSettings.AutoLoadImages),
|
(MapType.attribute, QWebSettings.AutoLoadImages),
|
||||||
'dns-prefetch-enabled':
|
'dns-prefetch-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.DnsPrefetchEnabled),
|
(MapType.attribute, QWebSettings.DnsPrefetchEnabled),
|
||||||
'javascript-enabled':
|
'javascript-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.JavascriptEnabled),
|
(MapType.attribute, QWebSettings.JavascriptEnabled),
|
||||||
#'java-enabled':
|
#'java-enabled':
|
||||||
# (ATTRIBUTE, QWebSettings.JavaEnabled),
|
# (MapType.attribute, QWebSettings.JavaEnabled),
|
||||||
'plugins-enabled':
|
'plugins-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.PluginsEnabled),
|
(MapType.attribute, QWebSettings.PluginsEnabled),
|
||||||
'private-browsing-enabled':
|
'private-browsing-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.PrivateBrowsingEnabled),
|
(MapType.attribute, QWebSettings.PrivateBrowsingEnabled),
|
||||||
'javascript-can-open-windows':
|
'javascript-can-open-windows':
|
||||||
(ATTRIBUTE, QWebSettings.JavascriptCanOpenWindows),
|
(MapType.attribute, QWebSettings.JavascriptCanOpenWindows),
|
||||||
'javascript-can-close-windows':
|
'javascript-can-close-windows':
|
||||||
(ATTRIBUTE, QWebSettings.JavascriptCanCloseWindows),
|
(MapType.attribute, QWebSettings.JavascriptCanCloseWindows),
|
||||||
'javascript-can-access-clipboard':
|
'javascript-can-access-clipboard':
|
||||||
(ATTRIBUTE, QWebSettings.JavascriptCanAccessClipboard),
|
(MapType.attribute, QWebSettings.JavascriptCanAccessClipboard),
|
||||||
'developer-extras-enabled':
|
'developer-extras-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.DeveloperExtrasEnabled),
|
(MapType.attribute, QWebSettings.DeveloperExtrasEnabled),
|
||||||
'spatial-navigation-enabled':
|
'spatial-navigation-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.SpatialNavigationEnabled),
|
(MapType.attribute, QWebSettings.SpatialNavigationEnabled),
|
||||||
'links-included-in-focus-chain':
|
'links-included-in-focus-chain':
|
||||||
(ATTRIBUTE, QWebSettings.LinksIncludedInFocusChain),
|
(MapType.attribute, QWebSettings.LinksIncludedInFocusChain),
|
||||||
'zoom-text-only':
|
'zoom-text-only':
|
||||||
(ATTRIBUTE, QWebSettings.ZoomTextOnly),
|
(MapType.attribute, QWebSettings.ZoomTextOnly),
|
||||||
'print-element-backgrounds':
|
'print-element-backgrounds':
|
||||||
(ATTRIBUTE, QWebSettings.PrintElementBackgrounds),
|
(MapType.attribute, QWebSettings.PrintElementBackgrounds),
|
||||||
'offline-storage-database-enabled':
|
'offline-storage-database-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.OfflineStorageDatabaseEnabled),
|
(MapType.attribute, QWebSettings.OfflineStorageDatabaseEnabled),
|
||||||
'offline-web-application-storage-enabled':
|
'offline-web-application-storage-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.OfflineWebApplicationCacheEnabled),
|
(MapType.attribute, QWebSettings.OfflineWebApplicationCacheEnabled),
|
||||||
'local-storage-enabled':
|
'local-storage-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.LocalStorageEnabled),
|
(MapType.attribute, QWebSettings.LocalStorageEnabled),
|
||||||
'local-content-can-access-remote-urls':
|
'local-content-can-access-remote-urls':
|
||||||
(ATTRIBUTE, QWebSettings.LocalContentCanAccessRemoteUrls),
|
(MapType.attribute, QWebSettings.LocalContentCanAccessRemoteUrls),
|
||||||
'local-content-can-access-file-urls':
|
'local-content-can-access-file-urls':
|
||||||
(ATTRIBUTE, QWebSettings.LocalContentCanAccessFileUrls),
|
(MapType.attribute, QWebSettings.LocalContentCanAccessFileUrls),
|
||||||
'xss-auditing-enabled':
|
'xss-auditing-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.XSSAuditingEnabled),
|
(MapType.attribute, QWebSettings.XSSAuditingEnabled),
|
||||||
#'accelerated-compositing-enabled':
|
#'accelerated-compositing-enabled':
|
||||||
# (ATTRIBUTE, QWebSettings.AcceleratedCompositingEnabled),
|
# (MapType.attribute, QWebSettings.AcceleratedCompositingEnabled),
|
||||||
#'tiled-backing-store-enabled':
|
#'tiled-backing-store-enabled':
|
||||||
# (ATTRIBUTE, QWebSettings.TiledBackingStoreEnabled),
|
# (MapType.attribute, QWebSettings.TiledBackingStoreEnabled),
|
||||||
'frame-flattening-enabled':
|
'frame-flattening-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.FrameFlatteningEnabled),
|
(MapType.attribute, QWebSettings.FrameFlatteningEnabled),
|
||||||
'site-specific-quirks-enabled':
|
'site-specific-quirks-enabled':
|
||||||
(ATTRIBUTE, QWebSettings.SiteSpecificQuirksEnabled),
|
(MapType.attribute, QWebSettings.SiteSpecificQuirksEnabled),
|
||||||
'user-stylesheet':
|
'user-stylesheet':
|
||||||
(SETTER, lambda qws, v: qws.setUserStyleSheetUrl(v)),
|
(MapType.setter, lambda qws, v: qws.setUserStyleSheetUrl(v)),
|
||||||
'css-media-type':
|
'css-media-type':
|
||||||
(SETTER, lambda qws, v: qws.setCSSMediaType(v)),
|
(MapType.setter, lambda qws, v: qws.setCSSMediaType(v)),
|
||||||
'default-encoding':
|
'default-encoding':
|
||||||
(SETTER, lambda qws, v: qws.setDefaultTextEncoding(v)),
|
(MapType.setter, lambda qws, v: qws.setDefaultTextEncoding(v)),
|
||||||
'font-family-standard':
|
'font-family-standard':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.StandardFont, v)),
|
qws.setFontFamily(QWebSettings.StandardFont, v)),
|
||||||
'font-family-fixed':
|
'font-family-fixed':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.FixedFont, v)),
|
qws.setFontFamily(QWebSettings.FixedFont, v)),
|
||||||
'font-family-serif':
|
'font-family-serif':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.SerifFont, v)),
|
qws.setFontFamily(QWebSettings.SerifFont, v)),
|
||||||
'font-family-sans-serif':
|
'font-family-sans-serif':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.SansSerifFont, v)),
|
qws.setFontFamily(QWebSettings.SansSerifFont, v)),
|
||||||
'font-family-cursive':
|
'font-family-cursive':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.CursiveFont, v)),
|
qws.setFontFamily(QWebSettings.CursiveFont, v)),
|
||||||
'font-family-fantasy':
|
'font-family-fantasy':
|
||||||
(SETTER, lambda qws, v:
|
(MapType.setter, lambda qws, v:
|
||||||
qws.setFontFamily(QWebSettings.FantasyFont, v)),
|
qws.setFontFamily(QWebSettings.FantasyFont, v)),
|
||||||
'maximum-pages-in-cache':
|
'maximum-pages-in-cache':
|
||||||
(STATIC_SETTER, lambda v: QWebSettings.setMaximumPagesInCache(v)),
|
(MapType.static_setter, lambda v:
|
||||||
|
QWebSettings.setMaximumPagesInCache(v)),
|
||||||
'object-cache-capacities':
|
'object-cache-capacities':
|
||||||
(STATIC_SETTER, lambda v: QWebSettings.setObjectCacheCapacities(*v)),
|
(MapType.static_setter, lambda v:
|
||||||
|
QWebSettings.setObjectCacheCapacities(*v)),
|
||||||
'offline-storage-default-quota':
|
'offline-storage-default-quota':
|
||||||
(STATIC_SETTER, lambda v:
|
(MapType.static_setter, lambda v:
|
||||||
QWebSettings.setOfflineStorageDefaultQuota(v)),
|
QWebSettings.setOfflineStorageDefaultQuota(v)),
|
||||||
'offline-web-application-cache-quota':
|
'offline-web-application-cache-quota':
|
||||||
(STATIC_SETTER, lambda v:
|
(MapType.static_setter, lambda v:
|
||||||
QWebSettings.setOfflineWebApplicationCacheQuota(v)),
|
QWebSettings.setOfflineWebApplicationCacheQuota(v)),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,15 +131,16 @@ def _set_setting(typ, arg, value):
|
|||||||
"""Set a QWebSettings setting.
|
"""Set a QWebSettings setting.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
typ: The type of the item (ATTRIBUTE/SETTER/STATIC_SETTER)
|
typ: The type of the item
|
||||||
|
(MapType.attribute/MapType.setter/MapType.static_setter)
|
||||||
arg: The argument (attribute/handler)
|
arg: The argument (attribute/handler)
|
||||||
value: The value to set.
|
value: The value to set.
|
||||||
"""
|
"""
|
||||||
if typ == ATTRIBUTE:
|
if typ == MapType.attribute:
|
||||||
settings.setAttribute(arg, value)
|
settings.setAttribute(arg, value)
|
||||||
elif typ == SETTER and value is not None:
|
elif typ == MapType.setter and value is not None:
|
||||||
arg(settings, value)
|
arg(settings, value)
|
||||||
elif typ == STATIC_SETTER and value is not None:
|
elif typ == MapType.static_setter and value is not None:
|
||||||
arg(value)
|
arg(value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject, QTimer
|
|||||||
from PyQt5.QtGui import QKeySequence
|
from PyQt5.QtGui import QKeySequence
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
import qutebrowser.config.config as config
|
||||||
|
from qutebrowser.utils.usertypes import enum
|
||||||
|
|
||||||
|
|
||||||
class BaseKeyParser(QObject):
|
class BaseKeyParser(QObject):
|
||||||
@ -35,14 +36,16 @@ class BaseKeyParser(QObject):
|
|||||||
execute() to do whatever they want to.
|
execute() to do whatever they want to.
|
||||||
|
|
||||||
Class Attributes:
|
Class Attributes:
|
||||||
MATCH_PARTIAL: Constant for a partial match (no keychain matched yet,
|
Match: types of a match between a binding and the keystring.
|
||||||
but it's still possible in the future.
|
partial: No keychain matched yet, but it's still possible in the
|
||||||
MATCH_DEFINITIVE: Constant for a full match (keychain matches exactly).
|
future.
|
||||||
MATCH_AMBIGUOUS: There are both a partial and a definitive match.
|
definitive: Keychain matches exactly.
|
||||||
MATCH_NONE: Constant for no match (no more matches possible).
|
ambiguous: There are both a partial and a definitive match.
|
||||||
|
none: No more matches possible.
|
||||||
|
|
||||||
TYPE_CHAIN: execute() was called via a chain-like keybinding
|
Types: type of a keybinding.
|
||||||
TYPE_SPECIAL: execute() was called via a special keybinding
|
chain: execute() was called via a chain-like keybinding
|
||||||
|
special: execute() was called via a special keybinding
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
bindings: Bound keybindings
|
bindings: Bound keybindings
|
||||||
@ -60,13 +63,8 @@ class BaseKeyParser(QObject):
|
|||||||
|
|
||||||
keystring_updated = pyqtSignal(str)
|
keystring_updated = pyqtSignal(str)
|
||||||
|
|
||||||
MATCH_PARTIAL = 0
|
Match = enum('partial', 'definitive', 'ambiguous', 'none')
|
||||||
MATCH_DEFINITIVE = 1
|
Type = enum('chain', 'special')
|
||||||
MATCH_AMBIGUOUS = 2
|
|
||||||
MATCH_NONE = 3
|
|
||||||
|
|
||||||
TYPE_CHAIN = 0
|
|
||||||
TYPE_SPECIAL = 1
|
|
||||||
|
|
||||||
def __init__(self, parent=None, supports_count=None,
|
def __init__(self, parent=None, supports_count=None,
|
||||||
supports_chains=False):
|
supports_chains=False):
|
||||||
@ -134,7 +132,7 @@ class BaseKeyParser(QObject):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
logging.debug("No binding found for {}.".format(modstr + keystr))
|
logging.debug("No binding found for {}.".format(modstr + keystr))
|
||||||
return False
|
return False
|
||||||
self.execute(cmdstr, self.TYPE_SPECIAL)
|
self.execute(cmdstr, self.Type.special)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _handle_single_key(self, e):
|
def _handle_single_key(self, e):
|
||||||
@ -173,15 +171,15 @@ class BaseKeyParser(QObject):
|
|||||||
|
|
||||||
(match, binding) = self._match_key(cmd_input)
|
(match, binding) = self._match_key(cmd_input)
|
||||||
|
|
||||||
if match == self.MATCH_DEFINITIVE:
|
if match == self.Match.definitive:
|
||||||
self._keystring = ''
|
self._keystring = ''
|
||||||
self.execute(binding, self.TYPE_CHAIN, count)
|
self.execute(binding, self.Type.chain, count)
|
||||||
elif match == self.MATCH_AMBIGUOUS:
|
elif match == self.Match.ambiguous:
|
||||||
self._handle_ambiguous_match(binding, count)
|
self._handle_ambiguous_match(binding, count)
|
||||||
elif match == self.MATCH_PARTIAL:
|
elif match == self.Match.partial:
|
||||||
logging.debug("No match for \"{}\" (added {})".format(
|
logging.debug("No match for \"{}\" (added {})".format(
|
||||||
self._keystring, txt))
|
self._keystring, txt))
|
||||||
elif match == self.MATCH_NONE:
|
elif match == self.Match.none:
|
||||||
logging.debug("Giving up with \"{}\", no matches".format(
|
logging.debug("Giving up with \"{}\", no matches".format(
|
||||||
self._keystring))
|
self._keystring))
|
||||||
self._keystring = ''
|
self._keystring = ''
|
||||||
@ -196,11 +194,11 @@ class BaseKeyParser(QObject):
|
|||||||
|
|
||||||
Return:
|
Return:
|
||||||
A tuple (matchtype, binding).
|
A tuple (matchtype, binding).
|
||||||
matchtype: MATCH_DEFINITIVE, MATCH_AMBIGUOUS, MATCH_PARTIAL or
|
matchtype: Match.definitive, Match.ambiguous, Match.partial or
|
||||||
MATCH_NONE
|
Match.none
|
||||||
binding: - None with MATCH_PARTIAL/MATCH_NONE
|
binding: - None with Match.partial/Match.none
|
||||||
- The found binding with MATCH_DEFINITIVE/
|
- The found binding with Match.definitive/
|
||||||
MATCH_AMBIGUOUS
|
Match.ambiguous
|
||||||
"""
|
"""
|
||||||
# A (cmd_input, binding) tuple (k, v of bindings) or None.
|
# A (cmd_input, binding) tuple (k, v of bindings) or None.
|
||||||
definitive_match = None
|
definitive_match = None
|
||||||
@ -219,13 +217,13 @@ class BaseKeyParser(QObject):
|
|||||||
partial_match = True
|
partial_match = True
|
||||||
break
|
break
|
||||||
if definitive_match is not None and partial_match:
|
if definitive_match is not None and partial_match:
|
||||||
return (self.MATCH_AMBIGUOUS, definitive_match[1])
|
return (self.Match.ambiguous, definitive_match[1])
|
||||||
elif definitive_match is not None:
|
elif definitive_match is not None:
|
||||||
return (self.MATCH_DEFINITIVE, definitive_match[1])
|
return (self.Match.definitive, definitive_match[1])
|
||||||
elif partial_match:
|
elif partial_match:
|
||||||
return (self.MATCH_PARTIAL, None)
|
return (self.Match.partial, None)
|
||||||
else:
|
else:
|
||||||
return (self.MATCH_NONE, None)
|
return (self.Match.none, None)
|
||||||
|
|
||||||
def _stop_delayed_exec(self):
|
def _stop_delayed_exec(self):
|
||||||
"""Stop a delayed execution if any is running."""
|
"""Stop a delayed execution if any is running."""
|
||||||
@ -246,7 +244,7 @@ class BaseKeyParser(QObject):
|
|||||||
if time == 0:
|
if time == 0:
|
||||||
# execute immediately
|
# execute immediately
|
||||||
self._keystring = ''
|
self._keystring = ''
|
||||||
self.execute(binding, self.TYPE_CHAIN, count)
|
self.execute(binding, self.Type.chain, count)
|
||||||
else:
|
else:
|
||||||
# execute in `time' ms
|
# execute in `time' ms
|
||||||
logging.debug("Scheduling execution of {} in {}ms".format(binding,
|
logging.debug("Scheduling execution of {} in {}ms".format(binding,
|
||||||
@ -271,7 +269,7 @@ class BaseKeyParser(QObject):
|
|||||||
self._timer = None
|
self._timer = None
|
||||||
self._keystring = ''
|
self._keystring = ''
|
||||||
self.keystring_updated.emit(self._keystring)
|
self.keystring_updated.emit(self._keystring)
|
||||||
self.execute(command, self.TYPE_CHAIN, count)
|
self.execute(command, self.Type.chain, count)
|
||||||
|
|
||||||
def handle(self, e):
|
def handle(self, e):
|
||||||
"""Handle a new keypress and call the respective handlers.
|
"""Handle a new keypress and call the respective handlers.
|
||||||
@ -329,7 +327,7 @@ class BaseKeyParser(QObject):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
cmdstr: The command to execute as a string.
|
cmdstr: The command to execute as a string.
|
||||||
keytype: TYPE_CHAIN or TYPE_SPECIAL
|
keytype: Type.chain or Type.special
|
||||||
count: The count if given.
|
count: The count if given.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -127,9 +127,9 @@ class HintKeyParser(CommandKeyParser):
|
|||||||
"""Handle a completed keychain.
|
"""Handle a completed keychain.
|
||||||
|
|
||||||
Emit:
|
Emit:
|
||||||
fire_hint: Emitted if keytype is TYPE_CHAIN
|
fire_hint: Emitted if keytype is chain
|
||||||
"""
|
"""
|
||||||
if keytype == self.TYPE_CHAIN:
|
if keytype == self.Type.chain:
|
||||||
self.fire_hint.emit(cmdstr)
|
self.fire_hint.emit(cmdstr)
|
||||||
else:
|
else:
|
||||||
# execute as command
|
# execute as command
|
||||||
|
@ -133,21 +133,21 @@ class OneTests(TestCase):
|
|||||||
self.nl = NeighborList([1], default=1)
|
self.nl = NeighborList([1], default=1)
|
||||||
|
|
||||||
def test_first_wrap(self):
|
def test_first_wrap(self):
|
||||||
self.nl._mode = NeighborList.WRAP
|
self.nl._mode = NeighborList.Modes.wrap
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.previtem(), 1)
|
self.assertEqual(self.nl.previtem(), 1)
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
|
|
||||||
def test_first_block(self):
|
def test_first_block(self):
|
||||||
self.nl._mode = NeighborList.BLOCK
|
self.nl._mode = NeighborList.Modes.block
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.previtem(), 1)
|
self.assertEqual(self.nl.previtem(), 1)
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
|
|
||||||
def test_first_raise(self):
|
def test_first_raise(self):
|
||||||
self.nl._mode = NeighborList.RAISE
|
self.nl._mode = NeighborList.Modes.exception
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
@ -155,21 +155,21 @@ class OneTests(TestCase):
|
|||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
|
|
||||||
def test_last_wrap(self):
|
def test_last_wrap(self):
|
||||||
self.nl._mode = NeighborList.WRAP
|
self.nl._mode = NeighborList.Modes.wrap
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.nextitem(), 1)
|
self.assertEqual(self.nl.nextitem(), 1)
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
|
|
||||||
def test_last_block(self):
|
def test_last_block(self):
|
||||||
self.nl._mode = NeighborList.BLOCK
|
self.nl._mode = NeighborList.Modes.block
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.nextitem(), 1)
|
self.assertEqual(self.nl.nextitem(), 1)
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
|
|
||||||
def test_last_raise(self):
|
def test_last_raise(self):
|
||||||
self.nl._mode = NeighborList.RAISE
|
self.nl._mode = NeighborList.Modes.exception
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
@ -179,11 +179,11 @@ class OneTests(TestCase):
|
|||||||
|
|
||||||
class BlockTests(TestCase):
|
class BlockTests(TestCase):
|
||||||
|
|
||||||
"""Tests with mode=BLOCK."""
|
"""Tests with mode=block."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
||||||
mode=NeighborList.BLOCK)
|
mode=NeighborList.Modes.block)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
@ -200,11 +200,11 @@ class BlockTests(TestCase):
|
|||||||
|
|
||||||
class WrapTests(TestCase):
|
class WrapTests(TestCase):
|
||||||
|
|
||||||
"""Tests with mode=WRAP."""
|
"""Tests with mode=wrap."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
||||||
mode=NeighborList.WRAP)
|
mode=NeighborList.Modes.wrap)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
@ -221,11 +221,11 @@ class WrapTests(TestCase):
|
|||||||
|
|
||||||
class RaiseTests(TestCase):
|
class RaiseTests(TestCase):
|
||||||
|
|
||||||
"""Tests with mode=RAISE."""
|
"""Tests with mode=exception."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
||||||
mode=NeighborList.RAISE)
|
mode=NeighborList.Modes.exception)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
|
@ -26,12 +26,31 @@ import logging
|
|||||||
_UNSET = object()
|
_UNSET = object()
|
||||||
|
|
||||||
|
|
||||||
|
def enum(*items, **named):
|
||||||
|
|
||||||
|
"""Factory for simple enumerations.
|
||||||
|
|
||||||
|
We really don't need more complex things here, so we don't use python3.4's
|
||||||
|
enum, because we'd have to backport things to 3.3 and maybe even 3.2.
|
||||||
|
|
||||||
|
Based on: http://stackoverflow.com/a/1695250/2085149
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*items: Items to be sequentally enumerated.
|
||||||
|
**named: Items to have a given position/number.
|
||||||
|
"""
|
||||||
|
enums = dict(zip(items, range(len(items))), **named)
|
||||||
|
reverse = dict((v, k) for k, v in enums.items())
|
||||||
|
enums['reverse_mapping'] = reverse
|
||||||
|
return type('Enum', (), enums)
|
||||||
|
|
||||||
|
|
||||||
class NeighborList:
|
class NeighborList:
|
||||||
|
|
||||||
"""A list of items which saves it current position.
|
"""A list of items which saves it current position.
|
||||||
|
|
||||||
Class attributes:
|
Class attributes:
|
||||||
BLOCK/WRAP/RAISE: Modes, see constructor documentation.
|
Modes: Different modes, see constructor documentation.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
idx: The current position in the list.
|
idx: The current position in the list.
|
||||||
@ -39,20 +58,18 @@ class NeighborList:
|
|||||||
_mode: The current mode.
|
_mode: The current mode.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
BLOCK = 0
|
Modes = enum('block', 'wrap', 'exception')
|
||||||
WRAP = 1
|
|
||||||
RAISE = 2
|
|
||||||
|
|
||||||
def __init__(self, items=None, default=_UNSET, mode=RAISE):
|
def __init__(self, items=None, default=_UNSET, mode=Modes.exception):
|
||||||
"""Constructor.
|
"""Constructor.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
items: The list of items to iterate in.
|
items: The list of items to iterate in.
|
||||||
_default: The initially selected value.
|
_default: The initially selected value.
|
||||||
_mode: Behaviour when the first/last item is reached.
|
_mode: Behaviour when the first/last item is reached.
|
||||||
BLOCK: Stay on the selected item
|
Modes.block: Stay on the selected item
|
||||||
WRAP: Wrap around to the other end
|
Modes.wrap: Wrap around to the other end
|
||||||
RAISE: Raise an IndexError.
|
Modes.exception: Raise an IndexError.
|
||||||
"""
|
"""
|
||||||
if items is None:
|
if items is None:
|
||||||
self._items = []
|
self._items = []
|
||||||
@ -80,7 +97,8 @@ class NeighborList:
|
|||||||
The new item.
|
The new item.
|
||||||
|
|
||||||
Raise:
|
Raise:
|
||||||
IndexError if the border of the list is reached and mode is RAISE.
|
IndexError if the border of the list is reached and mode is
|
||||||
|
exception.
|
||||||
"""
|
"""
|
||||||
logging.debug("{} items, idx {}, offset {}".format(len(self._items),
|
logging.debug("{} items, idx {}, offset {}".format(len(self._items),
|
||||||
self.idx, offset))
|
self.idx, offset))
|
||||||
@ -92,13 +110,13 @@ class NeighborList:
|
|||||||
else:
|
else:
|
||||||
raise IndexError
|
raise IndexError
|
||||||
except IndexError:
|
except IndexError:
|
||||||
if self._mode == self.BLOCK:
|
if self._mode == self.Modes.block:
|
||||||
new = self.curitem()
|
new = self.curitem()
|
||||||
elif self._mode == self.WRAP:
|
elif self._mode == self.Modes.wrap:
|
||||||
self.idx += offset
|
self.idx += offset
|
||||||
self.idx %= len(self.items)
|
self.idx %= len(self.items)
|
||||||
new = self.curitem()
|
new = self.curitem()
|
||||||
elif self._mode == self.RAISE:
|
elif self._mode == self.Modes.exception:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
self.idx += offset
|
self.idx += offset
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"""Utilities related to QWebElements.
|
"""Utilities related to QWebElements.
|
||||||
|
|
||||||
Module attributes:
|
Module attributes:
|
||||||
|
Group: Enum for different kinds of groups.
|
||||||
SELECTORS: CSS selectors for different groups of elements.
|
SELECTORS: CSS selectors for different groups of elements.
|
||||||
FILTERS: A dictionary of filter functions for the modes.
|
FILTERS: A dictionary of filter functions for the modes.
|
||||||
The filter for "links" filters javascript:-links and a-tags
|
The filter for "links" filters javascript:-links and a-tags
|
||||||
@ -25,26 +26,32 @@ Module attributes:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import qutebrowser.utils.url as urlutils
|
import qutebrowser.utils.url as urlutils
|
||||||
|
from qutebrowser.utils.usertypes import enum
|
||||||
|
|
||||||
|
|
||||||
|
Group = enum('all', 'links', 'images', 'editable', 'url', 'prevnext_rel',
|
||||||
|
'prevnext', 'editable_focused')
|
||||||
|
|
||||||
|
|
||||||
SELECTORS = {
|
SELECTORS = {
|
||||||
'all': ('a, textarea, select, input:not([type=hidden]), button, '
|
Group.all: ('a, textarea, select, input:not([type=hidden]), button, '
|
||||||
'frame, iframe, [onclick], [onmousedown], [role=link], '
|
'frame, iframe, [onclick], [onmousedown], [role=link], '
|
||||||
'[role=option], [role=button], img'),
|
'[role=option], [role=button], img'),
|
||||||
'links': 'a',
|
Group.links: 'a',
|
||||||
'images': 'img',
|
Group.images: 'img',
|
||||||
'editable': ('input[type=text], input[type=email], input[type=url], '
|
Group.editable: ('input[type=text], input[type=email], input[type=url], '
|
||||||
'input[type=tel], input[type=number], '
|
'input[type=tel], input[type=number], '
|
||||||
'input[type=password], input[type=search], textarea'),
|
'input[type=password], input[type=search], textarea'),
|
||||||
'url': '[src], [href]',
|
Group.url: '[src], [href]',
|
||||||
'prevnext_rel': 'link, [role=link]',
|
Group.prevnext_rel: 'link, [role=link]',
|
||||||
'prevnext': 'a, button, [role=button]',
|
Group.prevnext: 'a, button, [role=button]',
|
||||||
}
|
}
|
||||||
|
|
||||||
SELECTORS['editable_focused'] = ', '.join(
|
SELECTORS[Group.editable_focused] = ', '.join(
|
||||||
[sel.strip() + ':focus' for sel in SELECTORS['editable'].split(',')])
|
[sel.strip() + ':focus' for sel in SELECTORS[Group.editable].split(',')])
|
||||||
|
|
||||||
FILTERS = {
|
FILTERS = {
|
||||||
'links': (lambda e: e.hasAttribute('href') and
|
Group.links: (lambda e: e.hasAttribute('href') and
|
||||||
urlutils.qurl(e.attribute('href')).scheme() != 'javascript'),
|
urlutils.qurl(e.attribute('href')).scheme() != 'javascript'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,10 @@ import qutebrowser.utils.webelem as webelem
|
|||||||
from qutebrowser.browser.webpage import BrowserPage
|
from qutebrowser.browser.webpage import BrowserPage
|
||||||
from qutebrowser.browser.hints import HintManager
|
from qutebrowser.browser.hints import HintManager
|
||||||
from qutebrowser.utils.signals import SignalCache
|
from qutebrowser.utils.signals import SignalCache
|
||||||
from qutebrowser.utils.usertypes import NeighborList
|
from qutebrowser.utils.usertypes import NeighborList, enum
|
||||||
|
|
||||||
|
|
||||||
|
Target = enum('normal', 'tab', 'bgtab')
|
||||||
|
|
||||||
|
|
||||||
class WebView(QWebView):
|
class WebView(QWebView):
|
||||||
@ -72,7 +75,7 @@ class WebView(QWebView):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._scroll_pos = (-1, -1)
|
self._scroll_pos = (-1, -1)
|
||||||
self._shutdown_callback = None
|
self._shutdown_callback = None
|
||||||
self._open_target = 'normal'
|
self._open_target = Target.normal
|
||||||
self._force_open_target = None
|
self._force_open_target = None
|
||||||
self._destroyed = {}
|
self._destroyed = {}
|
||||||
self._zoom = None
|
self._zoom = None
|
||||||
@ -95,7 +98,7 @@ class WebView(QWebView):
|
|||||||
self._zoom = NeighborList(
|
self._zoom = NeighborList(
|
||||||
config.get('general', 'zoom-levels'),
|
config.get('general', 'zoom-levels'),
|
||||||
default=config.get('general', 'default-zoom'),
|
default=config.get('general', 'default-zoom'),
|
||||||
mode=NeighborList.BLOCK)
|
mode=NeighborList.Modes.block)
|
||||||
|
|
||||||
def _on_destroyed(self, sender):
|
def _on_destroyed(self, sender):
|
||||||
"""Called when a subsystem has been destroyed during shutdown.
|
"""Called when a subsystem has been destroyed during shutdown.
|
||||||
@ -226,9 +229,9 @@ class WebView(QWebView):
|
|||||||
Emit:
|
Emit:
|
||||||
open_tab: Emitted if window should be opened in a new tab.
|
open_tab: Emitted if window should be opened in a new tab.
|
||||||
"""
|
"""
|
||||||
if self._open_target == 'tab':
|
if self._open_target == Target.tab:
|
||||||
self.open_tab.emit(url, False)
|
self.open_tab.emit(url, False)
|
||||||
elif self._open_target == 'bgtab':
|
elif self._open_target == Target.bgtab:
|
||||||
self.open_tab.emit(url, True)
|
self.open_tab.emit(url, True)
|
||||||
else:
|
else:
|
||||||
self.openurl(url)
|
self.openurl(url)
|
||||||
@ -252,7 +255,7 @@ class WebView(QWebView):
|
|||||||
return
|
return
|
||||||
frame = self.page_.currentFrame()
|
frame = self.page_.currentFrame()
|
||||||
elem = frame.findFirstElement(
|
elem = frame.findFirstElement(
|
||||||
webelem.SELECTORS['editable_focused'])
|
webelem.SELECTORS[webelem.Group.editable_focused])
|
||||||
logging.debug("focus element: {}".format(not elem.isNull()))
|
logging.debug("focus element: {}".format(not elem.isNull()))
|
||||||
if elem.isNull():
|
if elem.isNull():
|
||||||
modeman.maybe_leave("insert")
|
modeman.maybe_leave("insert")
|
||||||
@ -266,7 +269,7 @@ class WebView(QWebView):
|
|||||||
Args:
|
Args:
|
||||||
target: A string to set self._force_open_target to.
|
target: A string to set self._force_open_target to.
|
||||||
"""
|
"""
|
||||||
self._force_open_target = target
|
self._force_open_target = getattr(Target, target)
|
||||||
|
|
||||||
def paintEvent(self, e):
|
def paintEvent(self, e):
|
||||||
"""Extend paintEvent to emit a signal if the scroll position changed.
|
"""Extend paintEvent to emit a signal if the scroll position changed.
|
||||||
@ -339,10 +342,10 @@ class WebView(QWebView):
|
|||||||
elif (e.button() == Qt.MidButton or
|
elif (e.button() == Qt.MidButton or
|
||||||
e.modifiers() & Qt.ControlModifier):
|
e.modifiers() & Qt.ControlModifier):
|
||||||
if config.get('general', 'background-tabs'):
|
if config.get('general', 'background-tabs'):
|
||||||
self._open_target = "bgtab"
|
self._open_target = Target.bgtab
|
||||||
else:
|
else:
|
||||||
self._open_target = "tab"
|
self._open_target = Target.tab
|
||||||
logging.debug("Setting target: {}".format(self._open_target))
|
logging.debug("Setting target: {}".format(self._open_target))
|
||||||
else:
|
else:
|
||||||
self._open_target = "normal"
|
self._open_target = Target.normal
|
||||||
return super().mousePressEvent(e)
|
return super().mousePressEvent(e)
|
||||||
|
Loading…
Reference in New Issue
Block a user