Add Tools menu buttons directly to QMenuBar next to menu headers

- Инструменты добавлены непосредственно на панель меню QMenuBar в виде QToolButton.
- Действия инструментов отображаются справа от заголовков меню (Файл, Правка, Вид, Инструменты).
- Действия инструментов отделены от заголовков вертикальным разделителем.
- Добавлен и пройден тест test_menu_bar_tools_buttons в qa_smoke.py.
This commit is contained in:
Данил Ярош 2026-07-31 16:32:24 +03:00
parent c3b98d7fe8
commit 3431ef6b50
2 changed files with 67 additions and 1 deletions

View File

@ -37,6 +37,8 @@ from PySide6.QtWidgets import (
QLineEdit,
QPlainTextEdit,
QTextEdit,
QFrame,
QWidgetAction,
)
try:
@ -491,6 +493,34 @@ class MainWindow(QMainWindow):
tools_menu.addSeparator()
tools_menu.addAction(self.actions["brush"])
# Add vertical separator and buttons next to the menu headers in the QMenuBar
container = QWidget()
layout = QHBoxLayout(container)
layout.setContentsMargins(10, 0, 10, 0)
layout.setSpacing(4)
# Vertical line separator
separator = QFrame()
separator.setFrameShape(QFrame.Shape.VLine)
separator.setFrameShadow(QFrame.Shadow.Sunken)
separator.setStyleSheet("color: #cbd5e1; margin: 4px 0;")
layout.addWidget(separator)
# Add Tools actions as buttons
for key in ["add_line", "add_led", "generate_script", "auto_blocks", "counterclockwise", "brush"]:
action = self.actions[key]
btn = QToolButton()
btn.setDefaultAction(action)
btn.setIconSize(QSize(16, 16))
btn.setToolButtonStyle(Qt.ToolButtonIconOnly)
btn.setAutoRaise(True)
btn.setStyleSheet("QToolButton { border: none; padding: 2px; }")
layout.addWidget(btn)
widget_action = QWidgetAction(menu_bar)
widget_action.setDefaultWidget(container)
menu_bar.addAction(widget_action)
def _build_layout(self) -> None:
side = QWidget()
self.side_panel = side

View File

@ -130,6 +130,7 @@ def main() -> None:
test_block_renaming_and_naming_strategy,
test_line_renaming_and_tree_shortcuts,
test_new_file_action,
test_menu_bar_tools_buttons,
test_export_mapping_to_image,
test_save_preserves_unknown_source_fields,
test_ordered_json_preserves_document_and_remaps_uids,
@ -1186,6 +1187,41 @@ def test_new_file_action() -> None:
def test_menu_bar_tools_buttons() -> None:
if MainWindow is None or QApplication is None:
return
app = QApplication.instance() or QApplication([])
window = MainWindow()
app.processEvents()
# Find the QWidgetAction in the QMenuBar
from PySide6.QtWidgets import QWidgetAction, QToolButton, QFrame
menu_bar = window.menuBar()
widget_actions = [action for action in menu_bar.actions() if isinstance(action, QWidgetAction)]
assert len(widget_actions) == 1
container = widget_actions[0].defaultWidget()
assert container is not None
# Check layout
layout = container.layout()
assert layout is not None
# Find separator and buttons
frames = container.findChildren(QFrame)
assert len(frames) == 1
buttons = container.findChildren(QToolButton)
assert len(buttons) == 6
button_actions = [btn.defaultAction() for btn in buttons]
expected_keys = ["add_line", "add_led", "generate_script", "auto_blocks", "counterclockwise", "brush"]
for key in expected_keys:
assert window.actions[key] in button_actions
window.close()
def test_export_mapping_to_image() -> None:
if QApplication is None:
return
@ -1935,7 +1971,7 @@ def test_classic_menu_contains_expected_actions() -> None:
app.processEvents()
expected = {
"Файл": ["Создать...", "Открыть", "Сохранить", "Сохранить как", "Сгенерировать скрипт", "Параметры"],
"Файл": ["Создать...", "Открыть", "Сохранить", "Сохранить как", "Экспортировать в изображение...", "Сгенерировать скрипт", "Параметры"],
"Правка": ["Отменить", "Повторить", "Удалить фиксацию", "Удалить точки", "Удалить все", "Очистить выбор"],
"Вид": [
"Показать всё",