130 lines
5.0 KiB
Python
130 lines
5.0 KiB
Python
"""Shared drag gestures, with real Qt events and C math, without SETGUI imports."""
|
|
import ctypes
|
|
import os
|
|
import unittest
|
|
from dataclasses import replace
|
|
|
|
os.environ.setdefault('QT_QPA_PLATFORM', 'offscreen')
|
|
try:
|
|
from PySide6.QtCore import QEvent, QPoint, QPointF, QRectF, Qt, Signal
|
|
from PySide6.QtGui import QMouseEvent
|
|
from PySide6.QtTest import QTest
|
|
from PySide6.QtWidgets import QApplication, QCheckBox, QWidget
|
|
except ImportError:
|
|
from PySide2.QtCore import QEvent, QPoint, QPointF, QRectF, Qt, Signal
|
|
from PySide2.QtGui import QMouseEvent
|
|
from PySide2.QtTest import QTest
|
|
from PySide2.QtWidgets import QApplication, QCheckBox, QWidget
|
|
|
|
from protocan.plot import Bounds, Marker, Markers, PlotMath, Viewport
|
|
from set_devices.qt_ports.plot_drag import PlotDragInteraction
|
|
|
|
|
|
class Canvas(PlotDragInteraction, QWidget):
|
|
view_changed = Signal()
|
|
|
|
def __init__(self, core):
|
|
super().__init__()
|
|
self.core = core
|
|
self.viewport = Viewport(.25, .25, .5, .5)
|
|
self.markers = replace(Markers(a=40, b=60, e=50, f=65), y_enabled=True)
|
|
self.marker_mode = QCheckBox(self)
|
|
self.marker_mode.setChecked(True)
|
|
self.marker_mode.hide()
|
|
self.has_plot_data = True
|
|
self.lock_x = self.lock_y = False
|
|
self._press = self._dragged = None
|
|
self.single_clicks = []
|
|
self.resize(440, 340)
|
|
|
|
@property
|
|
def visible_bounds(self):
|
|
return Bounds(0, 100, 0, 100).visible(self.core, self.viewport)
|
|
|
|
def plot_rect(self):
|
|
return QRectF(20, 20, 400, 300)
|
|
|
|
def value_rect(self):
|
|
return QRectF(20, 20, 400, 200)
|
|
|
|
def _refresh_controls(self):
|
|
pass
|
|
|
|
def _single_cursor_click(self, pos):
|
|
self.single_clicks.append(pos)
|
|
|
|
|
|
@unittest.skipUnless(os.environ.get('SETPROTOCOL_LIBRARY'), 'Set SETPROTOCOL_LIBRARY')
|
|
class PlotDragTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.app = QApplication.instance() or QApplication([])
|
|
cls.core = PlotMath(ctypes.CDLL(os.environ['SETPROTOCOL_LIBRARY']))
|
|
|
|
def setUp(self):
|
|
self.plot = Canvas(self.core)
|
|
self.plot.show()
|
|
self.app.processEvents()
|
|
|
|
def tearDown(self):
|
|
self.plot.close()
|
|
|
|
def drag(self, start, end, modifiers=Qt.NoModifier):
|
|
QTest.mousePress(self.plot, Qt.LeftButton, modifiers, start)
|
|
QTest.mouseRelease(self.plot, Qt.LeftButton, modifiers, end)
|
|
|
|
def test_empty_space_pans_x_and_preserves_markers(self):
|
|
before, markers = self.plot.viewport, self.plot.markers
|
|
self.drag(QPoint(220, 180), QPoint(260, 210))
|
|
self.assertEqual(before.transform(self.core, pan_x=.1), self.plot.viewport)
|
|
self.assertEqual(markers, self.plot.markers)
|
|
|
|
def test_shift_over_marker_pans_only_y_and_respects_lock(self):
|
|
before, markers = self.plot.viewport, self.plot.markers
|
|
self.drag(QPoint(140, 180), QPoint(180, 200), Qt.ShiftModifier)
|
|
self.assertEqual(before.transform(self.core, pan_y=.1), self.plot.viewport)
|
|
self.assertEqual(markers, self.plot.markers)
|
|
self.plot.lock_y = True
|
|
before = self.plot.viewport
|
|
self.drag(QPoint(140, 180), QPoint(180, 200), Qt.ShiftModifier)
|
|
self.assertEqual(before, self.plot.viewport)
|
|
|
|
def test_marker_capture_in_analog_and_digital_panes(self):
|
|
before = self.plot.viewport
|
|
# X marker A at x=140 remains draggable in a digital lane.
|
|
self.drag(QPoint(145, 270), QPoint(185, 290))
|
|
self.assertAlmostEqual(45, self.plot.markers.a)
|
|
self.assertEqual(before, self.plot.viewport)
|
|
# Y marker E at y=120 uses the analog pane's height.
|
|
self.drag(QPoint(220, 125), QPoint(240, 145))
|
|
self.assertAlmostEqual(45, self.plot.markers.e)
|
|
self.assertEqual(before, self.plot.viewport)
|
|
|
|
def test_click_miss_and_locked_x_do_not_move_markers(self):
|
|
before, markers = self.plot.viewport, self.plot.markers
|
|
self.drag(QPoint(220, 180), QPoint(220, 180))
|
|
self.assertEqual(before, self.plot.viewport)
|
|
self.assertEqual(markers, self.plot.markers)
|
|
self.assertEqual(1, len(self.plot.single_clicks))
|
|
self.plot.lock_x = True
|
|
self.drag(QPoint(220, 180), QPoint(260, 210))
|
|
self.assertEqual(before, self.plot.viewport)
|
|
self.assertEqual(markers, self.plot.markers)
|
|
self.assertEqual(1, len(self.plot.single_clicks))
|
|
|
|
def test_marker_click_and_drag_returning_to_start_are_not_single_clicks(self):
|
|
point = QPoint(220, 180)
|
|
self.drag(QPoint(140, 180), QPoint(140, 180))
|
|
QTest.mousePress(self.plot, Qt.LeftButton, pos=point)
|
|
moved = point + QPoint(40, 0)
|
|
event = QMouseEvent(QEvent.MouseMove, QPointF(moved),
|
|
QPointF(self.plot.mapToGlobal(moved)),
|
|
Qt.NoButton, Qt.LeftButton, Qt.NoModifier)
|
|
self.app.sendEvent(self.plot, event)
|
|
QTest.mouseRelease(self.plot, Qt.LeftButton, pos=point)
|
|
self.assertEqual([], self.plot.single_clicks)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|