diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 59aff9476..bdffc2921 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -274,7 +274,7 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None): if via_ipc and target_arg and target_arg != 'auto': open_target = target_arg else: - open_target = config.get('general', 'new-instance-open-target') + open_target = config.val.new_instance_open_target win_id = mainwindow.get_window(via_ipc, force_target=open_target) tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) @@ -310,7 +310,7 @@ def _open_startpage(win_id=None): window=cur_win_id) if tabbed_browser.count() == 0: log.init.debug("Opening startpage") - for urlstr in config.get('general', 'startpage'): + for urlstr in config.val.startpage: try: url = urlutils.fuzzy_url(urlstr, do_search=False) except urlutils.InvalidUrlError as e: @@ -464,7 +464,7 @@ def _init_modules(args, crash_handler): completionmodels.init() log.init.debug("Misc initialization...") - if config.get('ui', 'hide-wayland-decoration'): + if config.val.ui.hide_wayland_decoration: os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1' else: os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None) @@ -674,7 +674,7 @@ class Quitter: if session is not None: session_manager.save(session, last_window=last_window, load_next_time=True) - elif config.get('general', 'save-session'): + elif config.val.save_session: session_manager.save(sessions.default, last_window=last_window, load_next_time=True) diff --git a/qutebrowser/browser/adblock.py b/qutebrowser/browser/adblock.py index 276dec08b..b27a54424 100644 --- a/qutebrowser/browser/adblock.py +++ b/qutebrowser/browser/adblock.py @@ -67,7 +67,7 @@ def is_whitelisted_host(host): Args: host: The host of the request as string. """ - whitelist = config.get('content', 'host-blocking-whitelist') + whitelist = config.val.content.host_blocking_whitelist if whitelist is None: return False @@ -123,7 +123,7 @@ class HostBlocker: def is_blocked(self, url): """Check if the given URL (as QUrl) is blocked.""" - if not config.get('content', 'host-blocking-enabled'): + if not config.val.content.host_blocking_enabled: return False host = url.host() return ((host in self._blocked_hosts or @@ -164,9 +164,9 @@ class HostBlocker: if not found: args = objreg.get('args') - if (config.get('content', 'host-block-lists') is not None and + if (config.val.content.host_block_lists is not None and args.basedir is None and - config.get('content', 'host-blocking-enabled')): + config.val.content.host_blocking_enabled): message.info("Run :adblock-update to get adblock lists.") @cmdutils.register(instance='host-blocker') @@ -180,7 +180,7 @@ class HostBlocker: self._config_blocked_hosts) self._blocked_hosts = set() self._done_count = 0 - urls = config.get('content', 'host-block-lists') + urls = config.val.content.host_block_lists download_manager = objreg.get('qtnetwork-download-manager', scope='window', window='last-focused') if urls is None: @@ -295,7 +295,7 @@ class HostBlocker: @config.change_filter('content', 'host-block-lists') def on_config_changed(self): """Update files when the config changed.""" - urls = config.get('content', 'host-block-lists') + urls = config.val.content.host_block_lists if urls is None: try: os.remove(self._local_hosts_file) diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index b36b5d1c3..7adb9608e 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -249,17 +249,17 @@ class AbstractZoom(QObject): def _on_config_changed(self, section, option): if section == 'ui' and option in ['zoom-levels', 'default-zoom']: if not self._default_zoom_changed: - factor = float(config.get('ui', 'default-zoom')) / 100 + factor = float(config.val.ui.default_zoom) / 100 self._set_factor_internal(factor) self._default_zoom_changed = False self._init_neighborlist() def _init_neighborlist(self): """Initialize self._neighborlist.""" - levels = config.get('ui', 'zoom-levels') + levels = config.val.ui.zoom_levels self._neighborlist = usertypes.NeighborList( levels, mode=usertypes.NeighborList.Modes.edge) - self._neighborlist.fuzzyval = config.get('ui', 'default-zoom') + self._neighborlist.fuzzyval = config.val.ui.default_zoom def offset(self, offset): """Increase/Decrease the zoom level by the given offset. @@ -295,7 +295,7 @@ class AbstractZoom(QObject): raise NotImplementedError def set_default(self): - default_zoom = config.get('ui', 'default-zoom') + default_zoom = config.val.ui.default_zoom self._set_factor_internal(float(default_zoom) / 100) @@ -690,7 +690,7 @@ class AbstractTab(QWidget): def _handle_auto_insert_mode(self, ok): """Handle auto-insert-mode after loading finished.""" - if not config.get('input', 'auto-insert-mode') or not ok: + if not config.val.input.auto_insert_mode or not ok: return cur_mode = self._mode_manager.mode diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 3d8516fe2..c375188f4 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -190,7 +190,7 @@ class CommandDispatcher: elif next_: return QTabBar.SelectRightTab elif opposite: - conf_selection = config.get('tabs', 'select-on-remove') + conf_selection = config.val.tabs.select_on_remove if conf_selection == QTabBar.SelectLeftTab: return QTabBar.SelectRightTab elif conf_selection == QTabBar.SelectRightTab: @@ -307,7 +307,7 @@ class CommandDispatcher: private: Open a new window in private browsing mode. """ if url is None: - urls = [config.get('general', 'default-page')] + urls = [config.val.default_page] else: urls = self._parse_url_input(url) @@ -507,9 +507,9 @@ class CommandDispatcher: idx = new_tabbed_browser.indexOf(newtab) new_tabbed_browser.set_page_title(idx, cur_title) - if config.get('tabs', 'show-favicons'): + if config.val.tabs.show_favicons: new_tabbed_browser.setTabIcon(idx, curtab.icon()) - if config.get('tabs', 'tabs-are-windows'): + if config.val.tabs.tabs_are_windows: new_tabbed_browser.window().setWindowIcon(curtab.icon()) newtab.data.keep_icon = True @@ -778,7 +778,7 @@ class CommandDispatcher: url_query.setQueryDelimiters('=', ';') url_query.setQuery(url_query_str) for key in dict(url_query.queryItems()): - if key in config.get('general', 'yank-ignored-url-parameters'): + if key in config.val.yank_ignored_url_parameters: url_query.removeQueryItem(key) url.setQuery(url_query) return url.toString(flags) @@ -888,7 +888,7 @@ class CommandDispatcher: level = count if count is not None else zoom if level is None: - level = config.get('ui', 'default-zoom') + level = config.val.ui.default_zoom tab = self._current_widget() try: @@ -953,7 +953,7 @@ class CommandDispatcher: newidx = self._current_index() - count if newidx >= 0: self._set_current_index(newidx) - elif config.get('tabs', 'wrap'): + elif config.val.tabs.wrap: self._set_current_index(newidx % self._count()) else: raise cmdexc.CommandError("First tab") @@ -973,7 +973,7 @@ class CommandDispatcher: newidx = self._current_index() + count if newidx < self._count(): self._set_current_index(newidx) - elif config.get('tabs', 'wrap'): + elif config.val.tabs.wrap: self._set_current_index(newidx % self._count()) else: raise cmdexc.CommandError("Last tab") @@ -1131,7 +1131,7 @@ class CommandDispatcher: elif index == '+': # pragma: no branch new_idx += delta - if config.get('tabs', 'wrap'): + if config.val.tabs.wrap: new_idx %= self._count() else: # absolute moving @@ -1192,7 +1192,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') def home(self): """Open main startpage in current tab.""" - self.openurl(config.get('general', 'startpage')[0]) + self.openurl(config.val.startpage[0]) def _run_userscript(self, cmd, *args, verbose=False): """Run a userscript given as argument. @@ -1746,7 +1746,7 @@ class CommandDispatcher: return options = { - 'ignore_case': config.get('general', 'ignore-case'), + 'ignore_case': config.val.ignore_case, 'reverse': reverse, } diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index c7cb5ad8e..b70d5ca45 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -69,8 +69,8 @@ class UnsupportedOperationError(Exception): def download_dir(): """Get the download directory to use.""" - directory = config.get('storage', 'download-directory') - remember_dir = config.get('storage', 'remember-download-directory') + directory = config.val.storage.download_directory + remember_dir = config.val.storage.remember_download_directory if remember_dir and last_used_directory is not None: return last_used_directory @@ -104,7 +104,7 @@ def _path_suggestion(filename): Args: filename: The filename to use if included in the suggestion. """ - suggestion = config.get('completion', 'download-path-suggestion') + suggestion = config.val.completion.download_path_suggestion if suggestion == 'path': # add trailing '/' if not present return os.path.join(download_dir(), '') @@ -735,7 +735,7 @@ class AbstractDownloadManager(QObject): download.remove_requested.connect(functools.partial( self._remove_item, download)) - delay = config.get('ui', 'remove-finished-downloads') + delay = config.val.ui.remove_finished_downloads if delay > -1: download.finished.connect( lambda: QTimer.singleShot(delay, download.remove)) diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 3cc70f434..aed554d9f 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -68,7 +68,7 @@ class HintLabel(QLabel): background-color: {{ color['hints.bg'] }}; color: {{ color['hints.fg'] }}; font: {{ font['hints'] }}; - border: {{ config.get('hints', 'border') }}; + border: {{ config.val.hints.border }}; padding-left: -3px; padding-right: -3px; } @@ -100,7 +100,7 @@ class HintLabel(QLabel): matched: The part of the text which was typed. unmatched: The part of the text which was not typed yet. """ - if (config.get('hints', 'uppercase') and + if (config.val.hints.uppercase and self._context.hint_mode in ['letter', 'word']): matched = html.escape(matched.upper()) unmatched = html.escape(unmatched.upper()) @@ -108,7 +108,7 @@ class HintLabel(QLabel): matched = html.escape(matched) unmatched = html.escape(unmatched) - match_color = html.escape(config.get('colors', 'hints.fg.match')) + match_color = html.escape(config.val.colors.hints.fg.match) self.setText('{}{}'.format( match_color, matched, unmatched)) self.adjustSize() @@ -121,7 +121,7 @@ class HintLabel(QLabel): log.hints.debug("Frame for {!r} vanished!".format(self)) self.hide() return - no_js = config.get('hints', 'find-implementation') != 'javascript' + no_js = config.val.hints.find_implementation != 'javascript' rect = self.elem.rect_on_view(no_js=no_js) self.move(rect.x(), rect.y()) @@ -203,7 +203,7 @@ class HintActions: Target.window: usertypes.ClickTarget.window, Target.hover: usertypes.ClickTarget.normal, } - if config.get('tabs', 'background-tabs'): + if config.val.tabs.background_tabs: target_mapping[Target.tab] = usertypes.ClickTarget.tab_bg else: target_mapping[Target.tab] = usertypes.ClickTarget.tab @@ -421,9 +421,9 @@ class HintManager(QObject): if hint_mode == 'number': chars = '0123456789' else: - chars = config.get('hints', 'chars') - min_chars = config.get('hints', 'min-chars') - if config.get('hints', 'scatter') and hint_mode != 'number': + chars = config.val.hints.chars + min_chars = config.val.hints.min_chars + if config.val.hints.scatter and hint_mode != 'number': return self._hint_scattered(min_chars, chars, elems) else: return self._hint_linear(min_chars, chars, elems) @@ -685,7 +685,7 @@ class HintManager(QObject): Target.download, Target.normal, Target.current]: pass elif (target == Target.tab and - config.get('tabs', 'background-tabs')): + config.val.tabs.background_tabs): pass else: name = target.name.replace('_', '-') @@ -693,7 +693,7 @@ class HintManager(QObject): "target {}!".format(name)) if mode is None: - mode = config.get('hints', 'mode') + mode = config.val.hints.mode self._check_args(target, *args) self._context = HintContext() @@ -729,7 +729,7 @@ class HintManager(QObject): if len(visible) != 1: return - auto_follow = config.get('hints', 'auto-follow') + auto_follow = config.val.hints.auto_follow if auto_follow == "always": follow = True @@ -747,7 +747,7 @@ class HintManager(QObject): if follow: # apply auto-follow-timeout - timeout = config.get('hints', 'auto-follow-timeout') + timeout = config.val.hints.auto_follow_timeout keyparsers = objreg.get('keyparsers', scope='window', window=self._win_id) normal_parser = keyparsers[usertypes.KeyMode.normal] @@ -773,7 +773,7 @@ class HintManager(QObject): # element doesn't match anymore -> hide it, unless in rapid # mode and hide-unmatched-rapid-hints is false (see #1799) if (not self._context.rapid or - config.get('hints', 'hide-unmatched-rapid-hints')): + config.val.hints.hide_unmatched_rapid_hints): label.hide() except webelem.Error: pass diff --git a/qutebrowser/browser/mouse.py b/qutebrowser/browser/mouse.py index d1cd889d3..18069a003 100644 --- a/qutebrowser/browser/mouse.py +++ b/qutebrowser/browser/mouse.py @@ -85,7 +85,7 @@ class MouseEventFilter(QObject): def _handle_mouse_press(self, e): """Handle pressing of a mouse button.""" - is_rocker_gesture = (config.get('input', 'rocker-gestures') and + is_rocker_gesture = (config.val.input.rocker_gestures and e.buttons() == Qt.LeftButton | Qt.RightButton) if e.button() in [Qt.XButton1, Qt.XButton2] or is_rocker_gesture: @@ -119,7 +119,7 @@ class MouseEventFilter(QObject): return True if e.modifiers() & Qt.ControlModifier: - divider = config.get('input', 'mouse-zoom-divider') + divider = config.val.input.mouse_zoom_divider if divider == 0: return False factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider) @@ -139,7 +139,7 @@ class MouseEventFilter(QObject): def _handle_context_menu(self, _e): """Suppress context menus if rocker gestures are turned on.""" - return config.get('input', 'rocker-gestures') + return config.val.input.rocker_gestures def _mousepress_insertmode_cb(self, elem): """Check if the clicked element is editable.""" @@ -157,7 +157,7 @@ class MouseEventFilter(QObject): 'click', only_if_normal=True) else: log.mouse.debug("Clicked non-editable element!") - if config.get('input', 'auto-leave-insert-mode'): + if config.val.input.auto_leave_insert_mode: modeman.leave(self._tab.win_id, usertypes.KeyMode.insert, 'click', maybe=True) @@ -179,7 +179,7 @@ class MouseEventFilter(QObject): 'click-delayed', only_if_normal=True) else: log.mouse.debug("Clicked non-editable element (delayed)!") - if config.get('input', 'auto-leave-insert-mode'): + if config.val.input.auto_leave_insert_mode: modeman.leave(self._tab.win_id, usertypes.KeyMode.insert, 'click-delayed', maybe=True) diff --git a/qutebrowser/browser/navigate.py b/qutebrowser/browser/navigate.py index 4443c6a47..92126c6ad 100644 --- a/qutebrowser/browser/navigate.py +++ b/qutebrowser/browser/navigate.py @@ -42,7 +42,7 @@ def incdec(url, count, inc_or_dec): background: Open the link in a new background tab. window: Open the link in a new window. """ - segments = set(config.get('general', 'url-incdec-segments')) + segments = set(config.val.url_incdec_segments) try: new_url = urlutils.incdec_number(url, inc_or_dec, count, segments=segments) diff --git a/qutebrowser/browser/network/proxy.py b/qutebrowser/browser/network/proxy.py index 1bdbc7b0b..037c9c712 100644 --- a/qutebrowser/browser/network/proxy.py +++ b/qutebrowser/browser/network/proxy.py @@ -44,7 +44,7 @@ class ProxyFactory(QNetworkProxyFactory): Return: None if proxy is correct, otherwise an error message. """ - proxy = config.get('network', 'proxy') + proxy = config.val.network.proxy if isinstance(proxy, pac.PACFetcher): return proxy.fetch_error() else: @@ -59,7 +59,7 @@ class ProxyFactory(QNetworkProxyFactory): Return: A list of QNetworkProxy objects in order of preference. """ - proxy = config.get('network', 'proxy') + proxy = config.val.network.proxy if proxy is configtypes.SYSTEM_PROXY: proxies = QNetworkProxyFactory.systemProxyForQuery(query) elif isinstance(proxy, pac.PACFetcher): @@ -69,7 +69,7 @@ class ProxyFactory(QNetworkProxyFactory): for p in proxies: if p.type() != QNetworkProxy.NoProxy: capabilities = p.capabilities() - if config.get('network', 'proxy-dns-requests'): + if config.val.network.proxy_dns_requests: capabilities |= QNetworkProxy.HostNameLookupCapability else: capabilities &= ~QNetworkProxy.HostNameLookupCapability diff --git a/qutebrowser/browser/qtnetworkdownloads.py b/qutebrowser/browser/qtnetworkdownloads.py index 71039dc2d..9aba6d335 100644 --- a/qutebrowser/browser/qtnetworkdownloads.py +++ b/qutebrowser/browser/qtnetworkdownloads.py @@ -368,7 +368,7 @@ class DownloadManager(downloads.AbstractDownloadManager): super().__init__(parent) self._networkmanager = networkmanager.NetworkManager( win_id=win_id, tab_id=None, - private=config.get('general', 'private-browsing'), parent=self) + private=config.val.private_browsing, parent=self) @pyqtSlot('QUrl') def get(self, url, *, user_agent=None, **kwargs): diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index 652c58726..552ced168 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -278,14 +278,14 @@ def qute_history(url): return 'text/html', json.dumps(history_data(start_time)) else: if ( - config.get('content', 'allow-javascript') and + config.val.content.allow_javascript and (objects.backend == usertypes.Backend.QtWebEngine or qtutils.is_qtwebkit_ng()) ): return 'text/html', jinja.render( 'history.html', title='History', - session_interval=config.get('ui', 'history-session-interval') + session_interval=config.val.ui.history_session_interval ) else: # Get current date from query parameter, if not given choose today. diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index d400387a9..5d3ddc506 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -35,16 +35,16 @@ class CallSuper(Exception): def custom_headers(): """Get the combined custom headers.""" headers = {} - dnt = b'1' if config.get('network', 'do-not-track') else b'0' + dnt = b'1' if config.val.network.do_not_track else b'0' headers[b'DNT'] = dnt headers[b'X-Do-Not-Track'] = dnt - config_headers = config.get('network', 'custom-headers') + config_headers = config.val.network.custom_headers if config_headers is not None: for header, value in config_headers.items(): headers[header.encode('ascii')] = value.encode('ascii') - accept_language = config.get('network', 'accept-language') + accept_language = config.val.network.accept_language if accept_language is not None: headers[b'Accept-Language'] = accept_language.encode('ascii') @@ -72,7 +72,7 @@ def authentication_required(url, authenticator, abort_on): def javascript_confirm(url, js_msg, abort_on): """Display a javascript confirm prompt.""" log.js.debug("confirm: {}".format(js_msg)) - if config.get('ui', 'modal-js-dialog'): + if config.val.ui.modal_js_dialog: raise CallSuper msg = 'From {}:
{}'.format(html.escape(url.toDisplayString()), @@ -86,9 +86,9 @@ def javascript_confirm(url, js_msg, abort_on): def javascript_prompt(url, js_msg, default, abort_on): """Display a javascript prompt.""" log.js.debug("prompt: {}".format(js_msg)) - if config.get('ui', 'modal-js-dialog'): + if config.val.ui.modal_js_dialog: raise CallSuper - if config.get('content', 'ignore-javascript-prompt'): + if config.val.content.ignore_javascript_prompt: return (False, "") msg = '{} asks:
{}'.format(html.escape(url.toDisplayString()), @@ -107,10 +107,10 @@ def javascript_prompt(url, js_msg, default, abort_on): def javascript_alert(url, js_msg, abort_on): """Display a javascript alert.""" log.js.debug("alert: {}".format(js_msg)) - if config.get('ui', 'modal-js-dialog'): + if config.val.ui.modal_js_dialog: raise CallSuper - if config.get('content', 'ignore-javascript-alert'): + if config.val.content.ignore_javascript_alert: return msg = 'From {}:
{}'.format(html.escape(url.toDisplayString()), @@ -129,7 +129,7 @@ def ignore_certificate_errors(url, errors, abort_on): Return: True if the error should be ignored, False otherwise. """ - ssl_strict = config.get('network', 'ssl-strict') + ssl_strict = config.val.network.ssl_strict log.webview.debug("Certificate errors {!r}, strict {}".format( errors, ssl_strict)) @@ -233,7 +233,7 @@ def get_tab(win_id, target): def get_user_stylesheet(): """Get the combined user-stylesheet.""" - filename = config.get('ui', 'user-stylesheet') + filename = config.val.ui.user_stylesheet if filename is None: css = '' @@ -241,7 +241,7 @@ def get_user_stylesheet(): with open(filename, 'r', encoding='utf-8') as f: css = f.read() - if config.get('ui', 'hide-scrollbar'): + if config.val.ui.hide_scrollbar: css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }' return css diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index 149300111..401a3bb93 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -182,7 +182,7 @@ class AbstractWebElement(collections.abc.MutableMapping): # at least a classid attribute. Oh, and let's hope images/... # DON'T have a classid attribute. HTML sucks. log.webelem.debug(" clicked.".format(objtype)) - return config.get('input', 'insert-mode-on-plugins') + return config.val.input.insert_mode_on_plugins else: # Image/Audio/... return False @@ -247,7 +247,7 @@ class AbstractWebElement(collections.abc.MutableMapping): return self.is_writable() elif tag in ['embed', 'applet']: # Flash/Java/... - return config.get('input', 'insert-mode-on-plugins') and not strict + return config.val.input.insert_mode_on_plugins and not strict elif tag == 'object': return self._is_editable_object() and not strict elif tag in ['div', 'pre']: @@ -329,7 +329,7 @@ class AbstractWebElement(collections.abc.MutableMapping): usertypes.ClickTarget.tab: Qt.ControlModifier, usertypes.ClickTarget.tab_bg: Qt.ControlModifier, } - if config.get('tabs', 'background-tabs'): + if config.val.tabs.background_tabs: modifiers[usertypes.ClickTarget.tab] |= Qt.ShiftModifier else: modifiers[usertypes.ClickTarget.tab_bg] |= Qt.ShiftModifier diff --git a/qutebrowser/browser/webengine/interceptor.py b/qutebrowser/browser/webengine/interceptor.py index 0cb2d446e..5d9dc8a70 100644 --- a/qutebrowser/browser/webengine/interceptor.py +++ b/qutebrowser/browser/webengine/interceptor.py @@ -63,6 +63,6 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor): for header, value in shared.custom_headers(): info.setHttpHeader(header, value) - user_agent = config.get('network', 'user-agent') + user_agent = config.val.network.user_agent if user_agent is not None: info.setHttpHeader(b'User-Agent', user_agent.encode('ascii')) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 493a2a687..00f4ec423 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -163,7 +163,7 @@ def _set_user_agent(profile): per-domain user agents), but this one still gets used for things like window.navigator.userAgent in JS. """ - user_agent = config.get('network', 'user-agent') + user_agent = config.val.network.user_agent profile.setHttpUserAgent(user_agent) @@ -212,7 +212,7 @@ def init(args): # We need to do this here as a WORKAROUND for # https://bugreports.qt.io/browse/QTBUG-58650 if not qtutils.version_check('5.9'): - PersistentCookiePolicy().set(config.get('content', 'cookies-store')) + PersistentCookiePolicy().set(config.val.content.cookies_store) Attribute(QWebEngineSettings.FullScreenSupportEnabled).set(True) websettings.init_mappings(MAPPINGS) diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index fd6fc99cb..b650df5a7 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -80,7 +80,7 @@ class WebEngineView(QWebEngineView): The new QWebEngineView object. """ debug_type = debug.qenum_key(QWebEnginePage, wintype) - background_tabs = config.get('tabs', 'background-tabs') + background_tabs = config.val.tabs.background_tabs log.webview.debug("createWindow with type {}, background_tabs " "{}".format(debug_type, background_tabs)) @@ -139,7 +139,7 @@ class WebEnginePage(QWebEnginePage): @config.change_filter('colors', 'webpage.bg') def _set_bg_color(self): - col = config.get('colors', 'webpage.bg') + col = config.val.colors.webpage.bg if col is None: col = self._theme_color self.setBackgroundColor(col) @@ -277,7 +277,7 @@ class WebEnginePage(QWebEnginePage): def javaScriptConsoleMessage(self, level, msg, line, source): """Log javascript messages to qutebrowser's log.""" # FIXME:qtwebengine maybe unify this in the tab api somehow? - setting = config.get('general', 'log-javascript-console') + setting = config.val.log_javascript_console if setting == 'none': return diff --git a/qutebrowser/browser/webkit/cache.py b/qutebrowser/browser/webkit/cache.py index ae717c956..6f2478c37 100644 --- a/qutebrowser/browser/webkit/cache.py +++ b/qutebrowser/browser/webkit/cache.py @@ -45,7 +45,7 @@ class DiskCache(QNetworkDiskCache): @config.change_filter('storage', 'cache-size') def _set_cache_size(self): """Set the cache size based on the config.""" - size = config.get('storage', 'cache-size') + size = config.val.storage.cache_size if size is None: size = 1024 * 1024 * 50 # default from QNetworkDiskCachePrivate # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-59909 diff --git a/qutebrowser/browser/webkit/cookies.py b/qutebrowser/browser/webkit/cookies.py index 79f7a67fa..2c9072f7d 100644 --- a/qutebrowser/browser/webkit/cookies.py +++ b/qutebrowser/browser/webkit/cookies.py @@ -50,7 +50,7 @@ class RAMCookieJar(QNetworkCookieJar): Return: True if one or more cookies are set for 'url', otherwise False. """ - if config.get('content', 'cookies-accept') == 'never': + if config.val.content.cookies_accept == 'never': return False else: self.changed.emit() @@ -77,7 +77,7 @@ class CookieJar(RAMCookieJar): objreg.get('config').changed.connect(self.cookies_store_changed) objreg.get('save-manager').add_saveable( 'cookies', self.save, self.changed, - config_opt=('content', 'cookies-store')) + config_opt='content.cookies_store') def parse_cookies(self): """Parse cookies from lineparser and store them.""" @@ -108,7 +108,7 @@ class CookieJar(RAMCookieJar): @config.change_filter('content', 'cookies-store') def cookies_store_changed(self): """Delete stored cookies if cookies-store changed.""" - if not config.get('content', 'cookies-store'): + if not config.val.content.cookies_store: self._lineparser.data = [] self._lineparser.save() self.changed.emit() diff --git a/qutebrowser/browser/webkit/network/networkmanager.py b/qutebrowser/browser/webkit/network/networkmanager.py index 9d4c1b317..c2ad03a6b 100644 --- a/qutebrowser/browser/webkit/network/networkmanager.py +++ b/qutebrowser/browser/webkit/network/networkmanager.py @@ -274,7 +274,7 @@ class NetworkManager(QNetworkAccessManager): # altogether. reply.netrc_used = True try: - net = netrc.netrc(config.get('network', 'netrc-file')) + net = netrc.netrc(config.val.network.netrc_file) authenticators = net.authenticators(reply.url().host()) if authenticators is not None: (user, _account, password) = authenticators @@ -338,7 +338,7 @@ class NetworkManager(QNetworkAccessManager): def set_referer(self, req, current_url): """Set the referer header.""" - referer_header_conf = config.get('network', 'referer-header') + referer_header_conf = config.val.network.referer_header try: if referer_header_conf == 'never': diff --git a/qutebrowser/browser/webkit/webkitelem.py b/qutebrowser/browser/webkit/webkitelem.py index b184f9905..522847511 100644 --- a/qutebrowser/browser/webkit/webkitelem.py +++ b/qutebrowser/browser/webkit/webkitelem.py @@ -168,7 +168,7 @@ class WebKitElement(webelem.AbstractWebElement): if width > 1 and height > 1: # fix coordinates according to zoom level zoom = self._elem.webFrame().zoomFactor() - if not config.get('ui', 'zoom-text-only'): + if not config.val.ui.zoom_text_only: rect["left"] *= zoom rect["top"] *= zoom width *= zoom diff --git a/qutebrowser/browser/webkit/webkitinspector.py b/qutebrowser/browser/webkit/webkitinspector.py index 9a056a896..2be95cb3d 100644 --- a/qutebrowser/browser/webkit/webkitinspector.py +++ b/qutebrowser/browser/webkit/webkitinspector.py @@ -36,7 +36,7 @@ class WebKitInspector(inspector.AbstractWebInspector): self._set_widget(qwebinspector) def inspect(self, page): - if not config.get('general', 'developer-extras'): + if not config.val.developer_extras: raise inspector.WebInspectorError( "Please enable developer-extras before using the " "webinspector!") diff --git a/qutebrowser/browser/webkit/webkitsettings.py b/qutebrowser/browser/webkit/webkitsettings.py index dd251949f..9da142932 100644 --- a/qutebrowser/browser/webkit/webkitsettings.py +++ b/qutebrowser/browser/webkit/webkitsettings.py @@ -132,7 +132,7 @@ def init(_args): QWebSettings.setOfflineStoragePath( os.path.join(data_path, 'offline-storage')) - if (config.get('general', 'private-browsing') and + if (config.val.private_browsing and not qtutils.version_check('5.4.2')): # WORKAROUND for https://codereview.qt-project.org/#/c/108936/ # Won't work when private browsing is not enabled globally, but that's diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py index acebf5cd3..beb47ea09 100644 --- a/qutebrowser/browser/webkit/webpage.py +++ b/qutebrowser/browser/webkit/webpage.py @@ -277,7 +277,7 @@ class BrowserPage(QWebPage): reply.finished.connect(functools.partial( self.display_content, reply, 'image/jpeg')) elif (mimetype in ['application/pdf', 'application/x-pdf'] and - config.get('content', 'enable-pdfjs')): + config.val.content.enable_pdfjs): # Use pdf.js to display the page self._show_pdfjs(reply) else: @@ -384,7 +384,7 @@ class BrowserPage(QWebPage): def userAgentForUrl(self, url): """Override QWebPage::userAgentForUrl to customize the user agent.""" - ua = config.get('network', 'user-agent') + ua = config.val.network.user_agent if ua is None: return super().userAgentForUrl(url) else: diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py index 99980b4b1..3daafd8ec 100644 --- a/qutebrowser/browser/webkit/webview.py +++ b/qutebrowser/browser/webkit/webview.py @@ -110,7 +110,7 @@ class WebView(QWebView): @config.change_filter('colors', 'webpage.bg') def _set_bg_color(self): """Set the webpage background color as configured.""" - col = config.get('colors', 'webpage.bg') + col = config.val.colors.webpage.bg palette = self.palette() if col is None: col = self.style().standardPalette().color(QPalette.Base) @@ -285,7 +285,7 @@ class WebView(QWebView): This is implemented here as we don't need it for QtWebEngine. """ if e.button() == Qt.MidButton or e.modifiers() & Qt.ControlModifier: - background_tabs = config.get('tabs', 'background-tabs') + background_tabs = config.val.tabs.background_tabs if e.modifiers() & Qt.ShiftModifier: background_tabs = not background_tabs if background_tabs: diff --git a/qutebrowser/commands/userscripts.py b/qutebrowser/commands/userscripts.py index 69a36f400..03d6bbffc 100644 --- a/qutebrowser/commands/userscripts.py +++ b/qutebrowser/commands/userscripts.py @@ -417,7 +417,7 @@ def run_async(tab, cmd, *args, win_id, env, verbose=False): lambda cmd: log.commands.debug("Got userscript command: {}".format(cmd))) runner.got_cmd.connect(commandrunner.run_safely) - user_agent = config.get('network', 'user-agent') + user_agent = config.val.network.user_agent if user_agent is not None: env['QUTE_USER_AGENT'] = user_agent diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py index 96d937829..38302fa5e 100644 --- a/qutebrowser/completion/completer.py +++ b/qutebrowser/completion/completer.py @@ -194,7 +194,7 @@ class Completer(QObject): if maxsplit is None: text = self._quote(text) model = self._model() - if model.count() == 1 and config.get('completion', 'quick-complete'): + if model.count() == 1 and config.val.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(text, before, after, immediate=True) diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py index 1d5dfadf0..f17a77cbf 100644 --- a/qutebrowser/completion/completiondelegate.py +++ b/qutebrowser/completion/completiondelegate.py @@ -156,7 +156,7 @@ class CompletionItemDelegate(QStyledItemDelegate): try: self._painter.setPen(config.get('colors', option)) except configexc.NoOptionError: - self._painter.setPen(config.get('colors', 'completion.fg')) + self._painter.setPen(config.val.colors.completion.fg) ctx = QAbstractTextDocumentLayout.PaintContext() ctx.palette.setColor(QPalette.Text, self._painter.pen().color()) if clip.isValid(): @@ -208,7 +208,7 @@ class CompletionItemDelegate(QStyledItemDelegate): else: self._doc.setHtml( '{}'.format( - html.escape(config.get('fonts', 'completion.category')), + html.escape(config.val.fonts.completion.category), html.escape(self._opt.text))) def _draw_focus_rect(self): diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py index 490fcd6c0..7fc5f36c9 100644 --- a/qutebrowser/completion/completionwidget.py +++ b/qutebrowser/completion/completionwidget.py @@ -85,13 +85,13 @@ class CompletionView(QTreeView): } QTreeView QScrollBar { - width: {{ config.get('completion', 'scrollbar-width') }}px; + width: {{ config.val.completion.scrollbar_width }}px; background: {{ color['completion.scrollbar.bg'] }}; } QTreeView QScrollBar::handle { background: {{ color['completion.scrollbar.fg'] }}; - border: {{ config.get('completion', 'scrollbar-padding') }}px solid + border: {{ config.val.completion.scrollbar_padding }}px solid {{ color['completion.scrollbar.bg'] }}; min-height: 10px; } @@ -257,9 +257,9 @@ class CompletionView(QTreeView): count = self.model().count() if count == 0: self.hide() - elif count == 1 and config.get('completion', 'quick-complete'): + elif count == 1 and config.val.completion.quick_complete: self.hide() - elif config.get('completion', 'show') == 'auto': + elif config.val.completion.show == 'auto': self.show() def set_model(self, model, pattern=None): @@ -288,7 +288,7 @@ class CompletionView(QTreeView): if old_model is not None: old_model.deleteLater() - if (config.get('completion', 'show') == 'always' and + if (config.val.completion.show == 'always' and model.count() > 0): self.show() else: @@ -306,7 +306,7 @@ class CompletionView(QTreeView): def _maybe_update_geometry(self): """Emit the update_geometry signal if the config says so.""" - if config.get('completion', 'shrink'): + if config.val.completion.shrink: self.update_geometry.emit() @pyqtSlot() @@ -321,14 +321,14 @@ class CompletionView(QTreeView): def sizeHint(self): """Get the completion size according to the config.""" # Get the configured height/percentage. - confheight = str(config.get('completion', 'height')) + confheight = str(config.val.completion.height) if confheight.endswith('%'): perc = int(confheight.rstrip('%')) height = self.window().height() * perc / 100 else: height = int(confheight) # Shrink to content size if needed and shrinking is enabled - if config.get('completion', 'shrink'): + if config.val.completion.shrink: contents_height = ( self.viewportSizeHint().height() + self.horizontalScrollBar().sizeHint().height()) diff --git a/qutebrowser/completion/models/urlmodel.py b/qutebrowser/completion/models/urlmodel.py index 98f68c08c..b52b50ff1 100644 --- a/qutebrowser/completion/models/urlmodel.py +++ b/qutebrowser/completion/models/urlmodel.py @@ -68,7 +68,7 @@ class UrlCompletionModel(base.BaseCompletionModel): bookmark_manager.removed.connect(self.on_bookmark_removed) self._history = objreg.get('web-history') - self._max_history = config.get('completion', 'web-history-max-items') + self._max_history = config.val.completion.web_history_max_items history = utils.newest_slice(self._history, self._max_history) for entry in history: if not entry.redirect: @@ -80,7 +80,7 @@ class UrlCompletionModel(base.BaseCompletionModel): def _fmt_atime(self, atime): """Format an atime to a human-readable string.""" - fmt = config.get('completion', 'timestamp-format') + fmt = config.val.completion.timestamp_format if fmt is None: return '' try: diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index a723d2f10..f52578040 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -50,6 +50,10 @@ from qutebrowser.utils.usertypes import Completion UNSET = object() +# FIXME:conf for new config +val = None + + class change_filter: # pylint: disable=invalid-name """Decorator to filter calls based on a config section/option matching. @@ -167,7 +171,7 @@ def _init_main_config(parent=None): save_manager = objreg.get('save-manager') save_manager.add_saveable( 'config', config_obj.save, config_obj.changed, - config_opt=('general', 'auto-save-config'), filename=filename) + config_opt='auto_save.config', filename=filename) for sect in config_obj.sections.values(): for opt in sect.values.values(): if opt.values['conf'] is None: @@ -204,7 +208,7 @@ def _init_key_config(parent): filename = os.path.join(standarddir.config(), 'keys.conf') save_manager.add_saveable( 'key-config', key_config.save, key_config.config_dirty, - config_opt=('general', 'auto-save-config'), filename=filename, + config_opt='auto_save.config', filename=filename, dirty=key_config.is_dirty) @@ -256,9 +260,11 @@ def init(parent=None): Args: parent: The parent to pass to QObjects which get initialized. """ + global val # _init_main_config(parent) configdata.init() _init_new_config(parent) + val = newconfig.val _init_key_config(parent) _init_misc() diff --git a/qutebrowser/config/newconfig.py b/qutebrowser/config/newconfig.py index 807ad0bfe..6dabf79e1 100644 --- a/qutebrowser/config/newconfig.py +++ b/qutebrowser/config/newconfig.py @@ -24,6 +24,15 @@ from PyQt5.QtCore import pyqtSignal, QObject from qutebrowser.config import configdata +from qutebrowser.utils import utils + +# An easy way to access the config from other code via config.val.foo +val = None + + +class UnknownOptionError(Exception): + + """Raised by NewConfigManager when an option is unknown.""" class SectionStub: @@ -48,16 +57,61 @@ class NewConfigManager(QObject): super().__init__(parent) self._values = {} - def _key(self, sect, opt=None): - if opt is None: - # New usage - return sect - return sect + '.' + opt - def read_defaults(self): for name, option in configdata.DATA.items(): self._values[name] = option - def get(self, section, option): - val = self._values[self._key(section, option)] + def get(self, option): + try: + val = self._values[option] + except KeyError as e: + raise UnknownOptionError(e) return val.typ.transform(val.default) + + def is_valid_prefix(self, prefix): + """Check whether the given prefix is a valid prefix for some option.""" + return any(key.startswith(prefix + '.') for key in self._values) + + +class ConfigContainer: + + """An object implementing config access via __getattr__. + + Attributes: + _manager: The ConfigManager object. + _prefix: The __getattr__ chain leading up to this object. + """ + + def __init__(self, manager, prefix=''): + self._manager = manager + self._prefix = prefix + + def __repr__(self): + return utils.get_repr(self, constructor=True, manager=self._manager, + prefix=self._prefix) + + def __getattr__(self, attr): + """Get an option or a new ConfigContainer with the added prefix. + + If we get an option which exists, we return the value for it. + If we get a part of an option name, we return a new ConfigContainer. + + Those two never overlap as configdata.py ensures there are no shadowing + options. + """ + name = self._join(attr) + if self._manager.is_valid_prefix(name): + return ConfigContainer(manager=self._manager, prefix=name) + # If it's not a valid prefix, this will raise NoOptionError. + self._manager.get(name) + + def __setattr__(self, attr, value): + if attr.startswith('_'): + return super().__setattr__(attr, value) + self._handler(self._join(attr), value) + + def _join(self, attr): + if self._prefix: + return '{}.{}'.format(self._prefix, attr) + else: + return attr diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 670cde853..897abb841 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -271,7 +271,7 @@ class BaseKeyParser(QObject): count: The count to pass. """ self._debug_log("Ambiguous match for '{}'".format(self._keystring)) - time = config.get('input', 'timeout') + time = config.val.input.timeout if time == 0: # execute immediately self.clear_keystring() diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py index 4ef393b03..bd0a5a1e9 100644 --- a/qutebrowser/keyinput/modeparsers.py +++ b/qutebrowser/keyinput/modeparsers.py @@ -74,7 +74,7 @@ class NormalKeyParser(keyparser.CommandKeyParser): return self.Match.none match = super()._handle_single_key(e) if match == self.Match.partial: - timeout = config.get('input', 'partial-timeout') + timeout = config.val.input.partial_timeout if timeout != 0: self._partial_timer.setInterval(timeout) self._partial_timer.timeout.connect(self._clear_partial_match) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 067b536bf..67aa9e125 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -60,7 +60,7 @@ def get_window(via_ipc, force_window=False, force_tab=False, # Initial main window return 0 - open_target = config.get('general', 'new-instance-open-target') + open_target = config.val.new_instance_open_target # Apply any target overrides, ordered by precedence if force_target is not None: @@ -98,7 +98,7 @@ def get_window(via_ipc, force_window=False, force_tab=False, def get_target_window(): """Get the target window for new tabs, or None if none exist.""" try: - win_mode = config.get('general', 'new-instance-open-target.window') + win_mode = config.val.new_instance_open_target.window if win_mode == 'last-focused': return objreg.last_focused_window() elif win_mode == 'first-opened': @@ -163,7 +163,7 @@ class MainWindow(QWidget): self._init_downloadmanager() self._downloadview = downloadview.DownloadView(self.win_id) - if config.get('general', 'private-browsing'): + if config.val.private_browsing: # This setting always trumps what's passed in. private = True else: @@ -250,7 +250,7 @@ class MainWindow(QWidget): left = (self.width() - width) / 2 if centered else 0 height_padding = 20 - status_position = config.get('ui', 'status-position') + status_position = config.val.ui.status_position if status_position == 'bottom': if self.status.isVisible(): status_height = self.status.height() @@ -341,8 +341,8 @@ class MainWindow(QWidget): self._vbox.removeWidget(self.tabbed_browser) self._vbox.removeWidget(self._downloadview) self._vbox.removeWidget(self.status) - downloads_position = config.get('ui', 'downloads-position') - status_position = config.get('ui', 'status-position') + downloads_position = config.val.ui.downloads_position + status_position = config.val.ui.status_position widgets = [self.tabbed_browser] if downloads_position == 'top': @@ -536,7 +536,7 @@ class MainWindow(QWidget): if crashsignal.is_crashing: e.accept() return - confirm_quit = config.get('ui', 'confirm-quit') + confirm_quit = config.val.ui.confirm_quit tab_count = self.tabbed_browser.count() download_model = objreg.get('download-model', scope='window', window=self.win_id) diff --git a/qutebrowser/mainwindow/messageview.py b/qutebrowser/mainwindow/messageview.py index 7d0d2b682..92bdd17ac 100644 --- a/qutebrowser/mainwindow/messageview.py +++ b/qutebrowser/mainwindow/messageview.py @@ -98,7 +98,7 @@ class MessageView(QWidget): @config.change_filter('ui', 'message-timeout') def _set_clear_timer_interval(self): """Configure self._clear_timer according to the config.""" - interval = config.get('ui', 'message-timeout') + interval = config.val.ui.message_timeout if interval != 0: self._clear_timer.setInterval(interval) @@ -127,7 +127,7 @@ class MessageView(QWidget): widget = Message(level, text, replace=replace, parent=self) self._vbox.addWidget(widget) widget.show() - if config.get('ui', 'message-timeout') != 0: + if config.val.ui.message_timeout != 0: self._clear_timer.start() self._messages.append(widget) self._last_text = text diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py index c38a41caa..8a1ee66d4 100644 --- a/qutebrowser/mainwindow/prompt.py +++ b/qutebrowser/mainwindow/prompt.py @@ -233,9 +233,9 @@ class PromptContainer(QWidget): """ STYLESHEET = """ - {% set prompt_radius = config.get('ui', 'prompt-radius') %} + {% set prompt_radius = config.val.ui.prompt_radius %} QWidget#PromptContainer { - {% if config.get('ui', 'status-position') == 'top' %} + {% if config.val.ui.status_position == 'top' %} border-bottom-left-radius: {{ prompt_radius }}px; border-bottom-right-radius: {{ prompt_radius }}px; {% else %} @@ -566,7 +566,7 @@ class FilenamePrompt(_BasePrompt): self.setFocusProxy(self._lineedit) self._init_key_label() - if config.get('ui', 'prompt-filebrowser'): + if config.val.ui.prompt_filebrowser: self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) @pyqtSlot(str) @@ -628,7 +628,7 @@ class FilenamePrompt(_BasePrompt): self._file_view.setModel(self._file_model) self._file_view.clicked.connect(self._insert_path) - if config.get('ui', 'prompt-filebrowser'): + if config.val.ui.prompt_filebrowser: self._vbox.addWidget(self._file_view) else: self._file_view.hide() diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py index ee3665ce2..513b7ad83 100644 --- a/qutebrowser/mainwindow/statusbar/bar.py +++ b/qutebrowser/mainwindow/statusbar/bar.py @@ -211,7 +211,7 @@ class StatusBar(QWidget): @pyqtSlot() def maybe_hide(self): """Hide the statusbar if it's configured to do so.""" - hide = config.get('ui', 'hide-statusbar') + hide = config.val.ui.hide_statusbar tab = self._current_tab() if hide or (tab is not None and tab.data.fullscreen): self.hide() @@ -219,7 +219,7 @@ class StatusBar(QWidget): self.show() def _set_hbox_padding(self): - padding = config.get('ui', 'statusbar-padding') + padding = config.val.ui.statusbar_padding self._hbox.setContentsMargins(padding.left, 0, padding.right, 0) @pyqtProperty('QStringList') @@ -344,7 +344,7 @@ class StatusBar(QWidget): def minimumSizeHint(self): """Set the minimum height to the text height plus some padding.""" - padding = config.get('ui', 'statusbar-padding') + padding = config.val.ui.statusbar_padding width = super().minimumSizeHint().width() height = self.fontMetrics().height() + padding.top + padding.bottom return QSize(width, height) diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index e0468330e..377825d6f 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -170,7 +170,7 @@ class TabbedBrowser(tabwidget.TabWidget): fields = self.get_tab_fields(idx) fields['id'] = self._win_id - fmt = config.get('ui', 'window-title-format') + fmt = config.val.ui.window_title_format self.window().setWindowTitle(fmt.format(**fields)) def _connect_tab_signals(self, tab): @@ -239,7 +239,7 @@ class TabbedBrowser(tabwidget.TabWidget): tab: The QWebView to be closed. add_undo: Whether the tab close can be undone. """ - last_close = config.get('tabs', 'last-close') + last_close = config.val.tabs.last_close count = self.count() if last_close == 'ignore' and count == 1: @@ -257,10 +257,10 @@ class TabbedBrowser(tabwidget.TabWidget): elif last_close == 'blank': self.openurl(QUrl('about:blank'), newtab=True) elif last_close == 'startpage': - url = QUrl(config.get('general', 'startpage')[0]) + url = QUrl(config.val.startpage[0]) self.openurl(url, newtab=True) elif last_close == 'default-page': - url = config.get('general', 'default-page') + url = config.val.default_page self.openurl(url, newtab=True) def _remove_tab(self, tab, *, add_undo=True, crashed=False): @@ -316,15 +316,15 @@ class TabbedBrowser(tabwidget.TabWidget): def undo(self): """Undo removing of a tab.""" # Remove unused tab which may be created after the last tab is closed - last_close = config.get('tabs', 'last-close') + last_close = config.val.tabs.last_close use_current_tab = False if last_close in ['blank', 'startpage', 'default-page']: only_one_tab_open = self.count() == 1 no_history = len(self.widget(0).history) == 1 urls = { 'blank': QUrl('about:blank'), - 'startpage': QUrl(config.get('general', 'startpage')[0]), - 'default-page': config.get('general', 'default-page'), + 'startpage': QUrl(config.val.startpage[0]), + 'default_page': config.val.default_page, } first_tab_url = self.widget(0).url() last_close_urlstr = urls[last_close].toString().rstrip('/') @@ -409,7 +409,7 @@ class TabbedBrowser(tabwidget.TabWidget): "explicit {}, idx {}".format( url, background, explicit, idx)) - if (config.get('tabs', 'tabs-are-windows') and self.count() > 0 and + if (config.val.tabs.tabs_are_windows and self.count() > 0 and not ignore_tabs_are_windows): from qutebrowser.mainwindow import mainwindow window = mainwindow.MainWindow(private=self.private) @@ -430,7 +430,7 @@ class TabbedBrowser(tabwidget.TabWidget): tab.openurl(url) if background is None: - background = config.get('tabs', 'background-tabs') + background = config.val.tabs.background_tabs if background: # Make sure the background tab has the correct initial size. # With a foreground tab, it's going to be resized correctly by the @@ -460,9 +460,9 @@ class TabbedBrowser(tabwidget.TabWidget): The index of the new tab. """ if explicit: - pos = config.get('tabs', 'new-tab-position-explicit') + pos = config.val.tabs.new_tab_position_explicit else: - pos = config.get('tabs', 'new-tab-position') + pos = config.val.tabs.new_tab_position if pos == 'prev': idx = self._tab_insert_idx_left # On first sight, we'd think we have to decrement @@ -488,8 +488,8 @@ class TabbedBrowser(tabwidget.TabWidget): @config.change_filter('tabs', 'show-favicons') def update_favicons(self): """Update favicons when config was changed.""" - show = config.get('tabs', 'show-favicons') - tabs_are_wins = config.get('tabs', 'tabs-are-windows') + show = config.val.tabs.show_favicons + tabs_are_wins = config.val.tabs.tabs_are_windows for i, tab in enumerate(self.widgets()): if show: self.setTabIcon(i, tab.icon()) @@ -517,8 +517,8 @@ class TabbedBrowser(tabwidget.TabWidget): tab.data.keep_icon = False else: self.setTabIcon(idx, QIcon()) - if (config.get('tabs', 'tabs-are-windows') and - config.get('tabs', 'show-favicons')): + if (config.val.tabs.tabs_are_windows and + config.val.tabs.show_favicons): self.window().setWindowIcon(self.default_window_icon) if idx == self.currentIndex(): self.update_window_title() @@ -582,7 +582,7 @@ class TabbedBrowser(tabwidget.TabWidget): tab: The WebView where the title was changed. icon: The new icon """ - if not config.get('tabs', 'show-favicons'): + if not config.val.tabs.show_favicons: return try: idx = self._tab_index(tab) @@ -590,7 +590,7 @@ class TabbedBrowser(tabwidget.TabWidget): # We can get signals for tabs we already deleted... return self.setTabIcon(idx, icon) - if config.get('tabs', 'tabs-are-windows'): + if config.val.tabs.tabs_are_windows: self.window().setWindowIcon(icon) @pyqtSlot(usertypes.KeyMode) @@ -643,9 +643,9 @@ class TabbedBrowser(tabwidget.TabWidget): except TabDeletedError: # We can get signals for tabs we already deleted... return - start = config.get('colors', 'tabs.indicator.start') - stop = config.get('colors', 'tabs.indicator.stop') - system = config.get('colors', 'tabs.indicator.system') + start = config.val.colors.tabs.indicator.start + stop = config.val.colors.tabs.indicator.stop + system = config.val.colors.tabs.indicator.system color = utils.interpolate_color(start, stop, perc, system) self.set_tab_indicator_color(idx, color) self.update_tab_title(idx) @@ -660,12 +660,12 @@ class TabbedBrowser(tabwidget.TabWidget): # We can get signals for tabs we already deleted... return if ok: - start = config.get('colors', 'tabs.indicator.start') - stop = config.get('colors', 'tabs.indicator.stop') - system = config.get('colors', 'tabs.indicator.system') + start = config.val.colors.tabs.indicator.start + stop = config.val.colors.tabs.indicator.stop + system = config.val.colors.tabs.indicator.system color = utils.interpolate_color(start, stop, 100, system) else: - color = config.get('colors', 'tabs.indicator.error') + color = config.val.colors.tabs.indicator.error self.set_tab_indicator_color(idx, color) self.update_tab_title(idx) if idx == self.currentIndex(): diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 2c4eb6eab..6fdbea5dd 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -74,10 +74,10 @@ class TabWidget(QTabWidget): # WORKAROUND for PyQt 5.2 return tabbar = self.tabBar() - self.setMovable(config.get('tabs', 'movable')) + self.setMovable(config.val.tabs.movable) self.setTabsClosable(False) - position = config.get('tabs', 'position') - selection_behavior = config.get('tabs', 'select-on-remove') + position = config.val.tabs.position + selection_behavior = config.val.tabs.select_on_remove self.setTabPosition(position) tabbar.vertical = position in [QTabWidget.West, QTabWidget.East] tabbar.setSelectionBehaviorOnRemove(selection_behavior) @@ -140,8 +140,8 @@ class TabWidget(QTabWidget): fields['title'] = fields['title'].replace('&', '&&') fields['index'] = idx + 1 - fmt = config.get('tabs', 'title-format') - fmt_pinned = config.get('tabs', 'title-format-pinned') + fmt = config.val.tabs.title_format + fmt_pinned = config.val.tabs.title_format_pinned if tab.data.pinned: title = '' if fmt_pinned is None else fmt_pinned.format(**fields) @@ -313,7 +313,7 @@ class TabBar(QTabBar): self._auto_hide_timer = QTimer() self._auto_hide_timer.setSingleShot(True) self._auto_hide_timer.setInterval( - config.get('tabs', 'show-switching-delay')) + config.val.tabs.show_switching_delay) self._auto_hide_timer.timeout.connect(self.maybe_hide) self.setAutoFillBackground(True) self.set_colors() @@ -340,12 +340,12 @@ class TabBar(QTabBar): def on_show_switching_delay_changed(self): """Set timer interval when tabs->show-switching-delay got changed.""" self._auto_hide_timer.setInterval( - config.get('tabs', 'show-switching-delay')) + config.val.tabs.show_switching_delay) def on_current_changed(self): """Show tab bar when current tab got changed.""" self.maybe_hide() # for fullscreen tabs - show = config.get('tabs', 'show') + show = config.val.tabs.show if show == 'switching': self.show() self._auto_hide_timer.start() @@ -353,7 +353,7 @@ class TabBar(QTabBar): @pyqtSlot() def maybe_hide(self): """Hide the tab bar if needed.""" - show = config.get('tabs', 'show') + show = config.val.tabs.show tab = self._current_tab() if (show in ['never', 'switching'] or (show == 'multiple' and self.count() == 1) or @@ -411,21 +411,21 @@ class TabBar(QTabBar): @config.change_filter('fonts', 'tabbar') def set_font(self): """Set the tab bar font.""" - self.setFont(config.get('fonts', 'tabbar')) + self.setFont(config.val.fonts.tabbar) self.set_icon_size() @config.change_filter('tabs', 'favicon-scale') def set_icon_size(self): """Set the tab bar favicon size.""" size = self.fontMetrics().height() - 2 - size *= config.get('tabs', 'favicon-scale') + size *= config.val.tabs.favicon_scale self.setIconSize(QSize(size, size)) @config.change_filter('colors', 'tabs.bg.bar') def set_colors(self): """Set the tab bar colors.""" p = self.palette() - p.setColor(QPalette.Window, config.get('colors', 'tabs.bg.bar')) + p.setColor(QPalette.Window, config.val.colors.tabs.bg.bar) self.setPalette(p) @pyqtSlot(str, str) @@ -436,7 +436,7 @@ class TabBar(QTabBar): def mousePressEvent(self, e): """Override mousePressEvent to close tabs if configured.""" - button = config.get('tabs', 'close-mouse-button') + button = config.val.tabs.close_mouse_button if (e.button() == Qt.RightButton and button == 'right' or e.button() == Qt.MiddleButton and button == 'middle'): e.accept() @@ -457,7 +457,7 @@ class TabBar(QTabBar): A QSize. """ icon = self.tabIcon(index) - padding = config.get('tabs', 'padding') + padding = config.val.tabs.padding padding_h = padding.left + padding.right padding_v = padding.top + padding.bottom if icon.isNull(): @@ -468,7 +468,7 @@ class TabBar(QTabBar): icon_size = icon.actualSize(QSize(extent, extent)) padding_h += self.style().pixelMetric( PixelMetrics.icon_padding, None, self) - indicator_width = config.get('tabs', 'indicator-width') + indicator_width = config.val.tabs.indicator_width height = self.fontMetrics().height() + padding_v width = (self.fontMetrics().width('\u2026') + icon_size.width() + padding_h + indicator_width) @@ -488,7 +488,7 @@ class TabBar(QTabBar): minimum_size = self.minimumTabSizeHint(index) height = minimum_size.height() if self.vertical: - confwidth = str(config.get('tabs', 'width')) + confwidth = str(config.val.tabs.width) if confwidth.endswith('%'): main_window = objreg.get('main-window', scope='window', window=self._win_id) @@ -507,7 +507,7 @@ class TabBar(QTabBar): # get scroll buttons as soon as needed. size = minimum_size else: - tab_width_pinned_conf = config.get('tabs', 'pinned-width') + tab_width_pinned_conf = config.val.tabs.pinned_width try: pinned = self.tab_data(index, 'pinned') @@ -596,7 +596,7 @@ class TabBar(QTabBar): Args: e: The QWheelEvent """ - if config.get('tabs', 'mousewheel-tab-switching'): + if config.val.tabs.mousewheel_tab_switching: super().wheelEvent(e) else: tabbed_browser = objreg.get('tabbed-browser', scope='window', @@ -706,7 +706,7 @@ class TabBarStyle(QCommonStyle): elif element == QStyle.CE_TabBarTabLabel: if not opt.icon.isNull() and layouts.icon.isValid(): self._draw_icon(layouts, opt, p) - alignment = (config.get('tabs', 'title-alignment') | + alignment = (config.val.tabs.title_alignment | Qt.AlignVCenter | Qt.TextHideMnemonic) self._style.drawItemText(p, layouts.text, alignment, opt.palette, opt.state & QStyle.State_Enabled, @@ -775,8 +775,8 @@ class TabBarStyle(QCommonStyle): Return: A Layout namedtuple with two QRects. """ - padding = config.get('tabs', 'padding') - indicator_padding = config.get('tabs', 'indicator-padding') + padding = config.val.tabs.padding + indicator_padding = config.val.tabs.indicator_padding text_rect = QRect(opt.rect) if not text_rect.isValid(): @@ -787,7 +787,7 @@ class TabBarStyle(QCommonStyle): text_rect.adjust(padding.left, padding.top, -padding.right, -padding.bottom) - indicator_width = config.get('tabs', 'indicator-width') + indicator_width = config.val.tabs.indicator_width if indicator_width == 0: indicator_rect = QRect() else: @@ -830,10 +830,10 @@ class TabBarStyle(QCommonStyle): icon_state = (QIcon.On if opt.state & QStyle.State_Selected else QIcon.Off) # reserve space for favicon when tab bar is vertical (issue #1968) - position = config.get('tabs', 'position') + position = config.val.tabs.position if (opt.icon.isNull() and position in [QTabWidget.East, QTabWidget.West] and - config.get('tabs', 'show-favicons')): + config.val.tabs.show_favicons): tab_icon_size = icon_size else: actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state) diff --git a/qutebrowser/misc/consolewidget.py b/qutebrowser/misc/consolewidget.py index 963076c21..f7e06c56b 100644 --- a/qutebrowser/misc/consolewidget.py +++ b/qutebrowser/misc/consolewidget.py @@ -105,7 +105,7 @@ class ConsoleLineEdit(miscwidgets.CommandLineEdit): @config.change_filter('fonts', 'debug-console') def update_font(self): """Set the correct font.""" - self.setFont(config.get('fonts', 'debug-console')) + self.setFont(config.val.fonts.debug_console) class ConsoleTextEdit(QTextEdit): @@ -126,7 +126,7 @@ class ConsoleTextEdit(QTextEdit): @config.change_filter('fonts', 'debug-console') def update_font(self): """Update font when config changed.""" - self.setFont(config.get('fonts', 'debug-console')) + self.setFont(config.val.fonts.debug_console) def append_text(self, text): """Append new text and scroll output to bottom. diff --git a/qutebrowser/misc/crashdialog.py b/qutebrowser/misc/crashdialog.py index b670f80ed..115796259 100644 --- a/qutebrowser/misc/crashdialog.py +++ b/qutebrowser/misc/crashdialog.py @@ -432,7 +432,7 @@ class ExceptionCrashDialog(_CrashDialog): self._chk_log = QCheckBox("Include a debug log in the report", checked=True) try: - if config.get('general', 'private-browsing'): + if config.val.private_browsing: self._chk_log.setChecked(False) except Exception: log.misc.exception("Error while checking private browsing mode") @@ -524,7 +524,7 @@ class FatalCrashDialog(_CrashDialog): "accessed pages in the report.", checked=True) try: - if config.get('general', 'private-browsing'): + if config.val.private_browsing: self._chk_history.setChecked(False) except Exception: log.misc.exception("Error while checking private browsing mode") diff --git a/qutebrowser/misc/editor.py b/qutebrowser/misc/editor.py index 58a08daf1..dba12d529 100644 --- a/qutebrowser/misc/editor.py +++ b/qutebrowser/misc/editor.py @@ -75,7 +75,7 @@ class ExternalEditor(QObject): try: if exitcode != 0: return - encoding = config.get('general', 'editor-encoding') + encoding = config.val.editor_encoding try: with open(self._file.name, 'r', encoding=encoding) as f: text = f.read() @@ -102,7 +102,7 @@ class ExternalEditor(QObject): if self._text is not None: raise ValueError("Already editing a file!") self._text = text - encoding = config.get('general', 'editor-encoding') + encoding = config.val.editor_encoding try: # Close while the external process is running, as otherwise systems # with exclusive write access (e.g. Windows) may fail to update @@ -120,7 +120,7 @@ class ExternalEditor(QObject): self._proc = guiprocess.GUIProcess(what='editor', parent=self) self._proc.finished.connect(self.on_proc_closed) self._proc.error.connect(self.on_proc_error) - editor = config.get('general', 'editor') + editor = config.val.editor executable = editor[0] args = [arg.replace('{}', self._file.name) for arg in editor[1:]] log.procs.debug("Calling \"{}\" with args {}".format(executable, args)) diff --git a/qutebrowser/misc/keyhintwidget.py b/qutebrowser/misc/keyhintwidget.py index b42612b1b..2dfede7b4 100644 --- a/qutebrowser/misc/keyhintwidget.py +++ b/qutebrowser/misc/keyhintwidget.py @@ -51,7 +51,7 @@ class KeyHintView(QLabel): color: {{ color['keyhint.fg'] }}; background-color: {{ color['keyhint.bg'] }}; padding: 6px; - {% if config.get('ui', 'status-position') == 'top' %} + {% if config.val.ui.status_position == 'top' %} border-bottom-right-radius: 6px; {% else %} border-top-right-radius: 6px; @@ -90,7 +90,7 @@ class KeyHintView(QLabel): self.hide() return - blacklist = config.get('ui', 'keyhint-blacklist') or [] + blacklist = config.val.ui.keyhint_blacklist or [] keyconf = objreg.get('key-config') def blacklisted(keychain): @@ -107,9 +107,9 @@ class KeyHintView(QLabel): return # delay so a quickly typed keychain doesn't display hints - self._show_timer.setInterval(config.get('ui', 'keyhint-delay')) + self._show_timer.setInterval(config.val.ui.keyhint_delay) self._show_timer.start() - suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix')) + suffix_color = html.escape(config.val.colors.keyhint.fg.suffix) text = '' for key, cmd in bindings: diff --git a/qutebrowser/misc/savemanager.py b/qutebrowser/misc/savemanager.py index 509e5489a..57755b4cd 100644 --- a/qutebrowser/misc/savemanager.py +++ b/qutebrowser/misc/savemanager.py @@ -38,9 +38,8 @@ class Saveable: _dirty: Whether the saveable was changed since the last save. _save_handler: The function to call to save this Saveable. _save_on_exit: Whether to always save this saveable on exit. - _config_opt: A (section, option) tuple of a config option which decides - whether to auto-save or not. None if no such option - exists. + _config_opt: A config option which decides whether to auto-save or not. + None if no such option exists. _filename: The filename of the underlying file. """ @@ -82,7 +81,7 @@ class Saveable: force: Force saving, no matter what. """ if (self._config_opt is not None and - (not config.get(*self._config_opt)) and + (not config.get(self._config_opt)) and (not explicit) and (not force)): if not silent: log.save.debug("Not saving {name} because autosaving has been " @@ -130,7 +129,7 @@ class SaveManager(QObject): @config.change_filter('general', 'auto-save-interval') def set_autosave_interval(self): """Set the auto-save interval.""" - interval = config.get('general', 'auto-save-interval') + interval = config.val.auto_save.interval if interval == 0: self._save_timer.stop() else: @@ -145,8 +144,7 @@ class SaveManager(QObject): name: The name to use. save: The function to call to save this saveable. changed: The signal emitted when this saveable changed. - config_opt: A (section, option) tuple deciding whether to auto-save - or not. + config_opt: An option deciding whether to auto-save or not. filename: The filename of the underlying file, so we can force saving if it doesn't exist. dirty: Whether the saveable is already dirty. diff --git a/qutebrowser/misc/sessions.py b/qutebrowser/misc/sessions.py index 5ce4ee66d..3bbee29f9 100644 --- a/qutebrowser/misc/sessions.py +++ b/qutebrowser/misc/sessions.py @@ -259,7 +259,7 @@ class SessionManager(QObject): object. """ if name is default: - name = config.get('general', 'session-default-name') + name = config.val.session_default_name if name is None: if self._current is not None: name = self._current diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index 4cd0e94d0..24bbfbc9c 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -99,7 +99,7 @@ def _get_search_url(txt): engine, term = _parse_search_term(txt) assert term if engine is None: - template = config.get('searchengines', 'DEFAULT') + template = config.val.searchengines.DEFAULT else: template = config.get('searchengines', engine) url = qurl_from_user_input(template.format(urllib.parse.quote(term))) @@ -194,7 +194,7 @@ def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True, url = qurl_from_user_input(urlstr) log.url.debug("Converting fuzzy term {!r} to URL -> {}".format( urlstr, url.toDisplayString())) - if do_search and config.get('general', 'auto-search') and urlstr: + if do_search and config.val.auto_search and urlstr: qtutils.ensure_valid(url) else: if not url.isValid(): @@ -239,7 +239,7 @@ def is_url(urlstr): Return: True if it is a valid URL, False otherwise. """ - autosearch = config.get('general', 'auto-search') + autosearch = config.val.auto_search log.url.debug("Checking if {!r} is a URL (autosearch={}).".format( urlstr, autosearch)) diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index 0b527637e..114be6a52 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -836,7 +836,7 @@ def open_file(filename, cmdline=None): from qutebrowser.config import config # the default program to open downloads with - will be empty string # if we want to use the default - override = config.get('general', 'default-open-dispatcher') + override = config.val.default_open_dispatcher # precedence order: cmdline > default-open-dispatcher > openUrl