Share waveform data and plot navigation and retain processing results
This commit is contained in:
112
python/set_devices/qt_ports/plot_navigation.py
Normal file
112
python/set_devices/qt_ports/plot_navigation.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Common keyboard and wheel gestures for all plot canvases (Qt 5/6)."""
|
||||
try:
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import QScrollArea
|
||||
except ImportError:
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtWidgets import QScrollArea
|
||||
|
||||
NAVIGATION_HINT = ('Колесо и +/− — масштаб X; Ctrl + колесо и Ctrl + +/− — масштаб Y. '
|
||||
'ЛКМ на свободном поле — перемещение; ←/→ — перемещение по X; Home/End — начало/конец.')
|
||||
|
||||
|
||||
class PlotNavigation:
|
||||
def setup_navigation(self):
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.setToolTip(NAVIGATION_HINT)
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
key = event.key()
|
||||
modifiers = event.modifiers()
|
||||
if modifiers & (Qt.AltModifier | Qt.MetaModifier):
|
||||
return super().keyPressEvent(event)
|
||||
if key in (Qt.Key_Plus, Qt.Key_Equal, Qt.Key_Minus):
|
||||
self._navigation_zoom(1.25 if key != Qt.Key_Minus else .8,
|
||||
bool(modifiers & Qt.ControlModifier))
|
||||
elif key in (Qt.Key_Left, Qt.Key_Right) and not (modifiers & Qt.ControlModifier):
|
||||
self._navigation_pan(-.1 if key == Qt.Key_Left else .1)
|
||||
elif key in (Qt.Key_Home, Qt.Key_End):
|
||||
self._navigation_edge(key == Qt.Key_End)
|
||||
else:
|
||||
return super().keyPressEvent(event)
|
||||
event.accept()
|
||||
|
||||
def wheelEvent(self, event):
|
||||
position = event.position() if hasattr(event, 'position') else event.posF()
|
||||
rect = self.plot_rect() if hasattr(self, 'plot_rect') else self.rect()
|
||||
if not rect.contains(position.toPoint()):
|
||||
event.ignore()
|
||||
return
|
||||
delta = event.angleDelta()
|
||||
ticks = delta.y() or delta.x()
|
||||
if not ticks:
|
||||
pixels = event.pixelDelta()
|
||||
ticks = (pixels.y() or pixels.x()) * 2
|
||||
if ticks:
|
||||
self.setFocus(Qt.MouseFocusReason)
|
||||
self._navigation_zoom(1.25 ** max(-8, min(8, ticks / 120)),
|
||||
bool(event.modifiers() & Qt.ControlModifier), position)
|
||||
event.accept()
|
||||
|
||||
|
||||
class ScrollPlotNavigation(PlotNavigation):
|
||||
"""Canvas navigation for waveforms whose viewport is a QScrollArea."""
|
||||
def scroll_area(self):
|
||||
parent = self.parentWidget()
|
||||
while parent is not None and not isinstance(parent, QScrollArea):
|
||||
parent = parent.parentWidget()
|
||||
return parent
|
||||
|
||||
def _navigation_zoom(self, factor, vertical, position=None):
|
||||
scroll = self.scroll_area()
|
||||
size = self.height() if vertical else self.width()
|
||||
if position is not None:
|
||||
anchor = position.y() if vertical else position.x()
|
||||
elif scroll is not None:
|
||||
bar = scroll.verticalScrollBar() if vertical else scroll.horizontalScrollBar()
|
||||
anchor = bar.value() + bar.pageStep() / 2
|
||||
else:
|
||||
anchor = size / 2
|
||||
self.zoom_dragged.emit('y' if vertical else 'x', factor, anchor / max(1, size))
|
||||
|
||||
def _navigation_pan(self, fraction):
|
||||
scroll = self.scroll_area()
|
||||
if scroll is not None:
|
||||
bar = scroll.horizontalScrollBar()
|
||||
bar.setValue(round(bar.value() + fraction * bar.pageStep()))
|
||||
self.navigation_panned()
|
||||
|
||||
def _navigation_edge(self, end):
|
||||
scroll = self.scroll_area()
|
||||
if scroll is not None:
|
||||
bar = scroll.horizontalScrollBar()
|
||||
bar.setValue(bar.maximum() if end else bar.minimum())
|
||||
self.navigation_panned()
|
||||
|
||||
def navigation_panned(self):
|
||||
pass
|
||||
|
||||
def begin_pan(self, event):
|
||||
self.setFocus(Qt.MouseFocusReason)
|
||||
self._pan_position = event.globalPosition() if hasattr(event, 'globalPosition') else event.globalPos()
|
||||
self.setCursor(Qt.ClosedHandCursor)
|
||||
|
||||
def move_pan(self, event):
|
||||
previous = getattr(self, '_pan_position', None)
|
||||
if previous is None:
|
||||
return
|
||||
position = event.globalPosition() if hasattr(event, 'globalPosition') else event.globalPos()
|
||||
delta = position - previous
|
||||
self._pan_position = position
|
||||
scroll = self.scroll_area()
|
||||
if scroll is not None:
|
||||
for bar, amount in ((scroll.horizontalScrollBar(), delta.x()), (scroll.verticalScrollBar(), delta.y())):
|
||||
bar.setValue(round(bar.value() - amount))
|
||||
if delta.x():
|
||||
self.navigation_panned()
|
||||
|
||||
def end_pan(self, event):
|
||||
self.move_pan(event)
|
||||
self._pan_position = None
|
||||
self.unsetCursor()
|
||||
|
||||
Reference in New Issue
Block a user