def contextMenuEvent(self, e): """Save a reference to the context menu so we can close it. This is not needed for QtWebEngine, so it's in here. """ menu = self.page().createStandardContextMenu() self.shutting_down.connect(menu.close) modeman.instance(self.win_id).entered.connect(menu.close) menu.exec_(e.globalPos())
def _handle_wheel(self, e): """Zoom on Ctrl-Mousewheel. Args: e: The QWheelEvent. """ if self._ignore_wheel_event: # See https://github.com/qutebrowser/qutebrowser/issues/395 self._ignore_wheel_event = False return True if e.modifiers() & Qt.ControlModifier: mode = modeman.instance(self._tab.win_id).mode if mode == usertypes.KeyMode.passthrough: return False divider = config.val.zoom.mouse_divider if divider == 0: return False factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider) if factor < 0: return False perc = int(100 * factor) message.info("Zoom level: {}%".format(perc), replace=True) self._tab.zoom.set_factor(factor) elif e.modifiers() & Qt.ShiftModifier: if e.angleDelta().y() > 0: self._tab.scroller.left() else: self._tab.scroller.right() return True return False
def eventFilter(self, _obj, event): """Act on ChildAdded events.""" if event.type() != QEvent.ChildAdded: return False pass_modes = [ usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno ] if modeman.instance(self._win_id).mode in pass_modes: return False tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) current_index = tabbed_browser.widget.currentIndex() try: widget_index = tabbed_browser.widget.indexOf(self._widget.parent()) except RuntimeError: widget_index = -1 if current_index == widget_index: QTimer.singleShot(0, self._widget.setFocus) return False
def eventFilter(self, obj, event): """Act on ChildAdded events.""" if event.type() == QEvent.ChildAdded: child = event.child() log.misc.debug("{} got new child {}, installing filter".format( obj, child)) assert obj is self._widget child.installEventFilter(self._filter) if qtutils.version_check('5.11', compiled=False, exact=True): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076 pass_modes = [ usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno ] if modeman.instance(self._win_id).mode not in pass_modes: tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) current_index = tabbed_browser.widget.currentIndex() try: widget_index = tabbed_browser.widget.indexOf( self._widget.parent()) except RuntimeError: widget_index = -1 if current_index == widget_index: QTimer.singleShot(0, self._widget.setFocus) elif event.type() == QEvent.ChildRemoved: child = event.child() log.misc.debug("{}: removed child {}".format(obj, child)) return False
def create(win_id: int, private: bool, parent: QWidget = None) -> 'AbstractTab': """Get a QtWebKit/QtWebEngine tab object. Args: win_id: The window ID where the tab will be shown. private: Whether the tab is a private/off the record tab. parent: The Qt parent to set. """ # Importing modules here so we don't depend on QtWebEngine without the # argument and to avoid circular imports. mode_manager = modeman.instance(win_id) if objects.backend == usertypes.Backend.QtWebEngine: from qutebrowser.browser.webengine import webenginetab tab_class: Type[AbstractTab] = webenginetab.WebEngineTab elif objects.backend == usertypes.Backend.QtWebKit: from qutebrowser.browser.webkit import webkittab tab_class = webkittab.WebKitTab else: raise utils.Unreachable(objects.backend) return tab_class(win_id=win_id, mode_manager=mode_manager, private=private, parent=parent)
def _do_focus_workaround(self): """WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076.""" if not self._focus_workaround: return assert self._widget is not None pass_modes = [ usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno ] if modeman.instance(self._win_id).mode in pass_modes: return tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) current_index = tabbed_browser.widget.currentIndex() try: widget_index = tabbed_browser.widget.indexOf(self._widget.parent()) except RuntimeError: widget_index = -1 if current_index == widget_index: QTimer.singleShot(0, self._widget.setFocus)
def eventFilter(self, obj, event): """Act on ChildAdded events.""" if event.type() == QEvent.ChildAdded: child = event.child() log.mouse.debug("{} got new child {}, installing filter".format( obj, child)) assert obj is self._widget child.installEventFilter(self._filter) if qtutils.version_check('5.11', compiled=False, exact=True): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076 pass_modes = [usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno] if modeman.instance(self._win_id).mode not in pass_modes: tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) current_index = tabbed_browser.widget.currentIndex() try: widget_index = tabbed_browser.widget.indexOf( self._widget.parent()) except RuntimeError: widget_index = -1 if current_index == widget_index: QTimer.singleShot(0, self._widget.setFocus) elif event.type() == QEvent.ChildRemoved: child = event.child() log.mouse.debug("{}: removed child {}".format(obj, child)) return False
def __init__(self, win_id: int, parent: QObject = None) -> None: """Constructor.""" super().__init__(parent) self._win_id = win_id self._context: Optional[HintContext] = None self._word_hinter = WordHinter() self._actions = HintActions(win_id) mode_manager = modeman.instance(self._win_id) mode_manager.left.connect(self.on_mode_left)
def on_mode_entered(self, mode): """Mark certain modes in the commandline.""" mode_manager = modeman.instance(self._win_id) if mode_manager.parsers[mode].passthrough: self._set_mode_text(mode.name) if mode in [ usertypes.KeyMode.insert, usertypes.KeyMode.command, usertypes.KeyMode.caret, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno, usertypes.KeyMode.passthrough ]: self.set_mode_active(mode, True)
def repeat_command(win_id: int, count: int = None) -> None: """Repeat the last executed command. Args: count: Which count to pass the command. """ mode_manager = modeman.instance(win_id) if mode_manager.mode not in runners.last_command: raise cmdutils.CommandError("You didn't do anything yet.") cmd = runners.last_command[mode_manager.mode] commandrunner = runners.CommandRunner(win_id) commandrunner.run(cmd[0], count if count is not None else cmd[1])
def run_macro_command(self, win_id, count=1, register=None): """Run a recorded macro. Args: count: How many times to run the macro. register: Which macro to run. """ self._macro_count[win_id] = count if register is None: mode_manager = modeman.instance(win_id) mode_manager.enter(usertypes.KeyMode.run_macro, 'run_macro') else: self.run_macro(win_id, register)
def macro_run(self, win_id: int, count: int = 1, register: str = None) -> None: """Run a recorded macro. Args: count: How many times to run the macro. register: Which macro to run. """ self._macro_count[win_id] = count if register is None: mode_manager = modeman.instance(win_id) mode_manager.enter(usertypes.KeyMode.run_macro, 'run_macro') else: self.run_macro(win_id, register)
def on_mode_left(self, old_mode, new_mode): """Clear marked mode.""" mode_manager = modeman.instance(self._win_id) if mode_manager.parsers[old_mode].passthrough: if mode_manager.parsers[new_mode].passthrough: self._set_mode_text(new_mode.name) else: self.txt.set_text(self.txt.Text.normal, '') if old_mode in [ usertypes.KeyMode.insert, usertypes.KeyMode.command, usertypes.KeyMode.caret, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno, usertypes.KeyMode.passthrough ]: self.set_mode_active(old_mode, False)
def on_mode_left(self, old_mode, new_mode): """Clear marked mode.""" mode_manager = modeman.instance(self._win_id) if config.val.statusbar.show == 'in-mode': self.hide() if mode_manager.parsers[old_mode].passthrough: if mode_manager.parsers[new_mode].passthrough: self._set_mode_text(new_mode.name) else: self.txt.setText('') if old_mode in [ usertypes.KeyMode.insert, usertypes.KeyMode.command, usertypes.KeyMode.caret, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno, usertypes.KeyMode.passthrough ]: self.set_mode_active(old_mode, False)
def record_macro_command(self, win_id, register=None): """Start or stop recording a macro. Args: register: Which register to store the macro in. """ if self._recording_macro is None: if register is None: mode_manager = modeman.instance(win_id) mode_manager.enter(usertypes.KeyMode.record_macro, 'record_macro') else: self.record_macro(register) else: message.info("Macro '{}' recorded.".format(self._recording_macro)) self._recording_macro = None
def macro_record(self, win_id: int, register: str = None) -> None: """Start or stop recording a macro. Args: register: Which register to store the macro in. """ if self._recording_macro is None: if register is None: mode_manager = modeman.instance(win_id) mode_manager.enter(usertypes.KeyMode.record_macro, 'record_macro') else: self.record_macro(register) else: message.info("Macro '{}' recorded.".format(self._recording_macro)) self._recording_macro = None
def create(win_id, parent=None): """Get a QtWebKit/QtWebEngine tab object. Args: win_id: The window ID where the tab will be shown. parent: The Qt parent to set. """ # Importing modules here so we don't depend on QtWebEngine without the # argument and to avoid circular imports. mode_manager = modeman.instance(win_id) if objects.backend == usertypes.Backend.QtWebEngine: from qutebrowser.browser.webengine import webenginetab tab_class = webenginetab.WebEngineTab else: from qutebrowser.browser.webkit import webkittab tab_class = webkittab.WebKitTab return tab_class(win_id=win_id, mode_manager=mode_manager, parent=parent)
def _check_prerequisites(self, win_id): """Check if the command is permitted to run currently. Args: win_id: The window ID the command is run in. """ from qutebrowser.keyinput import modeman mode_manager = modeman.instance(win_id) self.validate_mode(mode_manager.mode) if self.backend is not None and objects.backend != self.backend: raise cmdexc.PrerequisitesError("{}: Only available with {} " "backend.".format( self.name, self.backend.name)) if self.deprecated: message.warning(f'{self.name} is deprecated - {self.deprecated}')
def create(win_id, parent=None): """Get a QtWebKit/QtWebEngine tab object. Args: win_id: The window ID where the tab will be shown. parent: The Qt parent to set. """ # Importing modules here so we don't depend on QtWebEngine without the # argument and to avoid circular imports. mode_manager = modeman.instance(win_id) if objreg.get('args').backend == 'webengine': from qutebrowser.browser.webengine import webenginetab tab_class = webenginetab.WebEngineTab else: from qutebrowser.browser.webkit import webkittab tab_class = webkittab.WebKitTab return tab_class(win_id=win_id, mode_manager=mode_manager, parent=parent)
def _handle_wheel(self, e): """Zoom on Ctrl-Mousewheel. Args: e: The QWheelEvent. Return: True if the event should be filtered, False otherwise. """ if self._ignore_wheel_event: # See https://github.com/qutebrowser/qutebrowser/issues/395 self._ignore_wheel_event = False return True # Don't allow scrolling while hinting mode = modeman.instance(self._tab.win_id).mode if mode == usertypes.KeyMode.hint: return True elif e.modifiers() & Qt.ControlModifier: if mode == usertypes.KeyMode.passthrough: return False divider = config.val.zoom.mouse_divider if divider == 0: # Disable mouse zooming return True factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider) if factor < 0: return True perc = int(100 * factor) message.info("Zoom level: {}%".format(perc), replace=True) self._tab.zoom.set_factor(factor) return True elif (e.modifiers() & Qt.ShiftModifier and not qtutils.version_check('5.9', compiled=False)): if e.angleDelta().y() > 0: self._tab.scroller.left() else: self._tab.scroller.right() return True return False
def run(self, text, count=None, *, safely=False): """Parse a command from a line of text and run it. Args: text: The text to parse. count: The count to pass to the command. safely: Show CmdError exceptions as messages. """ record_last_command = True record_macro = True mode_manager = modeman.instance(self._win_id) cur_mode = mode_manager.mode parsed = None with self._handle_error(safely): parsed = self._parser.parse_all(text) if parsed is None: return # type: ignore[unreachable] for result in parsed: with self._handle_error(safely): if result.cmd.no_replace_variables: args = result.args else: args = replace_variables(self._win_id, result.args) result.cmd.run(self._win_id, args, count=count) if result.cmdline[0] == 'repeat-command': record_last_command = False if result.cmdline[0] in [ 'macro-record', 'macro-run', 'set-cmd-text' ]: record_macro = False if record_last_command: last_command[cur_mode] = (text, count) if record_macro and cur_mode == usertypes.KeyMode.normal: macros.macro_recorder.record_command(text, count)
def on_current_changed(self, idx): """Set last-focused-tab and leave hinting mode when focus changed.""" mode_on_change = config.val.tabs.mode_on_change if idx == -1 or self.shutting_down: # closing the last tab (before quitting) or shutting down return tab = self.widget.widget(idx) if tab is None: log.webview.debug("on_current_changed got called with invalid " "index {}".format(idx)) return log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] mm_instance = modeman.instance(self._win_id) current_mode = mm_instance.mode log.modes.debug( "Mode before tab change: {} (mode_on_change = {})".format( current_mode.name, mode_on_change)) if mode_on_change == 'normal': modes_to_leave += modeman.INPUT_MODES for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) if (mode_on_change == 'restore' and current_mode not in modeman.PROMPT_MODES): modeman.enter(self._win_id, tab.data.input_mode, 'restore') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) log.modes.debug( "Mode after tab change: {} (mode_on_change = {})".format( current_mode.name, mode_on_change)) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) self._tab_insert_idx_left = self.widget.currentIndex() self._tab_insert_idx_right = self.widget.currentIndex() + 1
def _handle_key_event(self, event: QKeyEvent) -> bool: """Handle a key press/release event. Args: event: The QEvent which is about to be delivered. Return: True if the event should be filtered, False if it's passed through. """ if q_app.activeWindow() not in objreg.window_registry.values(): # Some other window (print dialog, etc.) is focused so we pass the # event through. return False try: man = modeman.instance('current') return man.handle_event(event) except objreg.RegistryUnavailableError: # No window available yet, or not a MainWindow return False
def on_current_changed(self, idx): """Set last-focused-tab and leave hinting mode when focus changed.""" mode_on_change = config.val.tabs.mode_on_change modes_to_save = [ usertypes.KeyMode.insert, usertypes.KeyMode.passthrough ] if idx == -1 or self.shutting_down: # closing the last tab (before quitting) or shutting down return tab = self.widget(idx) if tab is None: log.webview.debug("on_current_changed got called with invalid " "index {}".format(idx)) return if self._now_focused is not None and mode_on_change == 'restore': current_mode = modeman.instance(self._win_id).mode if current_mode not in modes_to_save: current_mode = usertypes.KeyMode.normal self._now_focused.data.input_mode = current_mode log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] if mode_on_change != 'persist': modes_to_leave += modes_to_save for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) if mode_on_change == 'restore': modeman.enter(self._win_id, tab.data.input_mode, 'restore input mode for tab') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) self._tab_insert_idx_left = self.currentIndex() self._tab_insert_idx_right = self.currentIndex() + 1
def create(win_id: int, private: bool, parent: QWidget = None) -> 'AbstractTab': """Get a QtWebKit/QtWebEngine tab object. Args: win_id: The window ID where the tab will be shown. private: Whether the tab is a private/off the record tab. parent: The Qt parent to set. """ # Importing modules here so we don't depend on QtWebEngine without the # argument and to avoid circular imports. mode_manager = modeman.instance(win_id) if objects.backend == usertypes.Backend.QtWebEngine: from qutebrowser.browser.webengine import webenginetab tab_class = webenginetab.WebEngineTab else: from qutebrowser.browser.webkit import webkittab tab_class = webkittab.WebKitTab return tab_class(win_id=win_id, mode_manager=mode_manager, private=private, parent=parent)
def maybe_hide(self): """Hide the statusbar if it's configured to do so.""" strategy = config.val.statusbar.show tab = self._current_tab() if tab is not None and tab.data.fullscreen: self.hide() elif strategy == 'never': self.hide() elif strategy == 'in-mode': try: mode_manager = modeman.instance(self._win_id) except modeman.UnavailableError: self.hide() else: if mode_manager.mode == usertypes.KeyMode.normal: self.hide() else: self.show() elif strategy == 'always': self.show() else: raise utils.Unreachable
def _handle_wheel(self, e): """Zoom on Ctrl-Mousewheel. Args: e: The QWheelEvent. Return: True if the event should be filtered, False otherwise. """ if self._ignore_wheel_event: # See https://github.com/qutebrowser/qutebrowser/issues/395 self._ignore_wheel_event = False return True # Don't allow scrolling while hinting mode = modeman.instance(self._tab.win_id).mode if mode == usertypes.KeyMode.hint: return True elif e.modifiers() & Qt.ControlModifier: if mode == usertypes.KeyMode.passthrough: return False divider = config.val.zoom.mouse_divider if divider == 0: # Disable mouse zooming return True factor = self._tab.zoom.factor() + (e.angleDelta().y() / divider) if factor < 0: return True perc = int(100 * factor) message.info(f"Zoom level: {perc}%", replace='zoom-level') self._tab.zoom.set_factor(factor) return True return False
def on_current_changed(self, idx): """Set last-focused-tab and leave hinting mode when focus changed.""" mode_on_change = config.val.tabs.mode_on_change modes_to_save = [usertypes.KeyMode.insert, usertypes.KeyMode.passthrough] if idx == -1 or self.shutting_down: # closing the last tab (before quitting) or shutting down return tab = self.widget(idx) if tab is None: log.webview.debug("on_current_changed got called with invalid " "index {}".format(idx)) return if self._now_focused is not None and mode_on_change == 'restore': current_mode = modeman.instance(self._win_id).mode if current_mode not in modes_to_save: current_mode = usertypes.KeyMode.normal self._now_focused.data.input_mode = current_mode log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] if mode_on_change != 'persist': modes_to_leave += modes_to_save for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) if mode_on_change == 'restore': modeman.enter(self._win_id, tab.data.input_mode, 'restore input mode for tab') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) self._tab_insert_idx_left = self.currentIndex() self._tab_insert_idx_right = self.currentIndex() + 1
def on_current_changed(self, idx): """Set last-focused-tab and leave hinting mode when focus changed.""" mode_on_change = config.val.tabs.mode_on_change if idx == -1 or self.shutting_down: # closing the last tab (before quitting) or shutting down return tab = self.widget.widget(idx) if tab is None: log.webview.debug("on_current_changed got called with invalid " "index {}".format(idx)) return log.modes.debug("Current tab changed, focusing {!r}".format(tab)) tab.setFocus() modes_to_leave = [usertypes.KeyMode.hint, usertypes.KeyMode.caret] mm_instance = modeman.instance(self._win_id) current_mode = mm_instance.mode log.modes.debug("Mode before tab change: {} (mode_on_change = {})" .format(current_mode.name, mode_on_change)) if mode_on_change == 'normal': modes_to_leave += modeman.INPUT_MODES for mode in modes_to_leave: modeman.leave(self._win_id, mode, 'tab changed', maybe=True) if (mode_on_change == 'restore' and current_mode not in modeman.PROMPT_MODES): modeman.enter(self._win_id, tab.data.input_mode, 'restore') if self._now_focused is not None: objreg.register('last-focused-tab', self._now_focused, update=True, scope='window', window=self._win_id) log.modes.debug("Mode after tab change: {} (mode_on_change = {})" .format(current_mode.name, mode_on_change)) self._now_focused = tab self.current_tab_changed.emit(tab) QTimer.singleShot(0, self._update_window_title) self._tab_insert_idx_left = self.widget.currentIndex() self._tab_insert_idx_right = self.widget.currentIndex() + 1
def tabopen( self, url: QUrl = None, background: bool = None, related: bool = True, idx: int = None, ) -> browsertab.AbstractTab: """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 `tabs.background` setting decides. related: Whether the tab was opened from another existing tab. 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 (related=True). - Explicitly opened tabs are at the very right (related=False) idx: The index where the new tab should be opened. Return: The opened WebView instance. """ if url is not None: qtutils.ensure_valid(url) log.webview.debug("Creating new tab with URL {}, background {}, " "related {}, idx {}".format(url, background, related, idx)) prev_focus = QApplication.focusWidget() if config.val.tabs.tabs_are_windows and self.widget.count() > 0: window = mainwindow.MainWindow(private=self.is_private) window.show() tabbed_browser = objreg.get('tabbed-browser', scope='window', window=window.win_id) return tabbed_browser.tabopen(url=url, background=background, related=related) tab = browsertab.create(win_id=self._win_id, private=self.is_private, parent=self.widget) self._connect_tab_signals(tab) if idx is None: idx = self._get_new_tab_idx(related) self.widget.insertTab(idx, tab, "") if url is not None: tab.load_url(url) if background is None: background = config.val.tabs.background 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. tab.resize(self.widget.currentWidget().size()) self.widget.tab_index_changed.emit(self.widget.currentIndex(), self.widget.count()) # Refocus webview in case we lost it by spawning a bg tab self.widget.currentWidget().setFocus() else: self.widget.setCurrentWidget(tab) mode = modeman.instance(self._win_id).mode if mode in [ usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno ]: # If we were in a command prompt, restore old focus # The above commands need to be run to switch tabs if prev_focus is not None: prev_focus.setFocus() tab.show() self.new_tab.emit(tab, idx) return tab
def tabopen(self, url=None, background=None, related=True, 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 `tabs.background_tabs`` setting decides. related: Whether the tab was opened from another existing tab. 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 (related=True). - Explicitly opened tabs are at the very right (related=False) idx: The index where the new tab should be opened. ignore_tabs_are_windows: If given, never open a new window, even with tabs.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 {}, " "related {}, idx {}".format( url, background, related, idx)) prev_focus = QApplication.focusWidget() if (config.val.tabs.tabs_are_windows and self.widget.count() > 0 and not ignore_tabs_are_windows): 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=url, background=background, related=related) tab = browsertab.create(win_id=self._win_id, private=self.private, parent=self.widget) self._connect_tab_signals(tab) if idx is None: idx = self._get_new_tab_idx(related) self.widget.insertTab(idx, tab, "") if url is not None: tab.openurl(url) if background is None: background = config.val.tabs.background 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. tab.resize(self.widget.currentWidget().size()) self.widget.tab_index_changed.emit(self.widget.currentIndex(), self.widget.count()) # Refocus webview in case we lost it by spawning a bg tab self.widget.currentWidget().setFocus() else: self.widget.setCurrentWidget(tab) # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076 # Still seems to be needed with Qt 5.11.1 tab.setFocus() mode = modeman.instance(self._win_id).mode if mode in [usertypes.KeyMode.command, usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]: # If we were in a command prompt, restore old focus # The above commands need to be run to switch tabs if prev_focus is not None: prev_focus.setFocus() tab.show() self.new_tab.emit(tab, idx) return tab
def _connect_signals(self): """Connect all mainwindow signals.""" mode_manager = modeman.instance(self.win_id) # misc self.tabbed_browser.close_window.connect(self.close) mode_manager.entered.connect(hints.on_mode_entered) # status bar mode_manager.hintmanager.set_text.connect(self.status.set_text) mode_manager.entered.connect(self.status.on_mode_entered) mode_manager.left.connect(self.status.on_mode_left) mode_manager.left.connect(self.status.cmd.on_mode_left) mode_manager.left.connect(message.global_bridge.mode_left) # commands mode_manager.keystring_updated.connect( self.status.keystring.on_keystring_updated) self.status.cmd.got_cmd[str].connect(self._commandrunner.run_safely) self.status.cmd.got_cmd[str, int].connect(self._commandrunner.run_safely) self.status.cmd.returnPressed.connect( self.tabbed_browser.on_cmd_return_pressed) self.status.cmd.got_search.connect(self._command_dispatcher.search) # key hint popup mode_manager.keystring_updated.connect(self._keyhint.update_keyhint) # messages message.global_bridge.show_message.connect( self._messageview.show_message) message.global_bridge.flush() message.global_bridge.clear_messages.connect( self._messageview.clear_messages) # statusbar self.tabbed_browser.current_tab_changed.connect( self.status.on_tab_changed) self.tabbed_browser.cur_progress.connect( self.status.prog.on_load_progress) self.tabbed_browser.cur_load_started.connect( self.status.prog.on_load_started) self.tabbed_browser.cur_scroll_perc_changed.connect( self.status.percentage.set_perc) self.tabbed_browser.widget.tab_index_changed.connect( self.status.tabindex.on_tab_index_changed) self.tabbed_browser.cur_url_changed.connect(self.status.url.set_url) self.tabbed_browser.cur_url_changed.connect( functools.partial(self.status.backforward.on_tab_cur_url_changed, tabs=self.tabbed_browser)) self.tabbed_browser.cur_link_hovered.connect( self.status.url.set_hover_url) self.tabbed_browser.cur_load_status_changed.connect( self.status.url.on_load_status_changed) self.tabbed_browser.cur_caret_selection_toggled.connect( self.status.on_caret_selection_toggled) self.tabbed_browser.cur_fullscreen_requested.connect( self._on_fullscreen_requested) self.tabbed_browser.cur_fullscreen_requested.connect( self.status.maybe_hide) # downloadview self.tabbed_browser.cur_fullscreen_requested.connect( self._downloadview.on_fullscreen_requested) # command input / completion mode_manager.entered.connect(self.tabbed_browser.on_mode_entered) mode_manager.left.connect(self.tabbed_browser.on_mode_left) self.status.cmd.clear_completion_selection.connect( self._completion.on_clear_completion_selection) self.status.cmd.hide_completion.connect(self._completion.hide)
def start( self, # pylint: disable=keyword-arg-before-vararg group: str = 'all', target: Target = Target.normal, *args: str, mode: str = None, add_history: bool = False, rapid: bool = False, first: bool = False) -> None: """Start hinting. Args: rapid: Whether to do rapid hinting. With rapid hinting, the hint mode isn't left after a hint is followed, so you can easily open multiple links. This is only possible with targets `tab` (with `tabs.background=true`), `tab-bg`, `window`, `run`, `hover`, `userscript` and `spawn`. add_history: Whether to add the spawned or yanked link to the browsing history. first: Click the first hinted element without prompting. group: The element types to hint. - `all`: All clickable elements. - `links`: Only links. - `images`: Only images. - `inputs`: Only input fields. Custom groups can be added via the `hints.selectors` setting and also used here. 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 `tabs.background` 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. - `right-click`: Right-click the element. - `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. - `delete`: Delete the selected element. mode: The hinting mode to use. - `number`: Use numeric hints. - `letter`: Use the chars in the hints.chars setting. - `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_HOME`), 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.widget.currentWidget() if tab is None: raise cmdutils.CommandError("No WebView available yet!") mode_manager = modeman.instance(self._win_id) if mode_manager.mode == usertypes.KeyMode.hint: modeman.leave(self._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, Target.yank, Target.yank_primary ]: pass elif target == Target.tab and config.val.tabs.background: pass else: name = target.name.replace('_', '-') raise cmdutils.CommandError("Rapid hinting makes no sense " "with target {}!".format(name)) self._check_args(target, *args) try: baseurl = tabbed_browser.current_url() except qtutils.QtValueError: raise cmdutils.CommandError("No URL set for this page yet!") self._context = HintContext( tab=tab, target=target, rapid=rapid, hint_mode=self._get_hint_mode(mode), add_history=add_history, first=first, baseurl=baseurl, args=list(args), group=group, ) try: selector = webelem.css_selector(self._context.group, self._context.baseurl) except webelem.Error as e: raise cmdutils.CommandError(str(e)) self._context.tab.elements.find_css( selector, callback=self._start_cb, error_cb=lambda err: message.error(str(err)), only_visible=True)
def _get_keyparser(self, mode: usertypes.KeyMode) -> basekeyparser.BaseKeyParser: mode_manager = modeman.instance(self._win_id) return mode_manager.parsers[mode]