Files
templates/python/set_devices/qt_ports/plot_navigation.py

113 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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()