Skip to content

Commit

Permalink
Add action "Move window"
Browse files Browse the repository at this point in the history
  • Loading branch information
rbreu committed Dec 2, 2023
1 parent 55c0e91 commit 723bb58
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 15 deletions.
10 changes: 6 additions & 4 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ Added
behaviour can be changed to always use PNG (the former behaviour) or
always JPG. To apply this behaviour to already saved images in
existing bee files, you can save them as new files.
* Enable antialiasing/smoothing. Images that are being displayed at a
* Enabled antialiasing/smoothing. Images that are being displayed at a
large zoom factor are exempt to make sure that icons, pixel sprites
etc can be viewed correctly.
* A scene can now be exported to a single image (File -> Export Scene...)
* Editing of text items will now be undoable after leaving edit mode
* Empty text items will be deleted after leaving edit mode
* Text edit mode can now be aborted with Escape
* Alternative way to move the BeeRef window without the title bar:
View -> Move Window (or press "M")


Changed
-------

* Editing of text items will now be undoable after leaving edit mode
* Empty text items will be deleted after leaving edit mode
* Text edit mode can now be aborted with Escape
* "Save as" will now open pre-select the folder of the currently opened file
* "Save" and "Save as" are now inactive when the scene is empty

Expand Down
6 changes: 6 additions & 0 deletions beeref/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@
'checked': True,
'callback': 'on_action_show_titlebar',
},
{
'id': 'move_window',
'text': 'Move &Window',
'shortcuts': ['Ctrl+M'],
'callback': 'on_action_move_window',
},
{
'id': 'fullscreen',
'text': '&Fullscreen',
Expand Down
2 changes: 2 additions & 0 deletions beeref/actions/menu_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
'show_scrollbars',
'show_menubar',
'show_titlebar',
MENU_SEPARATOR,
'move_window',
],
},
{
Expand Down
31 changes: 28 additions & 3 deletions beeref/main_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class MainControlsMixin:
* Right-click menu
* Dropping files
* Moving the window without title bar
"""

def init_main_controls(self, main_window):
Expand All @@ -42,6 +43,21 @@ def init_main_controls(self, main_window):
self.setAcceptDrops(True)
self.movewin_active = False

def enter_movewin_mode(self):
logger.debug('Entering movewin mode')
self.setMouseTracking(True)
self.movewin_active = True
self.event_start = QtCore.QPointF(self.cursor().pos())
if hasattr(self, 'disable_mouse_events'):
self.disable_mouse_events()

def exit_movewin_mode(self):
logger.debug('Exiting movewin mode')
self.setMouseTracking(False)
self.movewin_active = False
if hasattr(self, 'enable_mouse_events'):
self.enable_mouse_events()

def dragEnterEvent(self, event):
mimedata = event.mimeData()
logger.debug(f'Drag enter event: {mimedata.formats()}')
Expand Down Expand Up @@ -80,11 +96,14 @@ def dropEvent(self, event):
logger.info('Drop not an image')

def mousePressEventMainControls(self, event):
if self.movewin_active:
self.exit_movewin_mode()
event.accept()
return True
if (event.button() == Qt.MouseButton.LeftButton
and event.modifiers() == (Qt.KeyboardModifier.ControlModifier
| Qt.KeyboardModifier.AltModifier)):
self.movewin_active = True
self.event_start = self.mapToGlobal(event.position())
self.enter_movewin_mode()
event.accept()
return True

Expand All @@ -100,6 +119,12 @@ def mouseMoveEventMainControls(self, event):

def mouseReleaseEventMainControls(self, event):
if self.movewin_active:
self.movewin_active = False
self.exit_movewin_mode()
event.accept()
return True

def keyPressEventMainControls(self, event):
if self.movewin_active:
self.exit_movewin_mode()
event.accept()
return True
20 changes: 18 additions & 2 deletions beeref/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,13 @@ def on_scene_changed(self, region):
if not self.scene.items():
logger.debug('No items in scene')
self.setTransform(QtGui.QTransform())
self.welcome_overlay.setFocus()
self.clearFocus()
self.welcome_overlay.show()
self.actiongroup_set_enabled('active_when_items_in_scene', False)
else:
self.setFocus()
self.welcome_overlay.clearFocus()
self.welcome_overlay.hide()
self.actiongroup_set_enabled('active_when_items_in_scene', True)
self.recalc_scene_rect()
Expand Down Expand Up @@ -216,6 +220,12 @@ def on_action_show_titlebar(self, checked):
self.parent.create()
self.parent.show()

def on_action_move_window(self):
if self.welcome_overlay.isHidden():
self.enter_movewin_mode()
else:
self.welcome_overlay.enter_movewin_mode()

def on_action_undo(self):
logger.debug('Undo: %s' % self.undo_stack.undoText())
self.scene.cancel_crop_mode()
Expand Down Expand Up @@ -662,6 +672,9 @@ def wheelEvent(self, event):
event.accept()

def mousePressEvent(self, event):
if self.mousePressEventMainControls(event):
return

if (event.button() == Qt.MouseButton.MiddleButton
and event.modifiers() == Qt.KeyboardModifier.ControlModifier):
self.zoom_active = True
Expand All @@ -679,8 +692,6 @@ def mousePressEvent(self, event):
event.accept()
return

if self.mousePressEventMainControls(event):
return
super().mousePressEvent(event)

def mouseMoveEvent(self, event):
Expand Down Expand Up @@ -723,3 +734,8 @@ def resizeEvent(self, event):
super().resizeEvent(event)
self.recalc_scene_rect()
self.welcome_overlay.resize(self.size())

def keyPressEvent(self, event):
if self.keyPressEventMainControls(event):
return
super().keyPressEvent(event)
27 changes: 23 additions & 4 deletions beeref/widgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ def __init__(self, parent):
self.files_layout.addStretch(50)

# Help text
label = QtWidgets.QLabel(self.txt, self)
label.setAlignment(Qt.AlignmentFlag.AlignVCenter
| Qt.AlignmentFlag.AlignCenter)
self.label = QtWidgets.QLabel(self.txt, self)
self.label.setAlignment(Qt.AlignmentFlag.AlignVCenter
| Qt.AlignmentFlag.AlignCenter)
self.layout = QtWidgets.QHBoxLayout()
self.layout.addStretch(50)
self.layout.addWidget(label)
self.layout.addWidget(self.label)
self.layout.addStretch(50)
self.setLayout(self.layout)

Expand All @@ -123,6 +123,20 @@ def show(self):
self.layout.insertLayout(0, self.files_layout)
super().show()

def disable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)

def enable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)

def mousePressEvent(self, event):
if self.mousePressEventMainControls(event):
return
Expand All @@ -138,6 +152,11 @@ def mouseReleaseEvent(self, event):
return
super().mouseReleaseEvent(event)

def keyPressEvent(self, event):
if self.keyPressEventMainControls(event):
return
super().keyPressEvent(event)


class BeeProgressDialog(QtWidgets.QProgressDialog):

Expand Down
41 changes: 39 additions & 2 deletions tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,25 @@ def test_on_action_show_titlebar_unchecked(
create_mock.assert_called_once()


@patch('beeref.widgets.WelcomeOverlay.cursor')
def test_on_action_move_window_when_welcome_overlay(cursor_mock, view):
cursor_mock.return_value = MagicMock(
pos=MagicMock(return_value=QtCore.QPointF(10.0, 20.0)))
view.on_action_move_window()
assert view.welcome_overlay.movewin_active is True
assert view.welcome_overlay.event_start == QtCore.QPointF(10.0, 20.0)


@patch('beeref.view.BeeGraphicsView.cursor')
def test_on_action_move_window_when_scene(cursor_mock, view):
cursor_mock.return_value = MagicMock(
pos=MagicMock(return_value=QtCore.QPointF(10.0, 20.0)))
view.welcome_overlay.hide()
view.on_action_move_window()
assert view.movewin_active is True
assert view.event_start == QtCore.QPointF(10.0, 20.0)


def test_on_action_delete_items(view, item):
view.scene.cancel_crop_mode = MagicMock()
view.scene.addItem(item)
Expand Down Expand Up @@ -781,9 +800,11 @@ def test_mouse_press_pan_alt_left_drag(mouse_event_mock, view):


@patch('PyQt6.QtWidgets.QGraphicsView.mousePressEvent')
def test_mouse_press_move_window(mouse_event_mock, view):
@patch('beeref.view.BeeGraphicsView.cursor')
def test_mouse_press_move_window(cursor_mock, mouse_event_mock, view):
event = MagicMock()
event.position.return_value = QtCore.QPointF(10.0, 20.0)
cursor_mock.return_value = MagicMock(
pos=MagicMock(return_value=QtCore.QPointF(10.0, 20.0)))
event.button.return_value = Qt.MouseButton.LeftButton
event.modifiers.return_value = (
Qt.KeyboardModifier.AltModifier | Qt.KeyboardModifier.ControlModifier)
Expand All @@ -796,6 +817,22 @@ def test_mouse_press_move_window(mouse_event_mock, view):
event.accept.assert_called_once_with()


@patch('PyQt6.QtWidgets.QGraphicsView.mousePressEvent')
def test_mouse_press_when_move_window_active(mouse_event_mock, view):
view.movewin_active = True
view.mousePressEvent(MagicMock())
assert view.movewin_active is False
mouse_event_mock.assert_not_called()


@patch('PyQt6.QtWidgets.QGraphicsView.keyPressEvent')
def test_key_press_when_move_window_active(key_event_mock, view):
view.movewin_active = True
view.keyPressEvent(MagicMock())
assert view.movewin_active is False
key_event_mock.assert_not_called()


@patch('PyQt6.QtWidgets.QGraphicsView.mousePressEvent')
def test_mouse_press_unhandled(mouse_event_mock, view):
event = MagicMock()
Expand Down

0 comments on commit 723bb58

Please sign in to comment.