From e3fae14c694de5d54b62d47386cc4aa7aff0e110 Mon Sep 17 00:00:00 2001 From: claudi Date: Wed, 4 Mar 2026 16:56:38 +0100 Subject: [PATCH] feat: add Developer Tools integration with shortcut for enhanced debugging --- src/webdrop_bridge/main.py | 4 ++ src/webdrop_bridge/ui/developer_tools.py | 54 +++++++++++++++++++++++ src/webdrop_bridge/ui/main_window.py | 56 +++++++++++++++++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/webdrop_bridge/ui/developer_tools.py diff --git a/src/webdrop_bridge/main.py b/src/webdrop_bridge/main.py index 99f9fcc..b8b4c18 100644 --- a/src/webdrop_bridge/main.py +++ b/src/webdrop_bridge/main.py @@ -7,6 +7,10 @@ import sys # This ensures CSS media queries (hover: hover) evaluate correctly for desktop applications os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--touch-events=disabled" +# Enable Qt WebEngine Remote Debugging Protocol (Chromium Developer Tools) +# Allows debugging via browser DevTools at http://localhost:9222 or edge://inspect +os.environ["QTWEBENGINE_REMOTE_DEBUGGING"] = "9222" + from PySide6.QtWidgets import QApplication from webdrop_bridge.config import Config, ConfigurationError diff --git a/src/webdrop_bridge/ui/developer_tools.py b/src/webdrop_bridge/ui/developer_tools.py new file mode 100644 index 0000000..30cfe61 --- /dev/null +++ b/src/webdrop_bridge/ui/developer_tools.py @@ -0,0 +1,54 @@ +"""Developer Tools for WebDrop Bridge - using Chromium Remote Debugging Protocol.""" + +import logging +from typing import Any + +from PySide6.QtCore import QTimer, QUrl +from PySide6.QtWebEngineWidgets import QWebEngineView +from PySide6.QtWidgets import QVBoxLayout, QWidget + +logger = logging.getLogger(__name__) + +__all__ = ["DeveloperToolsWidget"] + + +class DeveloperToolsWidget(QWidget): + """Embedded Chromium Developer Tools Inspector. + + Loads the Chromium DevTools UI using the Remote Debugging Protocol + running on localhost:9222. + + Features: + - Real HTML/CSS Inspector with live editing + - Full JavaScript Console with all DevTools features + - Network monitoring + - Performance profiling + - Storage inspection + - All standard Chromium DevTools features + """ + + def __init__(self, web_view: Any) -> None: + """Initialize Developer Tools. + + Args: + web_view: The QWebEngineView to debug + """ + super().__init__() + self.web_view = web_view + + # Create layout + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + + # Create WebEngineView for DevTools UI + self.dev_tools_view = QWebEngineView() + layout.addWidget(self.dev_tools_view) + + # Load DevTools after delay to let debugger start + QTimer.singleShot(500, self._load_devtools) + + def _load_devtools(self) -> None: + """Load the DevTools targets page from localhost:9222.""" + logger.info("Loading DevTools from http://localhost:9222") + self.dev_tools_view.load(QUrl("http://localhost:9222")) diff --git a/src/webdrop_bridge/ui/main_window.py b/src/webdrop_bridge/ui/main_window.py index 42bfaf5..c6db37e 100644 --- a/src/webdrop_bridge/ui/main_window.py +++ b/src/webdrop_bridge/ui/main_window.py @@ -22,7 +22,7 @@ from PySide6.QtCore import ( Signal, Slot, ) -from PySide6.QtGui import QDesktopServices, QIcon, QMouseEvent +from PySide6.QtGui import QDesktopServices, QIcon, QKeySequence, QMouseEvent, QShortcut from PySide6.QtWebChannel import QWebChannel from PySide6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEngineScript from PySide6.QtWidgets import ( @@ -425,6 +425,11 @@ class MainWindow(QMainWindow): # Create navigation toolbar (Kiosk-mode navigation) self._create_navigation_toolbar() + # Set up F12 keyboard shortcut for Developer Tools + f12_shortcut = QShortcut(QKeySequence(Qt.Key.Key_F12), self) + f12_shortcut.activated.connect(self._open_developer_tools) + logger.debug("F12 shortcut registered for Developer Tools") + # Create status bar self._create_status_bar() @@ -1307,6 +1312,11 @@ class MainWindow(QMainWindow): log_action.setToolTip("Open Log File") log_action.triggered.connect(self._open_log_file) + # Developer Tools button on the right + dev_tools_action = toolbar.addAction("🔧") + dev_tools_action.setToolTip("Developer Tools (F12)") + dev_tools_action.triggered.connect(self._open_developer_tools) + def _open_log_file(self) -> None: """Open the application log file in the system default text editor. @@ -1334,6 +1344,50 @@ class MainWindow(QMainWindow): f"No log file found at:\n{log_file}", ) + def _open_developer_tools(self) -> None: + """Open Developer Tools in a separate window. + + Creates a dedicated window with JavaScript Console and DOM Inspector. + Provides code execution, DOM inspection, and console log capture all + in your application window - no external browser needed. + """ + try: + # Check if dev tools window already exists and is visible + if not hasattr(self, "_dev_tools_window") or self._dev_tools_window is None: + from webdrop_bridge.ui.developer_tools import DeveloperToolsWidget + + # Create new window + self._dev_tools_window = QMainWindow() + self._dev_tools_window.setWindowTitle("🔧 Developer Tools") + self._dev_tools_window.setGeometry(100, 100, 1200, 700) + self._dev_tools_window.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) + + # Create developer tools widget + dev_tools_widget = DeveloperToolsWidget(self.web_view) + + # Set the widget as central widget + self._dev_tools_window.setCentralWidget(dev_tools_widget) + + # Connect close event to clear reference + def on_close_dev_tools(): + self._dev_tools_window = None + + self._dev_tools_window.destroyed.connect(on_close_dev_tools) + + # Show or bring to front + self._dev_tools_window.show() + self._dev_tools_window.raise_() + self._dev_tools_window.activateWindow() + logger.info("Developer Tools window opened") + + except Exception as e: + logger.error(f"Failed to open Developer Tools window: {e}", exc_info=True) + QMessageBox.warning( + self, + "Developer Tools", + f"Could not open Developer Tools:\n{e}", + ) + def _create_status_bar(self) -> None: """Create status bar with update status indicator.""" self.status_bar = self.statusBar()