Skip to content

Commit 69a9616

Browse files
committed
updated auto update function for live log view, ui improvements
1 parent 48e9e7d commit 69a9616

4 files changed

Lines changed: 198 additions & 79 deletions

File tree

ui/menu.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
from PyQt6.QtGui import QAction, QKeySequence
2-
from PyQt6.QtWidgets import QMenuBar, QMessageBox, QToolBar, QToolButton
3-
from PyQt6.QtCore import Qt
4-
from PyQt6.QtWidgets import QStyle
5-
from PyQt6.QtCore import QSize
2+
from PyQt6.QtCore import Qt, QSize
3+
from PyQt6.QtWidgets import (
4+
QMenuBar,
5+
QMessageBox,
6+
QToolBar,
7+
QToolButton,
8+
QWidget,
9+
QHBoxLayout,
10+
QPushButton,
11+
QStyle,
12+
)
613
from core.commands import COMMANDS
714
from models.test_scenario import TestScenarioModel
815
from typing import TYPE_CHECKING
@@ -171,37 +178,37 @@ def apply_fixed_widths(self) -> None:
171178
)
172179

173180
def create_corner_run_toolbar(self):
174-
"""Super compact icons-only in corner"""
175-
run_toolbar = QToolBar("Run", self)
176-
run_toolbar.setAccessibleName("corner-toolbar")
177-
run_toolbar.setMovable(False)
178-
run_toolbar.setFloatable(False)
179-
run_toolbar.setIconSize(QSize(14, 14))
180-
181-
# Add buttons (same as above)
182-
self.run_button = QToolButton()
183-
self.run_button.setText("▶")
181+
toolbar_widget = QWidget()
182+
toolbar_widget.setObjectName
183+
toolbar_layout = QHBoxLayout(toolbar_widget)
184+
toolbar_layout.setContentsMargins(5, 0, 5, 0)
185+
toolbar_layout.setSpacing(1)
186+
187+
self.run_button = QPushButton("▶")
184188
self.run_button.setToolTip("Run Current Module (Ctrl+R)")
185189
self.run_button.clicked.connect(self.run_current_module)
190+
self.run_button.setFlat(True)
186191
self.run_button.setObjectName("RunButton")
187-
run_toolbar.addWidget(self.run_button)
192+
toolbar_layout.addWidget(self.run_button)
188193

189-
self.stop_button = QToolButton()
190-
self.stop_button.setText("■")
194+
self.stop_button = QPushButton("■")
191195
self.stop_button.setToolTip("Stop Execution (Ctrl+Shift+R)")
192196
self.stop_button.clicked.connect(self.stop_test)
197+
self.stop_button.setFlat(True)
193198
self.stop_button.setObjectName("StopButton")
194199
self.stop_button.setEnabled(False)
195-
run_toolbar.addWidget(self.stop_button)
200+
toolbar_layout.addWidget(self.stop_button)
196201

197-
self.config_button = QToolButton()
198-
self.config_button.setText("⚙")
202+
self.config_button = QPushButton("⚙")
199203
self.config_button.setToolTip("Run Configuration")
200204
self.config_button.clicked.connect(self.show_run_config)
205+
self.config_button.setFlat(True)
201206
self.config_button.setObjectName("ConfigButton")
202-
run_toolbar.addWidget(self.config_button)
207+
toolbar_layout.addWidget(self.config_button)
208+
209+
toolbar_layout.addStretch()
203210

204-
self.main.menuBar().setCornerWidget(run_toolbar, Qt.Corner.TopRightCorner)
211+
self.main.menuBar().setCornerWidget(toolbar_widget, Qt.Corner.TopRightCorner)
205212

206213
def run_current_module(self):
207214
self.main.run_current_module()

ui/output_dock.py

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
from PyQt6.QtWidgets import (QDockWidget, QTabWidget, QTextEdit, QTabBar, QToolBar, QVBoxLayout, QWidget,
1+
from PyQt6.QtWidgets import (QDockWidget, QTabWidget, QTextEdit, QTabBar, QVBoxLayout, QWidget,
22
QHBoxLayout, QPushButton, QLabel)
3-
from PyQt6.QtCore import Qt, pyqtSignal, QUrl, QFileSystemWatcher
4-
from PyQt6.QtGui import QTextCursor
3+
from PyQt6.QtCore import Qt, pyqtSignal, QUrl, QFileSystemWatcher, QTimer
54
from PyQt6.QtWebEngineWidgets import QWebEngineView
65
from PyQt6.QtWebEngineCore import QWebEnginePage, QWebEngineHistory
6+
from PyQt6.QtWidgets import QStyle
7+
from PyQt6.QtWebEngineCore import QWebEngineProfile, QWebEngineScript
8+
79

810
class OutputDock(QDockWidget):
911
clear_requested = pyqtSignal()
@@ -15,19 +17,29 @@ def __init__(self, parent=None):
1517
title_bar = QWidget()
1618
title_bar_layout = QHBoxLayout(title_bar)
1719
title_bar_layout.setContentsMargins(5, 0, 5, 0)
18-
title_bar_layout.setSpacing(5)
20+
title_bar_layout.setSpacing(1)
1921

20-
title_label = QLabel("Output:")
21-
title_bar_layout.addWidget(title_label)
2222
title_bar_layout.addStretch()
2323

2424
self.is_maximized = False
2525
self.restore_height = 0
2626

27-
self.back_button = QPushButton("Back")
28-
self.forward_button = QPushButton("Forward")
29-
self.open_log_button = QPushButton("Open Log")
30-
self.maximize_button = QPushButton("Maximize")
27+
style = self.style()
28+
# back_icon = style.standardIcon(QStyle.StandardPixmap.SP_ArrowBack)
29+
# forward_icon = style.standardIcon(QStyle.StandardPixmap.SP_ArrowForward)
30+
open_log_icon = style.standardIcon(QStyle.StandardPixmap.SP_DialogOpenButton)
31+
self.maximize_icon = style.standardIcon(QStyle.StandardPixmap.SP_TitleBarMaxButton)
32+
self.restore_icon = style.standardIcon(QStyle.StandardPixmap.SP_TitleBarNormalButton)
33+
34+
self.back_button = QPushButton("◀")
35+
self.forward_button = QPushButton("▶")
36+
self.maximize_button = QPushButton(icon=self.maximize_icon)
37+
self.open_log_button = QPushButton(icon=open_log_icon)
38+
39+
self.back_button.setObjectName("DockTitleBarButton")
40+
self.forward_button.setObjectName("DockTitleBarButton")
41+
self.maximize_button.setObjectName("DockTitleBarButton")
42+
self.open_log_button.setObjectName("DockTitleBarButton")
3143

3244
self.back_button.hide()
3345
self.forward_button.hide()
@@ -37,6 +49,16 @@ def __init__(self, parent=None):
3749
title_bar_layout.addWidget(self.open_log_button)
3850
title_bar_layout.addWidget(self.maximize_button)
3951

52+
self.back_button.setFlat(True)
53+
self.forward_button.setFlat(True)
54+
self.open_log_button.setFlat(True)
55+
self.maximize_button.setFlat(True)
56+
57+
self.back_button.setToolTip("Go Back (Alt+Left)")
58+
self.forward_button.setToolTip("Go Forward (Alt+Right)")
59+
self.open_log_button.setToolTip("Open Log File")
60+
self.maximize_button.setToolTip("Maximize/Restore Dock (Ctrl+M)")
61+
4062
self.setTitleBarWidget(title_bar)
4163
self.maximize_button.clicked.connect(self.toggle_maximize)
4264

@@ -58,19 +80,22 @@ def __init__(self, parent=None):
5880
self.tabs.tabBar().setTabButton(0, QTabBar.ButtonPosition.RightSide, None)
5981
self.tabs.currentChanged.connect(self.on_tab_changed)
6082

83+
self.log_polling_timer = QTimer(self)
84+
self.log_polling_timer.timeout.connect(self._poll_active_log)
85+
86+
self._warmup_web_engine()
87+
6188
def get_console(self):
6289
return self.console
6390

6491
def open_log_tab(self, filepath, title):
6592
report_view = QWebEngineView()
93+
report_view.loadFinished.connect(self._scroll_log)
6694
report_view.setUrl(QUrl.fromLocalFile(filepath))
6795

6896
index = self.tabs.addTab(report_view, title)
6997
self.tabs.setCurrentIndex(index)
7098

71-
watcher = QFileSystemWatcher([filepath], self)
72-
watcher.fileChanged.connect(report_view.reload)
73-
7499
def close_tab(self, index):
75100
if index == 0:
76101
return
@@ -123,7 +148,8 @@ def toggle_maximize(self):
123148
# self.setFixedHeight(self.restore_height)
124149
main_window.centralWidget().show()
125150
self.is_maximized = False
126-
self.maximize_button.setText("Maximize")
151+
# self.maximize_button.setText("Maximize")
152+
self.maximize_button.setIcon(self.maximize_icon)
127153
else:
128154
if self.restore_height == 0:
129155
self.restore_height = self.height()
@@ -134,7 +160,8 @@ def toggle_maximize(self):
134160
# self.setFixedHeight(maximized_height)
135161
main_window.centralWidget().hide()
136162
self.is_maximized = True
137-
self.maximize_button.setText("Restore")
163+
self.maximize_button.setIcon(self.restore_icon)
164+
# self.maximize_button.setText("Restore")
138165

139166
def _update_back_button_status(self):
140167
current_widget = self.property("current_log_widget")
@@ -150,3 +177,38 @@ def _update_forward_button_status(self):
150177

151178
def is_dock_maximized(self):
152179
return self.is_maximized
180+
181+
def _warmup_web_engine(self):
182+
temp_view = QWebEngineView()
183+
temp_view.deleteLater()
184+
185+
def _scroll_log(self, ok):
186+
if not ok:
187+
return
188+
189+
view = self.sender()
190+
if not view:
191+
return
192+
193+
def do_scroll():
194+
try:
195+
js_code = "window.scrollTo(0, document.body.scrollHeight);"
196+
view.page().runJavaScript(js_code)
197+
except RuntimeError as e:
198+
if "has been deleted" in str(e):
199+
pass
200+
else:
201+
raise
202+
203+
QTimer.singleShot(50, do_scroll)
204+
205+
def start_log_polling(self, interval_ms=1000):
206+
self.log_polling_timer.start(interval_ms)
207+
208+
def stop_log_polling(self):
209+
self.log_polling_timer.stop()
210+
211+
def _poll_active_log(self):
212+
current_widget = self.tabs.currentWidget()
213+
if isinstance(current_widget, QWebEngineView):
214+
current_widget.reload()

0 commit comments

Comments
 (0)