def _on_load_finished(self, ok: bool) -> None: assert self._widget is not None if sip.isdeleted(self._widget): # https://github.com/qutebrowser/qutebrowser/issues/3498 return try: sess_manager = objreg.get('session-manager') except KeyError: # https://github.com/qutebrowser/qutebrowser/issues/4311 return sess_manager.save_autosave() if ok and not self._has_ssl_errors: if self.url().scheme() == 'https': self._set_load_status(usertypes.LoadStatus.success_https) else: self._set_load_status(usertypes.LoadStatus.success) elif ok: self._set_load_status(usertypes.LoadStatus.warn) else: self._set_load_status(usertypes.LoadStatus.error) self.load_finished.emit(ok) if not self.title(): self.title_changed.emit(self.url().toDisplayString()) self.zoom.reapply()
def _inject_userjs(self, frame): """Inject user JavaScripts into the page. Args: frame: The QWebFrame to inject the user scripts into. """ if sip.isdeleted(frame): log.greasemonkey.debug("_inject_userjs called for deleted frame!") return url = frame.url() if url.isEmpty(): url = frame.requestedUrl() log.greasemonkey.debug("_inject_userjs called for {} ({})" .format(frame, url.toDisplayString())) scripts = greasemonkey.gm_manager.scripts_for(url) # QtWebKit has trouble providing us with signals representing # page load progress at reasonable times, so we just load all # scripts on the same event. toload = scripts.start + scripts.end + scripts.idle if url.isEmpty(): # This happens during normal usage like with view source but may # also indicate a bug. log.greasemonkey.debug("Not running scripts for frame with no " "url: {}".format(frame)) assert not toload, toload for script in toload: if frame is self.mainFrame() or script.runs_on_sub_frames: log.webview.debug(f'Running GM script: {script}') frame.evaluateJavaScript(script.code())
def _on_load_finished(self, ok): if sip.isdeleted(self._widget): # https://github.com/qutebrowser/qutebrowser/issues/3498 return try: sess_manager = objreg.get('session-manager') except KeyError: # https://github.com/qutebrowser/qutebrowser/issues/4311 return sess_manager.save_autosave() if ok and not self._has_ssl_errors: if self.url().scheme() == 'https': self._set_load_status(usertypes.LoadStatus.success_https) else: self._set_load_status(usertypes.LoadStatus.success) elif ok: self._set_load_status(usertypes.LoadStatus.warn) else: self._set_load_status(usertypes.LoadStatus.error) self.load_finished.emit(ok) if not self.title(): self.title_changed.emit(self.url().toDisplayString()) self.zoom.set_current()
def on_ready_read(self): """Read json data from the client.""" if self._socket is None: # pragma: no cover # This happens when doing a connection while another one is already # active for some reason. if self._old_socket is None: log.ipc.warning("In on_ready_read with None socket and " "old_socket!") return log.ipc.debug("In on_ready_read with None socket!") socket = self._old_socket else: socket = self._socket if sip.isdeleted(socket): # pragma: no cover log.ipc.warning("Ignoring deleted IPC socket") return self._timer.stop() while socket is not None and socket.canReadLine(): data = bytes(socket.readLine()) self.got_raw.emit(data) log.ipc.debug("Read from socket 0x{:x}: {!r}".format( id(socket), data)) self._handle_data(data) if self._socket is not None: self._timer.start()
def _save_all(self, *, only_window=None, with_private=False): """Get a dict with data for all windows/tabs.""" data = {'windows': []} if only_window is not None: winlist = [only_window] else: winlist = objreg.window_registry for win_id in sorted(winlist): tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) main_window = objreg.get('main-window', scope='window', window=win_id) # We could be in the middle of destroying a window here if sip.isdeleted(main_window): continue if tabbed_browser.is_private and not with_private: continue win_data = {} active_window = QApplication.instance().activeWindow() if getattr(active_window, 'win_id', None) == win_id: win_data['active'] = True win_data['geometry'] = bytes(main_window.saveGeometry()) win_data['tabs'] = [] if tabbed_browser.is_private: win_data['private'] = True for i, tab in enumerate(tabbed_browser.widgets()): active = i == tabbed_browser.widget.currentIndex() win_data['tabs'].append(self._save_tab(tab, active)) data['windows'].append(win_data) return data
def _save_all(self, *, only_window=None, with_private=False, with_history=True): """Get a dict with data for all windows/tabs.""" data: _JsonType = {'windows': []} if only_window is not None: winlist: Iterable[int] = [only_window] else: winlist = objreg.window_registry for win_id in sorted(winlist): tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) main_window = objreg.get('main-window', scope='window', window=win_id) # We could be in the middle of destroying a window here if sip.isdeleted(main_window): continue if tabbed_browser.is_private and not with_private: continue win_data: _JsonType = {} active_window = objects.qapp.activeWindow() if getattr(active_window, 'win_id', None) == win_id: win_data['active'] = True win_data['geometry'] = bytes(main_window.saveGeometry()) win_data['tabs'] = [] if tabbed_browser.is_private: win_data['private'] = True for i, tab in enumerate(tabbed_browser.widgets()): active = i == tabbed_browser.widget.currentIndex() win_data['tabs'].append(self._save_tab(tab, active, with_history=with_history)) data['windows'].append(win_data) return data
def _inject_userjs(self, frame): """Inject user JavaScripts into the page. Args: frame: The QWebFrame to inject the user scripts into. """ if sip.isdeleted(frame): log.greasemonkey.debug("_inject_userjs called for deleted frame!") return url = frame.url() if url.isEmpty(): url = frame.requestedUrl() log.greasemonkey.debug("_inject_userjs called for {} ({})" .format(frame, url.toDisplayString())) greasemonkey = objreg.get('greasemonkey') scripts = greasemonkey.scripts_for(url) # QtWebKit has trouble providing us with signals representing # page load progress at reasonable times, so we just load all # scripts on the same event. toload = scripts.start + scripts.end + scripts.idle if url.isEmpty(): # This happens during normal usage like with view source but may # also indicate a bug. log.greasemonkey.debug("Not running scripts for frame with no " "url: {}".format(frame)) assert not toload, toload for script in toload: if frame is self.mainFrame() or script.runs_on_sub_frames: log.webview.debug('Running GM script: {}'.format(script.name)) frame.evaluateJavaScript(script.code())
def _cleanup(self, *, successful): """Clean up temporary files after the editor closed. Args: successful: Whether the editor exited successfully, i.e. the file can be deleted. """ assert self._remove_file is not None if (self._watcher is not None and not sip.isdeleted(self._watcher) and self._watcher.files()): failed = self._watcher.removePaths(self._watcher.files()) if failed: log.procs.error("Failed to unwatch paths: {}".format(failed)) if self._filename is None or not self._remove_file: # Could not create initial file. return assert self._proc is not None if successful: try: os.remove(self._filename) except OSError as e: # NOTE: Do not replace this with "raise CommandError" as it's # executed async. message.error("Failed to delete tempfile... ({})".format(e)) else: message.info( f"Keeping file {self._filename} as the editor process exited " "abnormally")
def debug_keytester() -> None: """Show a keytester widget.""" global _keytester_widget if (_keytester_widget and not sip.isdeleted(_keytester_widget) and _keytester_widget.isVisible()): _keytester_widget.close() else: _keytester_widget = miscwidgets.KeyTesterWidget() _keytester_widget.show()
def _pop(self): """Pop a question from the queue and ask it, if there are any.""" log.prompt.debug("Popping from queue {}".format(self._queue)) if self._queue: question = self._queue.popleft() if not sip.isdeleted(question): # the question could already be deleted, e.g. by a cancelled # download. See # https://github.com/qutebrowser/qutebrowser/issues/415 self.ask_question(question, blocking=False)
def window_only(current_win_id): """Close all windows except for the current one.""" for win_id, window in objreg.window_registry.items(): # We could be in the middle of destroying a window here if sip.isdeleted(window): continue if win_id != current_win_id: window.close()
def proc(qtbot, caplog): """A fixture providing a GUIProcess and cleaning it up after the test.""" p = guiprocess.GUIProcess('testprocess') yield p if not sip.isdeleted(p._proc) and p._proc.state() != QProcess.NotRunning: with caplog.at_level(logging.ERROR): with qtbot.wait_signal(p.finished, timeout=10000, raising=False) as blocker: p._proc.terminate() if not blocker.signal_triggered: p._proc.kill() p._proc.waitForFinished()
def _save_all(self, *, only_window=None, with_private=False): """Get a dict with data for all windows/tabs.""" data = {'windows': []} if only_window is not None: winlist = [only_window] else: winlist = objreg.window_registry for win_id in sorted(winlist): tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) main_window = objreg.get('main-window', scope='window', window=win_id) # We could be in the middle of destroying a window here if sip.isdeleted(main_window): continue if tabbed_browser.is_private and not with_private: continue win_data = {} active_window = QApplication.instance().activeWindow() if getattr(active_window, 'win_id', None) == win_id: win_data['active'] = True win_data['geometry'] = bytes(main_window.saveGeometry()) if tabbed_browser.is_private: win_data['private'] = True if tabbed_browser.is_treetabbedbrowser: # a dict where keys are node UIDs, and values are dicts # with tab data (the resul of _save_tab) and a list of # children UIDs tree_data = {} root_node = tabbed_browser.widget.tree_root for i, node in enumerate(root_node.traverse()): node_data = {} active = i == tabbed_browser.widget.currentIndex() node_data['tab'] = self._save_tab(node.value, active) node_data['children'] = [c.uid for c in node.children] node_data['collapsed'] = node.collapsed tree_data[node.uid] = node_data win_data['tree'] = tree_data else: win_data['tabs'] = [] for i, tab in enumerate(tabbed_browser.widgets()): active = i == tabbed_browser.widget.currentIndex() win_data['tabs'].append(self._save_tab(tab, active)) data['windows'].append(win_data) return data
def raise_window(window, alert=True): """Raise the given MainWindow object.""" window.setWindowState(window.windowState() & ~Qt.WindowMinimized) window.setWindowState(window.windowState() | Qt.WindowActive) window.raise_() # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-69568 QCoreApplication.processEvents( # type: ignore[call-overload] QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers) if not sip.isdeleted(window): # Could be deleted by the events run above window.activateWindow() if alert: objects.qapp.alert(window)
def _on_load_finished(self, ok: bool) -> None: assert self._widget is not None if sip.isdeleted(self._widget): # https://github.com/qutebrowser/qutebrowser/issues/3498 return if sessions.session_manager is not None: sessions.session_manager.save_autosave() self.load_finished.emit(ok) if not self.title(): self.title_changed.emit(self.url().toDisplayString()) self.zoom.reapply()
def qute_tabs(_url): """Handler for qute://tabs. Display information about all open tabs.""" tabs = collections.defaultdict(list) for win_id, window in objreg.window_registry.items(): if sip.isdeleted(window): continue tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) for tab in tabbed_browser.widgets(): if tab.url() not in [QUrl("qute://tabs/"), QUrl("qute://tabs")]: urlstr = tab.url().toDisplayString() tabs[str(win_id)].append((tab.title(), urlstr)) src = jinja.render('tabs.html', title='Tabs', tab_list_by_window=tabs) return 'text/html', src
def _remove_item(self, download): """Remove a given download.""" if sip.isdeleted(self): # https://github.com/qutebrowser/qutebrowser/issues/1242 return try: idx = self.downloads.index(download) except ValueError: # already removed return self.begin_remove_row.emit(idx) del self.downloads[idx] self.end_remove_row.emit() download.deleteLater() self._update_indexes() if not self.downloads: self._update_timer.stop() log.downloads.debug("Removed download {}".format(download))
def _on_proc_closed(self, _exitcode, exitstatus): """Write the editor text into the form field and clean up tempfile. Callback for QProcess when the editor was closed. """ if sip.isdeleted(self): # pragma: no cover log.procs.debug("Ignoring _on_proc_closed for deleted editor") return log.procs.debug("Editor closed") if exitstatus != QProcess.NormalExit: # No error/cleanup here, since we already handle this in # on_proc_error. return # do a final read to make sure we don't miss the last signal self._on_file_changed(self._filename) self.editing_finished.emit() self._cleanup()
def _on_load_finished(self, ok: bool) -> None: assert self._widget is not None if sip.isdeleted(self._widget): # https://github.com/qutebrowser/qutebrowser/issues/3498 return try: sess_manager = objreg.get('session-manager') except KeyError: # https://github.com/qutebrowser/qutebrowser/issues/4311 return sess_manager.save_autosave() self.load_finished.emit(ok) if not self.title(): self.title_changed.emit(self.url().toDisplayString()) self.zoom.reapply()
def _cleanup(self): """Clean up temporary files after the editor closed.""" assert self._remove_file is not None if (self._watcher is not None and not sip.isdeleted(self._watcher) and self._watcher.files()): failed = self._watcher.removePaths(self._watcher.files()) if failed: log.procs.error("Failed to unwatch paths: {}".format(failed)) if self._filename is None or not self._remove_file: # Could not create initial file. return assert self._proc is not None try: if self._proc.exit_status() != QProcess.CrashExit: os.remove(self._filename) except OSError as e: # NOTE: Do not replace this with "raise CommandError" as it's # executed async. message.error("Failed to delete tempfile... ({})".format(e))
def _get_socket(self, warn=True): """Get the current socket for on_ready_read. Arguments: warn: Whether to warn if no socket was found. """ if self._socket is None: # pragma: no cover # This happens when doing a connection while another one is already # active for some reason. if self._old_socket is None: if warn: log.ipc.warning("In _get_socket with None socket and old_socket!") return None log.ipc.debug("In _get_socket with None socket!") socket = self._old_socket else: socket = self._socket if sip.isdeleted(socket): # pragma: no cover log.ipc.warning("Ignoring deleted IPC socket") return None return socket
def raise_window(window, alert=True): """Raise the given MainWindow object.""" window.setWindowState(window.windowState() & ~Qt.WindowMinimized) window.setWindowState(window.windowState() | Qt.WindowActive) window.raise_() # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-69568 QCoreApplication.processEvents( # type: ignore[call-overload] QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers) window.activateWindow() global i3ipc_used if i3ipc_used and window.wm_variant == 'sway': curfoc = window.wm_connection.get_tree().find_focused().app_id if curfoc != 'org.qutebrowser.qutebrowser': window.wm_connection.command( '[app_id="org.qutebrowser.qutebrowser"] focus') if not sip.isdeleted(window): # Could be deleted by the events run above window.activateWindow() if alert: objects.qapp.alert(window)
def is_deleted(self): return sip.isdeleted(self._widget)
def is_deleted(self) -> bool: if self._widget is None: raise AssertionError return sip.isdeleted(self._widget)
def _on_webkit_icon_changed(self): """Emit iconChanged with a QIcon like QWebEngineView does.""" if sip.isdeleted(self._widget): log.webview.debug("Got _on_webkit_icon_changed for deleted view!") return self.icon_changed.emit(self._widget.icon())
def is_deleted(self) -> bool: assert self._widget is not None return sip.isdeleted(self._widget)
def on_web_closed(self, notification_id: int) -> None: assert notification_id == self.NOTIFICATION_ID, notification_id if not sip.isdeleted(self._systray): # This can get called during shutdown self._systray.hide()
def _update_geometry(): """Actually update the geometry if the object still exists.""" if sip.isdeleted(obj): return obj.updateGeometry()