def queryProxy(self, query): """Get the QNetworkProxies for a query. Args: query: The QNetworkProxyQuery to get a proxy for. Return: A list of QNetworkProxy objects in order of preference. """ proxy = config.get('network', 'proxy') if proxy is configtypes.SYSTEM_PROXY: proxies = QNetworkProxyFactory.systemProxyForQuery(query) elif isinstance(proxy, pac.PACFetcher): proxies = proxy.resolve(query) else: proxies = [proxy] for p in proxies: if p.type() != QNetworkProxy.NoProxy: capabilities = p.capabilities() if config.get('network', 'proxy-dns-requests'): capabilities |= QNetworkProxy.HostNameLookupCapability else: capabilities &= ~QNetworkProxy.HostNameLookupCapability p.setCapabilities(capabilities) return proxies
def close_tab(self, tab): """Close a tab. Args: tab: The QWebView to be closed. """ last_close = config.get('tabs', 'last-close') count = self.count() if last_close == 'ignore' and count == 1: return self._remove_tab(tab) if count == 1: # We just closed the last tab above. if last_close == 'close': self.close_window.emit() elif last_close == 'blank': self.openurl(QUrl('about:blank'), newtab=True) elif last_close == 'startpage': url = QUrl(config.get('general', 'startpage')[0]) self.openurl(url, newtab=True) elif last_close == 'default-page': url = config.get('general', 'default-page') self.openurl(url, newtab=True)
def _hint_strings(self, elems): """Calculate the hint strings for elems. Inspired by Vimium. Args: elems: The elements to get hint strings for. Return: A list of hint strings, in the same order as the elements. """ hint_mode = config.get('hints', 'mode') if hint_mode == 'word': try: return self._word_hinter.hint(elems) except WordHintingError as e: message.error(self._win_id, str(e), immediately=True) # falls back on letter hints 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': return self._hint_scattered(min_chars, chars, elems) else: return self._hint_linear(min_chars, chars, elems)
def _get_new_tab_idx(self, explicit): """Get the index of a tab to insert. Args: explicit: Whether the tab was opened explicitely. Return: The index of the new tab. """ if explicit: pos = config.get('tabs', 'new-tab-position-explicit') else: pos = config.get('tabs', 'new-tab-position') if pos == 'left': idx = self._tab_insert_idx_left # On first sight, we'd think we have to decrement # self._tab_insert_idx_left here, as we want the next tab to be # *before* the one we just opened. However, since we opened a tab # *to the left* of the currently focused tab, indices will shift by # 1 automatically. elif pos == 'right': idx = self._tab_insert_idx_right self._tab_insert_idx_right += 1 elif pos == 'first': idx = 0 elif pos == 'last': idx = -1 else: raise ValueError("Invalid new-tab-position '{}'.".format(pos)) log.webview.debug("new-tab-position {} -> opening new tab at {}, " "next left: {} / right: {}".format( pos, idx, self._tab_insert_idx_left, self._tab_insert_idx_right)) return idx
def minimumTabSizeHint(self, index): """Set the minimum tab size to indicator/icon/... text. Args: index: The index of the tab to get a size hint for. Return: A QSize. """ icon = self.tabIcon(index) padding = config.get('tabs', 'padding') padding_h = padding.left + padding.right padding_v = padding.top + padding.bottom if icon.isNull(): icon_size = QSize(0, 0) else: extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None, self) icon_size = icon.actualSize(QSize(extent, extent)) padding_h += self.style().pixelMetric( PixelMetrics.icon_padding, None, self) indicator_width = config.get('tabs', 'indicator-width') height = self.fontMetrics().height() + padding_v width = (self.fontMetrics().width('\u2026') + icon_size.width() + padding_h + indicator_width) return QSize(width, height)
def minimumTabSizeHint(self, index): """Set the minimum tab size to indicator/icon/... text. Args: index: The index of the tab to get a size hint for. Return: A QSize. """ icon = self.tabIcon(index) padding_count = 2 if icon.isNull(): icon_size = QSize(0, 0) else: extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None, self) icon_size = icon.actualSize(QSize(extent, extent)) padding_count += 1 indicator_width = config.get('tabs', 'indicator-width') if indicator_width != 0: indicator_width += config.get('tabs', 'indicator-space') padding_width = self.style().pixelMetric(PM_TabBarPadding, None, self) height = self.fontMetrics().height() width = (self.fontMetrics().width('\u2026') + icon_size.width() + padding_count * padding_width + indicator_width) return QSize(width, height)
def edit(self, text): """Edit a given text. Args: text: The initial text to edit. """ if self._text is not None: raise ValueError("Already editing a file!") self._text = text try: self._oshandle, self._filename = tempfile.mkstemp( text=True, prefix='qutebrowser-editor-') if text: encoding = config.get('general', 'editor-encoding') with open(self._filename, 'w', encoding=encoding) as f: f.write(text) # pragma: no branch except OSError as e: message.error(self._win_id, "Failed to create initial file: " "{}".format(e)) return self._proc = guiprocess.GUIProcess(self._win_id, 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') executable = editor[0] args = [self._filename if arg == '{}' else arg for arg in editor[1:]] log.procs.debug("Calling \"{}\" with args {}".format(executable, args)) self._proc.start(executable, args)
def close_tab(self, tab, *, add_undo=True): """Close a tab. Args: tab: The QWebView to be closed. add_undo: Whether the tab close can be undone. """ last_close = config.get('tabs', 'last-close') count = self.count() if last_close == 'ignore' and count == 1: return # If we are removing a pinned tab, decrease count if tab.data.pinned: self.tabBar().pinned_count -= 1 self._remove_tab(tab, add_undo=add_undo) if count == 1: # We just closed the last tab above. if last_close == 'close': self.close_window.emit() elif last_close == 'blank': self.openurl(QUrl('about:blank'), newtab=True) elif last_close == 'startpage': url = QUrl(config.get('general', 'startpage')[0]) self.openurl(url, newtab=True) elif last_close == 'default-page': url = config.get('general', 'default-page') self.openurl(url, newtab=True)
def search(self, text, reverse=False): """Search for a text on the current page. Args: text: The text to search for. reverse: Reverse search direction. """ if self._text is not None and self._text != text: # We first clear the marked text, then the highlights self.do_search.emit('', 0) self.do_search.emit('', QWebPage.HighlightAllOccurrences) self._text = text self._flags = 0 ignore_case = config.get('general', 'ignore-case') if ignore_case == 'smart': if not text.islower(): self._flags |= QWebPage.FindCaseSensitively elif not ignore_case: self._flags |= QWebPage.FindCaseSensitively if config.get('general', 'wrap-search'): self._flags |= QWebPage.FindWrapsAroundDocument if reverse: self._flags |= QWebPage.FindBackward # We actually search *twice* - once to highlight everything, then again # to get a mark so we can navigate. self.do_search.emit(self._text, self._flags) self.do_search.emit(self._text, self._flags | QWebPage.HighlightAllOccurrences)
def close_tab(self, tab): """Close a tab. Args: tab: The QWebView to be closed. """ last_close = config.get("tabs", "last-close") count = self.count() if last_close == "ignore" and count == 1: return self._remove_tab(tab) if count == 1: # We just closed the last tab above. if last_close == "close": self.close_window.emit() elif last_close == "blank": self.openurl(QUrl("about:blank"), newtab=True) elif last_close == "startpage": url = QUrl(config.get("general", "startpage")[0]) self.openurl(url, newtab=True) elif last_close == "default-page": url = config.get("general", "default-page") self.openurl(url, newtab=True)
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") use_current_tab = False if last_close in ["blank", "startpage", "default-page"]: only_one_tab_open = self.count() == 1 no_history = self.widget(0).history().count() == 1 urls = { "blank": QUrl("about:blank"), "startpage": QUrl(config.get("general", "startpage")[0]), "default-page": config.get("general", "default-page"), } first_tab_url = self.widget(0).page().mainFrame().requestedUrl() last_close_urlstr = urls[last_close].toString().rstrip("/") first_tab_urlstr = first_tab_url.toString().rstrip("/") last_close_url_used = first_tab_urlstr == last_close_urlstr use_current_tab = only_one_tab_open and no_history and last_close_url_used url, history_data = self._undo_stack.pop() if use_current_tab: self.openurl(url, newtab=False) newtab = self.widget(0) else: newtab = self.tabopen(url, background=False) qtutils.deserialize(history_data, newtab.history())
def search(self, text="", reverse=False): """Search for a text on the current page. With no text, clear results. Args: text: The text to search for. reverse: Reverse search direction. """ view = self._current_widget() if view.search_text is not None and view.search_text != text: # We first clear the marked text, then the highlights view.search('', 0) view.search('', QWebPage.HighlightAllOccurrences) flags = 0 ignore_case = config.get('general', 'ignore-case') if ignore_case == 'smart': if not text.islower(): flags |= QWebPage.FindCaseSensitively elif not ignore_case: flags |= QWebPage.FindCaseSensitively if config.get('general', 'wrap-search'): flags |= QWebPage.FindWrapsAroundDocument if reverse: flags |= QWebPage.FindBackward # We actually search *twice* - once to highlight everything, then again # to get a mark so we can navigate. view.search(text, flags) view.search(text, flags | QWebPage.HighlightAllOccurrences) view.search_text = text view.search_flags = flags
def _hint_strings(self, elems): """Calculate the hint strings for elems. Inspired by Vimium. Args: elems: The elements to get hint strings for. Return: A list of hint strings, in the same order as the elements. """ if not elems: return [] hint_mode = self._context.hint_mode if hint_mode == "word": try: return self._word_hinter.hint(elems) except HintingError as e: message.error(str(e)) # falls back on letter hints 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": return self._hint_scattered(min_chars, chars, elems) else: return self._hint_linear(min_chars, chars, elems)
def show_help(self, topic=None): r"""Show help about a command or setting. Args: topic: The topic to show help for. - :__command__ for commands. - __section__\->__option__ for settings. """ if topic is None: path = 'index.html' elif topic.startswith(':'): command = topic[1:] if command not in cmdutils.cmd_dict: raise cmdexc.CommandError("Invalid command {}!".format( command)) path = 'commands.html#{}'.format(command) elif '->' in topic: parts = topic.split('->') if len(parts) != 2: raise cmdexc.CommandError("Invalid help topic {}!".format( topic)) try: config.get(*parts) except config.NoSectionError: raise cmdexc.CommandError("Invalid section {}!".format( parts[0])) except config.NoOptionError: raise cmdexc.CommandError("Invalid option {}!".format( parts[1])) path = 'settings.html#{}'.format(topic.replace('->', '-')) else: raise cmdexc.CommandError("Invalid help topic {}!".format(topic)) self.openurl('qute://help/{}'.format(path))
def completion_item_focus(self, which): """Shift the focus of the completion menu to another item. Args: which: 'next', 'prev', 'next-category', or 'prev-category'. """ if not self._active: return selmodel = self.selectionModel() if which == 'next': idx = self._next_idx(upwards=False) elif which == 'prev': idx = self._next_idx(upwards=True) elif which == 'next-category': idx = self._next_category_idx(upwards=False) elif which == 'prev-category': idx = self._next_category_idx(upwards=True) else: # pragma: no cover raise ValueError("Invalid 'which' value {!r}".format(which)) if not idx.isValid(): return selmodel.setCurrentIndex( idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) count = self.model().count() if count == 0: self.hide() elif count == 1 and config.get('completion', 'quick-complete'): self.hide() elif config.get('completion', 'show') == 'auto': self.show()
def resize_completion(self): """Adjust completion according to config.""" if not self._completion.isVisible(): # It doesn't make sense to resize the completion as long as it's # not shown anyways. return # Get the configured height/percentage. confheight = str(config.get("completion", "height")) if confheight.endswith("%"): perc = int(confheight.rstrip("%")) height = self.height() * perc / 100 else: height = int(confheight) # Shrink to content size if needed and shrinking is enabled if config.get("completion", "shrink"): contents_height = ( self._completion.viewportSizeHint().height() + self._completion.horizontalScrollBar().sizeHint().height() ) if contents_height <= height: height = contents_height else: contents_height = -1 # hpoint now would be the bottom-left edge of the widget if it was on # the top of the main window. topleft_y = self.height() - self.status.height() - height topleft_y = qtutils.check_overflow(topleft_y, "int", fatal=False) topleft = QPoint(0, topleft_y) bottomright = self.status.geometry().topRight() rect = QRect(topleft, bottomright) log.misc.debug("completion rect: {}".format(rect)) if rect.isValid(): self._completion.setGeometry(rect)
def _get_search_url(txt): """Get a search engine URL for a text. Args: txt: Text to search for. Return: The search URL as a QUrl. """ log.url.debug("Finding search engine for '{}'".format(txt)) r = re.compile(r'(^\w+)\s+(.+)($|\s+)') m = r.search(txt) if m: engine = m.group(1) try: template = config.get('searchengines', engine) except configexc.NoOptionError: template = config.get('searchengines', 'DEFAULT') term = txt else: term = m.group(2).rstrip() log.url.debug("engine {}, term '{}'".format(engine, term)) else: template = config.get('searchengines', 'DEFAULT') term = txt log.url.debug("engine: default, term '{}'".format(txt)) if not term: raise FuzzyUrlError("No search term given") url = qurl_from_user_input(template.format(urllib.parse.quote(term))) qtutils.ensure_valid(url) return url
def paintEvent(self, _e): """Override paintEvent to draw the tabs like we want to.""" p = QStylePainter(self) tab = QStyleOptionTab() selected = self.currentIndex() for idx in range(self.count()): self.initStyleOption(tab, idx) if idx == selected: color = config.get('colors', 'tab.bg.selected') elif idx % 2: color = config.get('colors', 'tab.bg.odd') else: color = config.get('colors', 'tab.bg.even') tab.palette.setColor(QPalette.Window, color) tab.palette.setColor(QPalette.WindowText, config.get('colors', 'tab.fg')) indicator_color = self.tabData(idx) if indicator_color is None: indicator_color = QColor() tab.palette.setColor(QPalette.Base, indicator_color) if tab.rect.right() < 0 or tab.rect.left() > self.width(): # Don't bother drawing a tab if the entire tab is outside of # the visible tab bar. continue p.drawControl(QStyle.CE_TabBarTab, tab)
def _handle_auto_follow(self, keystr="", filterstr="", visible=None): """Handle the auto-follow option.""" if visible is None: visible = {string: label for string, label in self._context.labels.items() if label.isVisible()} if len(visible) != 1: return auto_follow = config.get('hints', 'auto-follow') if auto_follow == "always": follow = True elif auto_follow == "unique-match": follow = keystr or filterstr elif auto_follow == "full-match": elemstr = str(list(visible.values())[0].elem) filter_match = self._filter_matches_exactly(filterstr, elemstr) follow = (keystr in visible) or filter_match else: follow = False # save the keystr of the only one visible hint to be picked up # later by self.follow_hint self._context.to_follow = list(visible.keys())[0] if follow: # apply auto-follow-timeout timeout = config.get('hints', 'auto-follow-timeout') keyparsers = objreg.get('keyparsers', scope='window', window=self._win_id) normal_parser = keyparsers[usertypes.KeyMode.normal] normal_parser.set_inhibited_timeout(timeout) # unpacking gets us the first (and only) key in the dict. self._fire(*visible)
def paintEvent(self, _e): """Override paintEvent to draw the tabs like we want to.""" # pylint: disable=bad-config-call # WORKAROUND for https://bitbucket.org/logilab/astroid/issue/104 p = QStylePainter(self) selected = self.currentIndex() for idx in range(self.count()): tab = QStyleOptionTab() self.initStyleOption(tab, idx) bg_parts = ['tabs', 'bg'] fg_parts = ['tabs', 'fg'] if idx == selected: bg_parts.append('selected') fg_parts.append('selected') if idx % 2: bg_parts.append('odd') fg_parts.append('odd') else: bg_parts.append('even') fg_parts.append('even') bg_color = config.get('colors', '.'.join(bg_parts)) fg_color = config.get('colors', '.'.join(fg_parts)) tab.palette.setColor(QPalette.Window, bg_color) tab.palette.setColor(QPalette.WindowText, fg_color) indicator_color = self.tab_indicator_color(idx) tab.palette.setColor(QPalette.Base, indicator_color) if tab.rect.right() < 0 or tab.rect.left() > self.width(): # Don't bother drawing a tab if the entire tab is outside of # the visible tab bar. continue p.drawControl(QStyle.CE_TabBarTab, tab)
def _add_widgets(self): """Add or readd all widgets to the VBox.""" 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') widgets = [self.tabbed_browser] if downloads_position == 'top': widgets.insert(0, self._downloadview) elif downloads_position == 'bottom': widgets.append(self._downloadview) else: raise ValueError("Invalid position {}!".format(downloads_position)) if status_position == 'top': widgets.insert(0, self.status) elif status_position == 'bottom': widgets.append(self.status) else: raise ValueError("Invalid position {}!".format(status_position)) for widget in widgets: self._vbox.addWidget(widget)
def _get_icon_rect(self, opt, text_rect): """Get a QRect for the icon to draw. Args: opt: QStyleOptionTab text_rect: The QRect for the text. Return: A QRect. """ icon_size = opt.iconSize if not icon_size.isValid(): icon_extent = self.pixelMetric(QStyle.PM_SmallIconSize) icon_size = QSize(icon_extent, icon_extent) icon_mode = (QIcon.Normal if opt.state & QStyle.State_Enabled else QIcon.Disabled) 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') if (opt.icon.isNull() and position in [QTabWidget.East, QTabWidget.West] and config.get('tabs', 'show-favicons')): tab_icon_size = icon_size else: actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state) tab_icon_size = QSize( min(actual_size.width(), icon_size.width()), min(actual_size.height(), icon_size.height())) icon_rect = QRect(text_rect.left(), text_rect.top() + 1, tab_icon_size.width(), tab_icon_size.height()) icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect) return icon_rect
def _parse_search_term(s): """Get a search engine name and search term from a string. Args: s: The string to get a search engine for. Return: A (engine, term) tuple, where engine is None for the default engine. """ s = s.strip() split = s.split(maxsplit=1) if len(split) == 2: engine = split[0] try: config.get('searchengines', engine) except configexc.NoOptionError: engine = None term = s else: term = split[1] elif not split: raise ValueError("Empty search term!") else: engine = None term = s log.url.debug("engine {}, term {!r}".format(engine, term)) return (engine, term)
def edit(self, text): """Edit a given text. Args: text: The initial text to edit. """ if self._text is not None: raise ValueError("Already editing a file!") self._text = text encoding = config.get('general', 'editor-encoding') try: # Close while the external process is running, as otherwise systems # with exclusive write access (e.g. Windows) may fail to update # the file from the external editor, see # https://github.com/The-Compiler/qutebrowser/issues/1767 with tempfile.NamedTemporaryFile( mode='w', prefix='qutebrowser-editor-', encoding=encoding, delete=False) as fobj: if text: fobj.write(text) self._file = fobj except OSError as e: message.error("Failed to create initial file: {}".format(e)) return 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') executable = editor[0] args = [arg.replace('{}', self._file.name) for arg in editor[1:]] log.procs.debug("Calling \"{}\" with args {}".format(executable, args)) self._proc.start(executable, args)
def _draw_textdoc(self, rect): """Draw the QTextDocument of an item. Args: rect: The QRect to clip the drawing to. """ # We can't use drawContents because then the color would be ignored. # See: https://qt-project.org/forums/viewthread/21492 clip = QRectF(0, 0, rect.width(), rect.height()) self._painter.save() if self._opt.state & QStyle.State_Selected: option = 'completion.item.selected.fg' elif not self._opt.state & QStyle.State_Enabled: option = 'completion.category.fg' else: option = 'completion.fg' try: self._painter.setPen(config.get('colors', option)) except configexc.NoOptionError: self._painter.setPen(config.get('colors', 'completion.fg')) ctx = QAbstractTextDocumentLayout.PaintContext() ctx.palette.setColor(QPalette.Text, self._painter.pen().color()) if clip.isValid(): self._painter.setClipRect(clip) ctx.clip = clip self._doc.documentLayout().draw(self._painter, ctx) self._painter.restore()
def resize_completion(self): """Adjust completion according to config.""" if not self._completion.isVisible(): # It doesn't make sense to resize the completion as long as it's # not shown anyways. return # Get the configured height/percentage. confheight = str(config.get('completion', 'height')) if confheight.endswith('%'): perc = int(confheight.rstrip('%')) height = self.height() * perc / 100 else: height = int(confheight) # Shrink to content size if needed and shrinking is enabled if config.get('completion', 'shrink'): contents_height = ( self._completion.viewportSizeHint().height() + self._completion.horizontalScrollBar().sizeHint().height()) if contents_height <= height: height = contents_height else: contents_height = -1 rect = self._get_overlay_position(height) log.misc.debug('completion rect: {}'.format(rect)) if rect.isValid(): self._completion.setGeometry(rect)
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') 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'), } first_tab_url = self.widget(0).url() last_close_urlstr = urls[last_close].toString().rstrip('/') first_tab_urlstr = first_tab_url.toString().rstrip('/') last_close_url_used = first_tab_urlstr == last_close_urlstr use_current_tab = (only_one_tab_open and no_history and last_close_url_used) url, history_data, idx = self._undo_stack.pop() if use_current_tab: self.openurl(url, newtab=False) newtab = self.widget(0) else: newtab = self.tabopen(url, background=False, idx=idx) newtab.history.deserialize(history_data)
def init(): """Initialize the global QWebSettings.""" cache_path = standarddir.cache() data_path = standarddir.data() if config.get('general', 'private-browsing') or cache_path is None: QWebSettings.setIconDatabasePath('') else: QWebSettings.setIconDatabasePath(cache_path) if cache_path is not None: QWebSettings.setOfflineWebApplicationCachePath( os.path.join(cache_path, 'application-cache')) if data_path is not None: QWebSettings.globalSettings().setLocalStoragePath( os.path.join(data_path, 'local-storage')) QWebSettings.setOfflineStoragePath( os.path.join(data_path, 'offline-storage')) for sectname, section in MAPPINGS.items(): for optname, mapping in section.items(): default = mapping.save_default() log.config.vdebug("Saved default for {} -> {}: {!r}".format( sectname, optname, default)) value = config.get(sectname, optname) log.config.vdebug("Setting {} -> {} to {!r}".format( sectname, optname, value)) mapping.set(value) objreg.get('config').changed.connect(update_settings)
def resize_completion(self): """Adjust completion according to config.""" # Get the configured height/percentage. confheight = str(config.get('completion', 'height')) if confheight.endswith('%'): perc = int(confheight.rstrip('%')) height = self.height() * perc / 100 else: height = int(confheight) # Shrink to content size if needed and shrinking is enabled if config.get('completion', 'shrink'): contents_height = ( self._completion.viewportSizeHint().height() + self._completion.horizontalScrollBar().sizeHint().height()) if contents_height <= height: height = contents_height else: contents_height = -1 # hpoint now would be the bottom-left edge of the widget if it was on # the top of the main window. topleft_y = self.height() - self.status.height() - height topleft_y = qtutils.check_overflow(topleft_y, 'int', fatal=False) topleft = QPoint(0, topleft_y) bottomright = self.status.geometry().topRight() rect = QRect(topleft, bottomright) if rect.isValid(): self._completion.setGeometry(rect)
def _tab_layout(self, opt): """Compute the text/icon rect from the opt rect. This is based on Qt's QCommonStylePrivate::tabLayout (qtbase/src/widgets/styles/qcommonstyle.cpp) as we can't use the private implementation. Args: opt: QStyleOptionTab Return: A (text_rect, icon_rect) tuple (both QRects). """ padding = self.pixelMetric(PM_TabBarPadding, opt) icon_rect = QRect() text_rect = QRect(opt.rect) qtutils.ensure_valid(text_rect) indicator_width = config.get('tabs', 'indicator-width') text_rect.adjust(padding, 0, 0, 0) if indicator_width != 0: text_rect.adjust(indicator_width + config.get('tabs', 'indicator-space'), 0, 0, 0) if not opt.icon.isNull(): icon_rect = self._get_icon_rect(opt, text_rect) text_rect.adjust(icon_rect.width() + padding, 0, 0, 0) text_rect = self._style.visualRect(opt.direction, opt.rect, text_rect) return (text_rect, icon_rect)
def on_unsupported_content(self, reply): """Handle an unsupportedContent signal. Most likely this will mean we need to download the reply, but we correct for some common errors the server do. At some point we might want to implement the MIME Sniffing standard here: http://mimesniff.spec.whatwg.org/ """ inline, suggested_filename = http.parse_content_disposition(reply) download_manager = objreg.get('qtnetwork-download-manager', scope='window', window=self._win_id) if not inline: # Content-Disposition: attachment -> force download download_manager.fetch(reply, suggested_filename=suggested_filename) return mimetype, _rest = http.parse_content_type(reply) if mimetype == 'image/jpg': # Some servers (e.g. the LinkedIn CDN) send a non-standard # image/jpg (instead of image/jpeg, defined in RFC 1341 section # 7.5). If this is the case, we force displaying with a corrected # mimetype. if reply.isFinished(): self.display_content(reply, 'image/jpeg') else: 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')): # Use pdf.js to display the page self._show_pdfjs(reply) else: # Unknown mimetype, so download anyways. download_manager.fetch(reply, suggested_filename=suggested_filename)
def set_colors(self): """Set the tabbar colors.""" p = self.palette() p.setColor(QPalette.Window, config.get('colors', 'tabs.bg.bar')) self.setPalette(p)
def get(self, settings=None): return config.get('content', 'cookies-accept')
def set_hbox_padding(self): padding = config.get('ui', 'statusbar-padding') self._hbox.setContentsMargins(padding.left, 0, padding.right, 0)
def set_enabled(self): """Update self.enabled when the config changed.""" self.enabled = config.get('completion', 'show')
def _set_bg_color(self): col = config.get('colors', 'webpage.bg') if col is None: col = self._theme_color self.setBackgroundColor(col)
def _init_modules(args, crash_handler): """Initialize all 'modules' which need to be initialized. Args: args: The argparse namespace. crash_handler: The CrashHandler instance. """ # pylint: disable=too-many-statements log.init.debug("Initializing save manager...") save_manager = savemanager.SaveManager(qApp) objreg.register('save-manager', save_manager) save_manager.add_saveable('version', _save_version) log.init.debug("Initializing network...") networkmanager.init() log.init.debug("Initializing readline-bridge...") readline_bridge = readline.ReadlineBridge() objreg.register('readline-bridge', readline_bridge) log.init.debug("Initializing directories...") standarddir.init(args) log.init.debug("Initializing config...") config.init(qApp) save_manager.init_autosave() log.init.debug("Initializing web history...") history.init(qApp) log.init.debug("Initializing crashlog...") if not args.no_err_windows: crash_handler.handle_segfault() log.init.debug("Initializing sessions...") sessions.init(qApp) log.init.debug("Initializing js-bridge...") js_bridge = qutescheme.JSBridge(qApp) objreg.register('js-bridge', js_bridge) log.init.debug("Initializing websettings...") websettings.init() log.init.debug("Initializing adblock...") host_blocker = adblock.HostBlocker() host_blocker.read_hosts() objreg.register('host-blocker', host_blocker) log.init.debug("Initializing quickmarks...") quickmark_manager = urlmarks.QuickmarkManager(qApp) objreg.register('quickmark-manager', quickmark_manager) log.init.debug("Initializing bookmarks...") bookmark_manager = urlmarks.BookmarkManager(qApp) objreg.register('bookmark-manager', bookmark_manager) log.init.debug("Initializing proxy...") proxy.init() log.init.debug("Initializing cookies...") cookie_jar = cookies.CookieJar(qApp) objreg.register('cookie-jar', cookie_jar) log.init.debug("Initializing cache...") diskcache = cache.DiskCache(standarddir.cache(), parent=qApp) objreg.register('cache', diskcache) log.init.debug("Initializing completions...") completionmodels.init() log.init.debug("Misc initialization...") if config.get('ui', 'hide-wayland-decoration'): os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1' else: os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None) _maybe_hide_mouse_cursor() objreg.get('config').changed.connect(_maybe_hide_mouse_cursor)
def tabSizeHint(self, index): """Override tabSizeHint so all tabs are the same size. https://wiki.python.org/moin/PyQt/Customising%20tab%20bars Args: index: The index of the tab. Return: A QSize. """ minimum_size = self.minimumTabSizeHint(index) height = minimum_size.height() if self.vertical: confwidth = str(config.get('tabs', 'width')) if confwidth.endswith('%'): main_window = objreg.get('main-window', scope='window', window=self._win_id) perc = int(confwidth.rstrip('%')) width = main_window.width() * perc / 100 else: width = int(confwidth) size = QSize(max(minimum_size.width(), width), height) elif self.count() == 0: # This happens on startup on OS X. # We return it directly rather than setting `size' because we don't # want to ensure it's valid in this special case. return QSize() elif self.count() * minimum_size.width() > self.width(): # If we don't have enough space, we return the minimum size so we # get scroll buttons as soon as needed. size = minimum_size else: tab_width_pinned_conf = config.get('tabs', 'pinned-width') try: pinned = self.tab_data(index, 'pinned') except KeyError: pinned = False no_pinned_count = self.count() - self.pinned_count pinned_width = tab_width_pinned_conf * self.pinned_count no_pinned_width = self.width() - pinned_width if pinned: width = tab_width_pinned_conf else: # If we *do* have enough space, tabs should occupy the whole # window width. If there are pinned tabs their size will be # subtracted from the total window width. # During shutdown the self.count goes down, # but the self.pinned_count not - this generates some odd # behavior. To avoid this we compare self.count against # self.pinned_count. if self.pinned_count > 0 and no_pinned_count > 0: width = no_pinned_width / no_pinned_count else: width = self.width() / self.count() # If no_pinned_width is not divisible by no_pinned_count, add a # pixel to some tabs so that there is no ugly leftover space. if (no_pinned_count > 0 and index < no_pinned_width % no_pinned_count): width += 1 size = QSize(width, height) qtutils.ensure_valid(size) return size
def _set_clear_timer_interval(self): """Configure self._clear_timer according to the config.""" self._clear_timer.setInterval(config.get('ui', 'message-timeout'))
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'))
def set_icon_size(self): """Set the tab bar favicon size.""" size = self.fontMetrics().height() - 2 size *= config.get('tabs', 'favicon-scale') self.setIconSize(QSize(size, size))
def _shutdown(self, status): # noqa """Second stage of shutdown.""" # pylint: disable=too-many-branches, too-many-statements # FIXME refactor this # https://github.com/The-Compiler/qutebrowser/issues/113 log.destroy.debug("Stage 2 of shutting down...") # Remove eventfilter try: log.destroy.debug("Removing eventfilter...") self.removeEventFilter(self._event_filter) except AttributeError: pass # Close all windows QApplication.closeAllWindows() # Shut down IPC try: objreg.get('ipc-server').shutdown() except KeyError: pass # Save everything try: config_obj = objreg.get('config') except KeyError: log.destroy.debug("Config not initialized yet, so not saving " "anything.") else: to_save = [] if config.get('general', 'auto-save-config'): to_save.append(("config", config_obj.save)) try: key_config = objreg.get('key-config') except KeyError: pass else: to_save.append(("keyconfig", key_config.save)) to_save += [("window geometry", self._save_geometry)] try: command_history = objreg.get('command-history') except KeyError: pass else: to_save.append(("command history", command_history.save)) try: quickmark_manager = objreg.get('quickmark-manager') except KeyError: pass else: to_save.append(("command history", quickmark_manager.save)) try: state_config = objreg.get('state-config') except KeyError: pass else: to_save.append(("window geometry", state_config.save)) try: cookie_jar = objreg.get('cookie-jar') except KeyError: pass else: to_save.append(("cookies", cookie_jar.save)) for what, handler in to_save: log.destroy.debug("Saving {} (handler: {})".format( what, utils.qualname(handler))) try: handler() except AttributeError as e: log.destroy.warning("Could not save {}.".format(what)) log.destroy.debug(e) # Re-enable faulthandler to stdout, then remove crash log log.destroy.debug("Deactiving crash log...") self._destroy_crashlogfile() # If we don't kill our custom handler here we might get segfaults log.destroy.debug("Deactiving message handler...") qInstallMessageHandler(None) # Now we can hopefully quit without segfaults log.destroy.debug("Deferring QApplication::exit...") # We use a singleshot timer to exit here to minimize the likelyhood of # segfaults. QTimer.singleShot(0, functools.partial(self.exit, status))
def _maybe_update_geometry(self): """Emit the update_geometry signal if the config says so.""" if config.get('completion', 'shrink'): self.update_geometry.emit()
def home(self): """Open main startpage in current tab.""" self.openurl(config.get('general', 'startpage')[0])
def set_forward_unbound_keys(self): """Update local setting when config changed.""" self._forward_unbound_keys = config.get('input', 'forward-unbound-keys')
def fetch(self, reply, *, fileobj=None, filename=None, auto_remove=False, suggested_filename=None, prompt_download_directory=None): """Download a QNetworkReply to disk. Args: reply: The QNetworkReply to download. fileobj: The file object to write the answer to. filename: A path to write the data to. auto_remove: Whether to remove the download even if ui -> remove-finished-downloads is set to -1. Return: The created DownloadItem. """ if fileobj is not None and filename is not None: raise TypeError("Only one of fileobj/filename may be given!") if not suggested_filename: if filename is not None: suggested_filename = os.path.basename(filename) elif fileobj is not None and getattr(fileobj, 'name', None): suggested_filename = fileobj.name else: _, suggested_filename = http.parse_content_disposition(reply) log.downloads.debug("fetch: {} -> {}".format(reply.url(), suggested_filename)) download = DownloadItem(reply, self._win_id, self) download.cancelled.connect( functools.partial(self.remove_item, download)) delay = config.get('ui', 'remove-finished-downloads') if delay > -1: download.finished.connect( functools.partial(self.remove_item_delayed, download, delay)) elif auto_remove: download.finished.connect( functools.partial(self.remove_item, download)) download.data_changed.connect( functools.partial(self.on_data_changed, download)) download.error.connect(self.on_error) download.redirected.connect( functools.partial(self.on_redirect, download)) download.basename = suggested_filename idx = len(self.downloads) + 1 download.index = idx self.beginInsertRows(QModelIndex(), idx, idx) self.downloads.append(download) self.endInsertRows() if not self._update_timer.isActive(): self._update_timer.start() if fileobj is not None: download.set_fileobj(fileobj) download.autoclose = False return download if filename is not None: download.set_filename(filename) return download # Neither filename nor fileobj were given, prepare a question filename, q = ask_for_filename( suggested_filename, self._win_id, parent=self, prompt_download_directory=prompt_download_directory, ) # User doesn't want to be asked, so just use the download_dir if filename is not None: download.set_filename(filename) return download # Ask the user for a filename self._postprocess_question(q) q.answered.connect(download.set_filename) q.cancelled.connect(download.cancel) download.cancelled.connect(q.abort) download.error.connect(q.abort) q.ask() return download
def set_pop_timer_interval(self): """Update message timeout when config changed.""" self._text_pop_timer.setInterval(config.get('ui', 'message-timeout'))
def _handle_context_menu(self, _e): """Suppress context menus if rocker gestures are turned on.""" return config.get('input', 'rocker-gestures')
def fire(self, keystr, force=False): """Fire a completed hint. Args: keystr: The keychain string to follow. force: When True, follow even when auto-follow is false. """ if not (force or config.get('hints', 'auto-follow')): self.handle_partial_key(keystr) self._context.to_follow = keystr return # Handlers which take a QWebElement elem_handlers = { Target.normal: self._click, Target.tab: self._click, Target.tab_bg: self._click, Target.window: self._click, Target.rapid: self._click, Target.rapid_win: self._click, Target.hover: self._click, # _download needs a QWebElement to get the frame. Target.download: self._download, } # Handlers which take a QUrl url_handlers = { Target.yank: self._yank, Target.yank_primary: self._yank, Target.run: self._run_cmd, Target.fill: self._preset_cmd_text, Target.userscript: self._call_userscript, Target.spawn: self._spawn, } elem = self._context.elems[keystr].elem if self._context.target in elem_handlers: handler = functools.partial(elem_handlers[self._context.target], elem, self._context) elif self._context.target in url_handlers: url = self._resolve_url(elem, self._context.baseurl) if url is None: message.error(self._win_id, "No suitable link found for this element.", immediately=True) return handler = functools.partial(url_handlers[self._context.target], url, self._context) else: raise ValueError("No suitable handler found!") if self._context.target not in (Target.rapid, Target.rapid_win): modeman.maybe_leave(self._win_id, usertypes.KeyMode.hint, 'followed') else: # Show all hints again self.filter_hints(None) # Undo keystring highlighting for (string, elems) in self._context.elems.items(): elems.label.setInnerXml(string) handler()
def start(self, rapid=False, group=webelem.Group.all, target=Target.normal, *args: {'nargs': '*'}, win_id): """Start hinting. Args: rapid: Whether to do rapid hinting. This is only possible with targets `tab` (with background-tabs=true), `tab-bg`, `window`, `run`, `hover`, `userscript` and `spawn`. group: The hinting mode to use. - `all`: All clickable elements. - `links`: Only links. - `images`: Only images. target: What to do with the selected element. - `normal`: Open the link in the current tab. - `tab`: Open the link in a new tab (honoring the background-tabs setting). - `tab-fg`: Open the link in a new foreground tab. - `tab-bg`: Open the link in a new background tab. - `window`: Open the link in a new window. - `hover` : Hover over the link. - `yank`: Yank the link to the clipboard. - `yank-primary`: Yank the link to the primary selection. - `run`: Run the argument as command. - `fill`: Fill the commandline with the command given as argument. - `download`: Download the link. - `userscript`: Call a userscript with `$QUTE_URL` set to the link. - `spawn`: Spawn a command. *args: Arguments for spawn/userscript/run/fill. - With `spawn`: The executable and arguments to spawn. `{hint-url}` will get replaced by the selected URL. - With `userscript`: The userscript to execute. Either store the userscript in `~/.local/share/qutebrowser/userscripts` (or `$XDG_DATA_DIR`), or use an absolute path. - With `fill`: The command to fill the statusbar with. `{hint-url}` will get replaced by the selected URL. - With `run`: Same as `fill`. """ tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) widget = tabbed_browser.currentWidget() if widget is None: raise cmdexc.CommandError("No WebView available yet!") mainframe = widget.page().mainFrame() if mainframe is None: raise cmdexc.CommandError("No frame focused!") mode_manager = objreg.get('mode-manager', scope='window', window=self._win_id) if mode_manager.mode == usertypes.KeyMode.hint: modeman.leave(win_id, usertypes.KeyMode.hint, 're-hinting') if rapid: if target in [ Target.tab_bg, Target.window, Target.run, Target.hover, Target.userscript, Target.spawn, Target.download ]: pass elif (target == Target.tab and config.get('tabs', 'background-tabs')): pass else: name = target.name.replace('_', '-') raise cmdexc.CommandError("Rapid hinting makes no sense with " "target {}!".format(name)) self._check_args(target, *args) self._context = HintContext() self._context.target = target self._context.rapid = rapid try: self._context.baseurl = tabbed_browser.current_url() except qtutils.QtValueError: raise cmdexc.CommandError("No URL set for this page yet!") self._context.frames = webelem.get_child_frames(mainframe) for frame in self._context.frames: # WORKAROUND for # https://github.com/The-Compiler/qutebrowser/issues/152 frame.destroyed.connect( functools.partial(self._context.destroyed_frames.append, id(frame))) self._context.args = args self._context.mainframe = mainframe self._context.group = group self._init_elements() message_bridge = objreg.get('message-bridge', scope='window', window=self._win_id) message_bridge.set_text(self._get_text()) self._connect_frame_signals() modeman.enter(self._win_id, usertypes.KeyMode.hint, 'HintManager.start')
def init_neighborlist(self): """Initialize the _zoom neighborlist.""" levels = config.get('ui', 'zoom-levels') self._zoom = usertypes.NeighborList( levels, mode=usertypes.NeighborList.Modes.block) self._zoom.fuzzyval = config.get('ui', 'default-zoom')
def get(self, settings=None): utils.unused(settings) return config.get('content', 'cookies-store')
def tabopen(self, url=None, background=None, explicit=False, idx=None, *, ignore_tabs_are_windows=False): """Open a new tab with a given URL. Inner logic for open-tab and open-tab-bg. Also connect all the signals we need to _filter_signals. Args: url: The URL to open as QUrl or None for an empty tab. background: Whether to open the tab in the background. if None, the background-tabs setting decides. explicit: Whether the tab was opened explicitly. If this is set, the new position might be different. With the default settings we handle it like Chromium does: - Tabs from clicked links etc. are to the right of the current. - Explicitly opened tabs are at the very right. idx: The index where the new tab should be opened. ignore_tabs_are_windows: If given, never open a new window, even with tabs-are-windows set. Return: The opened WebView instance. """ if url is not None: qtutils.ensure_valid(url) log.webview.debug("Creating new tab with URL {}, background {}, " "explicit {}, idx {}".format(url, background, explicit, idx)) if (config.get('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) window.show() tabbed_browser = objreg.get('tabbed-browser', scope='window', window=window.win_id) return tabbed_browser.tabopen(url, background, explicit) tab = browsertab.create(win_id=self._win_id, private=self.private, parent=self) self._connect_tab_signals(tab) if idx is None: idx = self._get_new_tab_idx(explicit) self.insertTab(idx, tab, "") if url is not None: tab.openurl(url) if background is None: background = config.get('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 # layout anyways. if self.tabBar().vertical: tab_size = QSize(self.width() - self.tabBar().width(), self.height()) else: tab_size = QSize(self.width(), self.height() - self.tabBar().height()) tab.resize(tab_size) self.tab_index_changed.emit(self.currentIndex(), self.count()) else: self.setCurrentWidget(tab) tab.show() self.new_tab.emit(tab, idx) return tab
def start(self, rapid=False, group=webelem.Group.all, target=Target.normal, *args, win_id, mode=None, add_history=False): """Start hinting. Args: rapid: Whether to do rapid hinting. This is only possible with targets `tab` (with background-tabs=true), `tab-bg`, `window`, `run`, `hover`, `userscript` and `spawn`. add_history: Whether to add the spawned or yanked link to the browsing history. group: The element types to hint. - `all`: All clickable elements. - `links`: Only links. - `images`: Only images. - `inputs`: Only input fields. target: What to do with the selected element. - `normal`: Open the link. - `current`: Open the link in the current tab. - `tab`: Open the link in a new tab (honoring the background-tabs setting). - `tab-fg`: Open the link in a new foreground tab. - `tab-bg`: Open the link in a new background tab. - `window`: Open the link in a new window. - `hover` : Hover over the link. - `yank`: Yank the link to the clipboard. - `yank-primary`: Yank the link to the primary selection. - `run`: Run the argument as command. - `fill`: Fill the commandline with the command given as argument. - `download`: Download the link. - `userscript`: Call a userscript with `$QUTE_URL` set to the link. - `spawn`: Spawn a command. mode: The hinting mode to use. - `number`: Use numeric hints. - `letter`: Use the chars in the hints->chars settings. - `word`: Use hint words based on the html elements and the extra words. *args: Arguments for spawn/userscript/run/fill. - With `spawn`: The executable and arguments to spawn. `{hint-url}` will get replaced by the selected URL. - With `userscript`: The userscript to execute. Either store the userscript in `~/.local/share/qutebrowser/userscripts` (or `$XDG_DATA_DIR`), or use an absolute path. - With `fill`: The command to fill the statusbar with. `{hint-url}` will get replaced by the selected URL. - With `run`: Same as `fill`. """ tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) tab = tabbed_browser.currentWidget() if tab is None: raise cmdexc.CommandError("No WebView available yet!") mode_manager = objreg.get('mode-manager', scope='window', window=self._win_id) if mode_manager.mode == usertypes.KeyMode.hint: modeman.leave(win_id, usertypes.KeyMode.hint, 're-hinting') if rapid: if target in [ Target.tab_bg, Target.window, Target.run, Target.hover, Target.userscript, Target.spawn, Target.download, Target.normal, Target.current ]: pass elif (target == Target.tab and config.get('tabs', 'background-tabs')): pass else: name = target.name.replace('_', '-') raise cmdexc.CommandError("Rapid hinting makes no sense with " "target {}!".format(name)) if mode is None: mode = config.get('hints', 'mode') self._check_args(target, *args) self._context = HintContext() self._context.tab = tab self._context.target = target self._context.rapid = rapid self._context.hint_mode = mode self._context.add_history = add_history try: self._context.baseurl = tabbed_browser.current_url() except qtutils.QtValueError: raise cmdexc.CommandError("No URL set for this page yet!") self._context.args = args self._context.group = group selector = webelem.SELECTORS[self._context.group] self._context.tab.elements.find_css(selector, self._start_cb, only_visible=True)
def maybe_resize_completion(self): """Emit the resize_completion signal if the config says so.""" if config.get('completion', 'shrink'): self.resize_completion.emit()
def minimumSizeHint(self): """Set the minimum height to the text height plus some padding.""" padding = config.get('ui', 'statusbar-padding') width = super().minimumSizeHint().width() height = self.fontMetrics().height() + padding.top + padding.bottom return QSize(width, height)
def set_font(self): """Set the tabbar font.""" self.setFont(config.get('fonts', 'tabbar'))
def _init_modules(args, crash_handler): """Initialize all 'modules' which need to be initialized. Args: args: The argparse namespace. crash_handler: The CrashHandler instance. """ # pylint: disable=too-many-statements log.init.debug("Initializing prompts...") prompt.init() log.init.debug("Initializing save manager...") save_manager = savemanager.SaveManager(qApp) objreg.register('save-manager', save_manager) save_manager.add_saveable('version', _save_version) log.init.debug("Initializing network...") networkmanager.init() if qtutils.version_check('5.8'): # Otherwise we can only initialize it for QtWebKit because of crashes log.init.debug("Initializing proxy...") proxy.init() log.init.debug("Initializing readline-bridge...") readline_bridge = readline.ReadlineBridge() objreg.register('readline-bridge', readline_bridge) log.init.debug("Initializing config...") config.init(qApp) save_manager.init_autosave() log.init.debug("Initializing web history...") history.init(qApp) log.init.debug("Initializing crashlog...") if not args.no_err_windows: crash_handler.handle_segfault() log.init.debug("Initializing sessions...") sessions.init(qApp) log.init.debug("Initializing websettings...") websettings.init(args) log.init.debug("Initializing adblock...") host_blocker = adblock.HostBlocker() host_blocker.read_hosts() objreg.register('host-blocker', host_blocker) log.init.debug("Initializing quickmarks...") quickmark_manager = urlmarks.QuickmarkManager(qApp) objreg.register('quickmark-manager', quickmark_manager) log.init.debug("Initializing bookmarks...") bookmark_manager = urlmarks.BookmarkManager(qApp) objreg.register('bookmark-manager', bookmark_manager) log.init.debug("Initializing cookies...") cookie_jar = cookies.CookieJar(qApp) ram_cookie_jar = cookies.RAMCookieJar(qApp) objreg.register('cookie-jar', cookie_jar) objreg.register('ram-cookie-jar', ram_cookie_jar) log.init.debug("Initializing cache...") diskcache = cache.DiskCache(standarddir.cache(), parent=qApp) objreg.register('cache', diskcache) log.init.debug("Initializing completions...") completionmodels.init() log.init.debug("Misc initialization...") if config.get('ui', 'hide-wayland-decoration'): os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1' else: os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None) macros.init() # Init backend-specific stuff browsertab.init()
def on_change(self): """Show tab bar when current tab got changed.""" show = config.get('tabs', 'show') if show == 'switching': self.show() self._auto_hide_timer.start()
def set_font(self): """Set the tab bar font.""" self.setFont(config.get('fonts', 'tabbar')) size = self.fontMetrics().height() - 2 self.setIconSize(QSize(size, size))