diff options
Diffstat (limited to 'examples/webenginewidgets/simplebrowser/tabwidget.py')
-rw-r--r-- | examples/webenginewidgets/simplebrowser/tabwidget.py | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.py b/examples/webenginewidgets/simplebrowser/tabwidget.py new file mode 100644 index 000000000..bda321ac1 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/tabwidget.py @@ -0,0 +1,241 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +from functools import partial + +from PySide6.QtWebEngineCore import (QWebEngineFindTextResult, QWebEnginePage) +from PySide6.QtWidgets import QLabel, QMenu, QTabBar, QTabWidget +from PySide6.QtGui import QCursor, QIcon, QKeySequence, QPixmap +from PySide6.QtCore import QUrl, Qt, Signal, Slot + +from webpage import WebPage +from webview import WebView + + +class TabWidget(QTabWidget): + link_hovered = Signal(str) + load_progress = Signal(int) + title_changed = Signal(str) + url_changed = Signal(QUrl) + fav_icon_changed = Signal(QIcon) + web_action_enabled_changed = Signal(QWebEnginePage.WebAction, bool) + dev_tools_requested = Signal(QWebEnginePage) + find_text_finished = Signal(QWebEngineFindTextResult) + + def __init__(self, profile, parent): + super().__init__(parent) + self._profile = profile + tab_bar = self.tabBar() + tab_bar.setTabsClosable(True) + tab_bar.setSelectionBehaviorOnRemove(QTabBar.SelectPreviousTab) + tab_bar.setMovable(True) + tab_bar.setContextMenuPolicy(Qt.CustomContextMenu) + tab_bar.customContextMenuRequested.connect(self.handle_context_menu_requested) + tab_bar.tabCloseRequested.connect(self.close_tab) + tab_bar.tabBarDoubleClicked.connect(self._tabbar_double_clicked) + self.setDocumentMode(True) + self.setElideMode(Qt.ElideRight) + + self.currentChanged.connect(self.handle_current_changed) + + if profile.isOffTheRecord(): + icon = QLabel(self) + pixmap = QPixmap(":ninja.png") + icon.setPixmap(pixmap.scaledToHeight(tab_bar.height())) + w = icon.pixmap().width() + self.setStyleSheet(f"QTabWidget.tab-bar {{ left: {w}px; }}") + + @Slot(int) + def _tabbar_double_clicked(self, index): + if index == -1: + self.create_tab() + + def handle_current_changed(self, index): + if index != -1: + view = self.web_view(index) + if view.url(): + view.setFocus() + self.title_changed.emit(view.title()) + self.load_progress.emit(view.load_progress()) + self.url_changed.emit(view.url()) + self.fav_icon_changed.emit(view.fav_icon()) + e = view.is_web_action_enabled(QWebEnginePage.Back) + self.web_action_enabled_changed.emit(QWebEnginePage.Back, e) + e = view.is_web_action_enabled(QWebEnginePage.Forward) + self.web_action_enabled_changed.emit(QWebEnginePage.Forward, e) + e = view.is_web_action_enabled(QWebEnginePage.Stop) + self.web_action_enabled_changed.emit(QWebEnginePage.Stop, e) + e = view.is_web_action_enabled(QWebEnginePage.Reload) + self.web_action_enabled_changed.emit(QWebEnginePage.Reload, e) + else: + self.title_changed.emit("") + self.load_progress.emit(0) + self.url_changed.emit(QUrl()) + self.fav_icon_changed.emit(QIcon()) + self.web_action_enabled_changed.emit(QWebEnginePage.Back, False) + self.web_action_enabled_changed.emit(QWebEnginePage.Forward, False) + self.web_action_enabled_changed.emit(QWebEnginePage.Stop, False) + self.web_action_enabled_changed.emit(QWebEnginePage.Reload, True) + + def handle_context_menu_requested(self, pos): + menu = QMenu() + menu.addAction("New &Tab", QKeySequence.AddTab, self.create_tab) + index = self.tabBar().tabAt(pos) + if index != -1: + action = menu.addAction("Clone Tab") + action.triggered.connect(partial(self.clone_tab, index)) + menu.addSeparator() + action = menu.addAction("Close Tab") + action.setShortcut(QKeySequence.Close) + action.triggered.connect(partial(self.close_tab, index)) + action = menu.addAction("Close Other Tabs") + action.triggered.connect(partial(self.close_other_tabs, index)) + menu.addSeparator() + action = menu.addAction("Reload Tab") + action.setShortcut(QKeySequence.Refresh) + action.triggered.connect(partial(self.reload_tab, index)) + else: + menu.addSeparator() + + menu.addAction("Reload All Tabs", self.reload_all_tabs) + menu.exec(QCursor.pos()) + + def current_web_view(self): + return self.web_view(self.currentIndex()) + + def web_view(self, index): + return self.widget(index) + + def _title_changed(self, web_view, title): + index = self.indexOf(web_view) + if index != -1: + self.setTabText(index, title) + self.setTabToolTip(index, title) + + if self.currentIndex() == index: + self.title_changed.emit(title) + + def _url_changed(self, web_view, url): + index = self.indexOf(web_view) + if index != -1: + self.tabBar().setTabData(index, url) + if self.currentIndex() == index: + self.url_changed.emit(url) + + def _load_progress(self, web_view, progress): + if self.currentIndex() == self.indexOf(web_view): + self.load_progress.emit(progress) + + def _fav_icon_changed(self, web_view, icon): + index = self.indexOf(web_view) + if index != -1: + self.setTabIcon(index, icon) + if self.currentIndex() == index: + self.fav_icon_changed.emit(icon) + + def _link_hovered(self, web_view, url): + if self.currentIndex() == self.indexOf(web_view): + self.link_hovered.emit(url) + + def _webaction_enabled_changed(self, webView, action, enabled): + if self.currentIndex() == self.indexOf(webView): + self.web_action_enabled_changed.emit(action, enabled) + + def _window_close_requested(self, webView): + index = self.indexOf(webView) + if webView.page().inspectedPage(): + self.window().close() + elif index >= 0: + self.close_tab(index) + + def _find_text_finished(self, webView, result): + if self.currentIndex() == self.indexOf(webView): + self.find_text_finished.emit(result) + + def setup_view(self, webView): + web_page = webView.page() + webView.titleChanged.connect(partial(self._title_changed, webView)) + webView.urlChanged.connect(partial(self._url_changed, webView)) + webView.loadProgress.connect(partial(self._load_progress, webView)) + web_page.linkHovered.connect(partial(self._link_hovered, webView)) + webView.fav_icon_changed.connect(partial(self._fav_icon_changed, webView)) + webView.web_action_enabled_changed.connect(partial(self._webaction_enabled_changed, + webView)) + web_page.windowCloseRequested.connect(partial(self._window_close_requested, + webView)) + webView.dev_tools_requested.connect(self.dev_tools_requested) + web_page.findTextFinished.connect(partial(self._find_text_finished, + webView)) + + def create_tab(self): + web_view = self.create_background_tab() + self.setCurrentWidget(web_view) + return web_view + + def create_background_tab(self): + web_view = WebView() + web_page = WebPage(self._profile, web_view) + web_view.set_page(web_page) + self.setup_view(web_view) + index = self.addTab(web_view, "(Untitled)") + self.setTabIcon(index, web_view.fav_icon()) + # Workaround for QTBUG-61770 + web_view.resize(self.currentWidget().size()) + web_view.show() + return web_view + + def reload_all_tabs(self): + for i in range(0, self.count()): + self.web_view(i).reload() + + def close_other_tabs(self, index): + for i in range(index, self.count() - 1, -1): + self.close_tab(i) + for i in range(-1, index - 1, -1): + self.close_tab(i) + + def close_tab(self, index): + view = self.web_view(index) + if view: + has_focus = view.hasFocus() + self.removeTab(index) + if has_focus and self.count() > 0: + self.current_web_view().setFocus() + if self.count() == 0: + self.create_tab() + view.deleteLater() + + def clone_tab(self, index): + view = self.web_view(index) + if view: + tab = self.create_tab() + tab.setUrl(view.url()) + + def set_url(self, url): + view = self.current_web_view() + if view: + view.setUrl(url) + view.setFocus() + + def trigger_web_page_action(self, action): + web_view = self.current_web_view() + if web_view: + web_view.triggerPageAction(action) + web_view.setFocus() + + def next_tab(self): + next = self.currentIndex() + 1 + if next == self.count(): + next = 0 + self.setCurrentIndex(next) + + def previous_tab(self): + next = self.currentIndex() - 1 + if next < 0: + next = self.count() - 1 + self.setCurrentIndex(next) + + def reload_tab(self, index): + view = self.web_view(index) + if view: + view.reload() |