From ace9238329d7377bb711bfa1ff92303dca6bade4 Mon Sep 17 00:00:00 2001 From: Rebecca Breu Date: Sat, 5 Jun 2021 16:49:08 +0200 Subject: [PATCH] Add action to toggle title bar --- beeref/actions/actions.py | 7 +++++ beeref/actions/menu_structure.py | 1 + beeref/actions/mixin.py | 4 ++- beeref/view.py | 21 ++++++++----- tests/actions/test_mixin.py | 28 +++++++++++++++++ tests/test_main.py | 2 +- tests/test_view.py | 52 ++++++++++++++++++++++++++++++-- 7 files changed, 103 insertions(+), 12 deletions(-) diff --git a/beeref/actions/actions.py b/beeref/actions/actions.py index 53ef396..83d8083 100644 --- a/beeref/actions/actions.py +++ b/beeref/actions/actions.py @@ -225,6 +225,13 @@ actions = [ 'settings': 'View/show_menubar', 'callback': 'on_action_show_menubar', }, + { + 'id': 'show_titlebar', + 'text': 'Show &Title Bar', + 'checkable': True, + 'checked': True, + 'callback': 'on_action_show_titlebar', + }, { 'id': 'fullscreen', 'text': '&Fullscreen', diff --git a/beeref/actions/menu_structure.py b/beeref/actions/menu_structure.py index b843049..9f99d54 100644 --- a/beeref/actions/menu_structure.py +++ b/beeref/actions/menu_structure.py @@ -57,6 +57,7 @@ menu_structure = [ 'always_on_top', 'show_scrollbars', 'show_menubar', + 'show_titlebar', ], }, { diff --git a/beeref/actions/mixin.py b/beeref/actions/mixin.py index 503b7bf..570ffe0 100644 --- a/beeref/actions/mixin.py +++ b/beeref/actions/mixin.py @@ -61,8 +61,10 @@ class ActionsMixin: callback = getattr(self, actiondef['callback']) qaction.toggled.connect(callback) settings_key = actiondef.get('settings') + checked = actiondef.get('checked', False) + qaction.setChecked(checked) if settings_key: - val = self.settings.value(settings_key, False, type=bool) + val = self.settings.value(settings_key, checked, type=bool) qaction.setChecked(val) self._post_create_functions.append((callback, val)) qaction.toggled.connect( diff --git a/beeref/view.py b/beeref/view.py index 8c1d5fc..c5a8798 100644 --- a/beeref/view.py +++ b/beeref/view.py @@ -40,7 +40,11 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): self.app = app self.parent = parent self.settings = BeeSettings() + self.welcome_overlay = gui.WelcomeOverlay(self) + self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(60, 60, 60))) + self.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) + self.setAcceptDrops(True) self.undo_stack = QtGui.QUndoStack(self) self.undo_stack.setUndoLimit(100) @@ -48,19 +52,15 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): self.undo_stack.canUndoChanged.connect(self.on_can_undo_changed) self.undo_stack.cleanChanged.connect(self.on_undo_clean_changed) - self.scene = BeeGraphicsScene(self.undo_stack) self.filename = None - - self.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) - self.setAcceptDrops(True) - self.previous_transform = None self.pan_active = False self.zoom_active = False self.movewin_active = False + + self.scene = BeeGraphicsScene(self.undo_stack) self.scene.changed.connect(self.on_scene_changed) self.scene.selectionChanged.connect(self.on_selection_changed) - self.setScene(self.scene) # Context menu and actions @@ -69,8 +69,6 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.on_context_menu) - self.welcome_overlay = gui.WelcomeOverlay(self) - # Load file given via command line if commandline_args.filename: self.open_from_file(commandline_args.filename) @@ -200,6 +198,13 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): else: self.parent.setMenuBar(None) + def on_action_show_titlebar(self, checked): + self.parent.setWindowFlag( + Qt.WindowType.FramelessWindowHint, on=not checked) + self.parent.destroy() + self.parent.create() + self.parent.show() + def on_action_undo(self): logger.debug('Undo: %s' % self.undo_stack.undoText()) self.undo_stack.undo() diff --git a/tests/actions/test_mixin.py b/tests/actions/test_mixin.py index 6124336..15dc276 100644 --- a/tests/actions/test_mixin.py +++ b/tests/actions/test_mixin.py @@ -76,6 +76,34 @@ def test_create_actions_checkable( assert widget.bee_actions['foo'] == qaction +@patch('PyQt6.QtGui.QAction.triggered') +@patch('PyQt6.QtGui.QAction.toggled') +@patch('beeref.actions.mixin.menu_structure') +@patch('beeref.actions.mixin.actions') +def test_create_actions_checkable_checked_true( + actions_mock, menu_mock, toggle_mock, trigger_mock, qapp): + widget = FooWidget() + actions_mock.__iter__.return_value = [{ + 'id': 'foo', + 'text': '&Foo', + 'checkable': True, + 'checked': True, + 'callback': 'on_foo', + }] + + menu_mock.__iter__.return_value = ['foo'] + widget.build_menu_and_actions() + trigger_mock.connect.assert_not_called() + toggle_mock.connect.assert_called_once_with(widget.on_foo) + + assert len(widget.actions()) == 1 + qaction = widget.actions()[0] + assert qaction.text() == '&Foo' + assert qaction.isEnabled() is True + assert qaction.isChecked() is True + assert widget.bee_actions['foo'] == qaction + + @patch.object(FooWidget, 'on_foo') @patch.object(FooWidget, 'settings') @patch('PyQt6.QtGui.QAction.toggled') diff --git a/tests/test_main.py b/tests/test_main.py index 7779db2..d88c3d4 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -15,7 +15,7 @@ def test_beeref_mainwindow_init(show_mock, qapp): assert window.windowIcon() assert window.contentsMargins() == QtCore.QMargins(0, 0, 0, 0) assert isinstance(window.view, BeeGraphicsView) - show_mock.assert_called_once() + show_mock.assert_called() @patch('PyQt6.QtWidgets.QApplication') diff --git a/tests/test_view.py b/tests/test_view.py index 6f5dbd4..7dd932a 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -377,6 +377,30 @@ def test_on_action_cut(copy_mock, view, item): assert view.undo_stack.isClean() is False +@patch('PyQt6.QtWidgets.QWidget.create') +@patch('PyQt6.QtWidgets.QWidget.destroy') +@patch('PyQt6.QtWidgets.QWidget.show') +def test_on_action_always_on_top_checked( + show_mock, destroy_mock, create_mock, view): + view.on_action_always_on_top(True) + assert view.parent.windowFlags() & Qt.WindowType.WindowStaysOnTopHint + show_mock.assert_called_once() + destroy_mock.assert_called_once() + create_mock.assert_called_once() + + +@patch('PyQt6.QtWidgets.QWidget.create') +@patch('PyQt6.QtWidgets.QWidget.destroy') +@patch('PyQt6.QtWidgets.QWidget.show') +def test_on_action_always_on_top_unchecked( + show_mock, destroy_mock, create_mock, view): + view.on_action_always_on_top(False) + assert not (view.parent.windowFlags() & Qt.WindowType.WindowStaysOnTopHint) + show_mock.assert_called_once() + destroy_mock.assert_called_once() + create_mock.assert_called_once() + + def test_on_action_show_menubar(view): view.toplevel_menus = [QtWidgets.QMenu('Foo')] view.on_action_show_menubar(True) @@ -385,6 +409,30 @@ def test_on_action_show_menubar(view): assert view.parent.menuBar().actions() == [] +@patch('PyQt6.QtWidgets.QWidget.create') +@patch('PyQt6.QtWidgets.QWidget.destroy') +@patch('PyQt6.QtWidgets.QWidget.show') +def test_on_action_show_titlebar_checked( + show_mock, destroy_mock, create_mock, view): + view.on_action_show_titlebar(True) + assert not (view.parent.windowFlags() & Qt.WindowType.FramelessWindowHint) + show_mock.assert_called_once() + destroy_mock.assert_called_once() + create_mock.assert_called_once() + + +@patch('PyQt6.QtWidgets.QWidget.create') +@patch('PyQt6.QtWidgets.QWidget.destroy') +@patch('PyQt6.QtWidgets.QWidget.show') +def test_on_action_show_titlebar_unchecked( + show_mock, destroy_mock, create_mock, view): + view.on_action_show_titlebar(False) + assert view.parent.windowFlags() & Qt.WindowType.FramelessWindowHint + show_mock.assert_called_once() + destroy_mock.assert_called_once() + create_mock.assert_called_once() + + def test_on_action_delete_items(view, item): view.scene.addItem(item) item.setSelected(True) @@ -451,7 +499,7 @@ def test_zoom_in(pan_mock, reset_mock, view, imgfilename3x3): view.zoom(40, QtCore.QPointF(10, 10)) assert view.get_scale() == 1.04 reset_mock.assert_called_once_with() - pan_mock.assert_called_once_with(QtCore.QPoint(-10, -6)) + pan_mock.assert_called_once() @patch('beeref.view.BeeGraphicsView.reset_previous_transform') @@ -475,7 +523,7 @@ def test_zoom_out(pan_mock, reset_mock, view, imgfilename3x3): view.zoom(-40, QtCore.QPointF(10, 10)) assert view.get_scale() == 100 / 1.04 reset_mock.assert_called_once_with() - pan_mock.assert_called_once_with(QtCore.QPoint(9, 5)) + pan_mock.assert_called_once() @patch('beeref.view.BeeGraphicsView.reset_previous_transform')