scanwidget: changes as of edaba53

This commit is contained in:
Robert Jördens 2016-03-12 12:42:33 +01:00
parent 78f2706aa8
commit 5e7eff6c4d
1 changed files with 45 additions and 74 deletions

View File

@ -288,16 +288,33 @@ class ScanSlider(QtWidgets.QSlider):
# real (Sliders) => pixel (one pixel movement of sliders would increment by X) # real (Sliders) => pixel (one pixel movement of sliders would increment by X)
# => range (minimum granularity that sliders understand). # => range (minimum granularity that sliders understand).
class ScanProxy(QtCore.QObject): class ScanWidget(QtWidgets.QWidget):
sigStartMoved = QtCore.pyqtSignal(float) sigStartMoved = QtCore.pyqtSignal(float)
sigStopMoved = QtCore.pyqtSignal(float) sigStopMoved = QtCore.pyqtSignal(float)
sigNumChanged = QtCore.pyqtSignal(int) sigNumChanged = QtCore.pyqtSignal(int)
def __init__(self, slider, axis, zoomMargin, dynamicRange, zoomFactor): def __init__(self, zoomFactor=1.05, zoomMargin=.1, dynamicRange=1e9):
QtCore.QObject.__init__(self) QtWidgets.QWidget.__init__(self)
self.axis = axis self.slider = slider = ScanSlider()
self.axis = axis = ScanAxis()
axis.proxy = self axis.proxy = self
self.slider = slider
# Layout.
layout = QtWidgets.QVBoxLayout()
layout.setSpacing(0)
layout.addWidget(axis)
layout.addWidget(slider)
self.setLayout(layout)
# Context menu entries
self.menu = QtWidgets.QMenu(self)
viewRangeAct = QtWidgets.QAction("&View Range", self)
viewRangeAct.triggered.connect(self.viewRange)
self.menu.addAction(viewRangeAct)
snapRangeAct = QtWidgets.QAction("&Snap Range", self)
snapRangeAct.triggered.connect(self.snapRange)
self.menu.addAction(snapRangeAct)
self.realStart = -1. self.realStart = -1.
self.realStop = 1. self.realStop = 1.
self.numPoints = 11 self.numPoints = 11
@ -320,6 +337,9 @@ class ScanProxy(QtCore.QObject):
slider.sigStopMoved.connect(self.handleStopMoved) slider.sigStopMoved.connect(self.handleStopMoved)
slider.sigStartMoved.connect(self.handleStartMoved) slider.sigStartMoved.connect(self.handleStartMoved)
def contextMenuEvent(self, ev):
self.menu.popup(ev.globalPos())
# pixel vals for sliders: 0 to slider_width - 1 # pixel vals for sliders: 0 to slider_width - 1
def realToPixel(self, val): def realToPixel(self, val):
a, b = self.realToPixelTransform a, b = self.realToPixelTransform
@ -341,32 +361,32 @@ class ScanProxy(QtCore.QObject):
pixelVal = self.realToPixel(val) pixelVal = self.realToPixel(val)
return self.slider.pixelPosToRangeValue(pixelVal) return self.slider.pixelPosToRangeValue(pixelVal)
def moveStop(self, val): def setStop(self, val):
sliderX = self.realToRange(val) sliderX = self.realToRange(val)
self.slider.setStopPosition(sliderX) self.slider.setStopPosition(sliderX)
self.realStop = val self.realStop = val
self.axis.update() # Number of points ticks changed positions. self.axis.update() # Number of points ticks changed positions.
def moveStart(self, val): def setStart(self, val):
sliderX = self.realToRange(val) sliderX = self.realToRange(val)
self.slider.setStartPosition(sliderX) self.slider.setStartPosition(sliderX)
self.realStart = val self.realStart = val
self.axis.update() self.axis.update()
def setNumPoints(self, val):
self.numPoints = val
self.axis.update()
def handleStopMoved(self, rangeVal): def handleStopMoved(self, rangeVal):
# FIXME: this relies on the event being fed back and ending up calling # FIXME: this relies on the event being fed back and ending up calling
# moveStop() # setStop()
self.sigStopMoved.emit(self.rangeToReal(rangeVal)) self.sigStopMoved.emit(self.rangeToReal(rangeVal))
def handleStartMoved(self, rangeVal): def handleStartMoved(self, rangeVal):
# FIXME: this relies on the event being fed back and ending up calling # FIXME: this relies on the event being fed back and ending up calling
# moveStart() # setStart()
self.sigStartMoved.emit(self.rangeToReal(rangeVal)) self.sigStartMoved.emit(self.rangeToReal(rangeVal))
def setNumPoints(self, val):
self.numPoints = val
self.axis.update()
def handleZoom(self, zoomFactor, mouseXPos): def handleZoom(self, zoomFactor, mouseXPos):
newScale = self.realToPixelTransform[1] * zoomFactor newScale = self.realToPixelTransform[1] * zoomFactor
refReal = self.pixelToReal(mouseXPos) refReal = self.pixelToReal(mouseXPos)
@ -375,8 +395,8 @@ class ScanProxy(QtCore.QObject):
if zoomFactor > 1 and abs(newZero) > self.dynamicRange: if zoomFactor > 1 and abs(newZero) > self.dynamicRange:
return return
self.realToPixelTransform = newLeft, newScale self.realToPixelTransform = newLeft, newScale
self.moveStop(self.realStop) self.setStop(self.realStop)
self.moveStart(self.realStart) self.setStart(self.realStart)
def viewRange(self): def viewRange(self):
newScale = self.slider.effectiveWidth()/abs( newScale = self.slider.effectiveWidth()/abs(
@ -387,8 +407,8 @@ class ScanProxy(QtCore.QObject):
newScale = min(newScale, self.dynamicRange/abs(newCenter)) newScale = min(newScale, self.dynamicRange/abs(newCenter))
newLeft = newCenter - self.slider.effectiveWidth()/2/newScale newLeft = newCenter - self.slider.effectiveWidth()/2/newScale
self.realToPixelTransform = newLeft, newScale self.realToPixelTransform = newLeft, newScale
self.moveStop(self.realStop) self.setStop(self.realStop)
self.moveStart(self.realStart) self.setStart(self.realStart)
self.axis.update() # Axis normally takes care to update itself during self.axis.update() # Axis normally takes care to update itself during
# zoom. In this code path however, the zoom didn't arrive via the axis # zoom. In this code path however, the zoom didn't arrive via the axis
# widget, so we need to notify manually. # widget, so we need to notify manually.
@ -401,8 +421,8 @@ class ScanProxy(QtCore.QObject):
def viewRangeInit(self): def viewRangeInit(self):
currRangeReal = abs(self.realStop - self.realStart) currRangeReal = abs(self.realStop - self.realStart)
if currRangeReal == 0: if currRangeReal == 0:
self.moveStop(self.realStop) self.setStop(self.realStop)
self.moveStart(self.realStart) self.setStart(self.realStart)
# Ill-formed snap range- move the sliders anyway, # Ill-formed snap range- move the sliders anyway,
# because we arrived here during widget # because we arrived here during widget
# initialization, where the slider positions are likely invalid. # initialization, where the slider positions are likely invalid.
@ -426,7 +446,7 @@ class ScanProxy(QtCore.QObject):
# consequence of ValueChanged signal in spinboxes. The slider widget # consequence of ValueChanged signal in spinboxes. The slider widget
# has guards against recursive signals in setSpan(). # has guards against recursive signals in setSpan().
# FIXME: this relies on the events being fed back and ending up # FIXME: this relies on the events being fed back and ending up
# calling moveStart() and moveStop() # calling setStart() and setStop()
self.sigStopMoved.emit(newStop) self.sigStopMoved.emit(newStop)
self.sigStartMoved.emit(newStart) self.sigStartMoved.emit(newStart)
@ -444,7 +464,8 @@ class ScanProxy(QtCore.QObject):
# calling setNumPoints() # calling setNumPoints()
self.sigNumChanged.emit(self.numPoints + z) self.sigNumChanged.emit(self.numPoints + z)
self.axis.update() self.axis.update()
else: ev.accept()
elif ev.modifiers() & QtCore.Qt.ControlModifier:
z = self.zoomFactor**(y / 120.) z = self.zoomFactor**(y / 120.)
# Remove the slider-handle shift correction, b/c none of the # Remove the slider-handle shift correction, b/c none of the
# other widgets know about it. If we have the mouse directly # other widgets know about it. If we have the mouse directly
@ -453,6 +474,8 @@ class ScanProxy(QtCore.QObject):
# pixel-space, not slider pixel-space. # pixel-space, not slider pixel-space.
self.handleZoom(z, ev.x() - self.slider.handleWidth()/2) self.handleZoom(z, ev.x() - self.slider.handleWidth()/2)
ev.accept() ev.accept()
else:
ev.ignore()
def eventFilter(self, obj, ev): def eventFilter(self, obj, ev):
if ev.type() == QtCore.QEvent.Wheel: if ev.type() == QtCore.QEvent.Wheel:
@ -490,55 +513,3 @@ class ScanProxy(QtCore.QObject):
# confident that the new slider position will still map to the # confident that the new slider position will still map to the
# same positions in the new axis-space. # same positions in the new axis-space.
return False return False
class ScanWidget(QtWidgets.QWidget):
sigStartMoved = QtCore.pyqtSignal(float)
sigStopMoved = QtCore.pyqtSignal(float)
sigNumChanged = QtCore.pyqtSignal(int)
def __init__(self, zoomFactor=1.05, zoomMargin=.1, dynamicRange=1e9):
QtWidgets.QWidget.__init__(self)
self.slider = slider = ScanSlider()
self.axis = axis = ScanAxis()
self.proxy = ScanProxy(slider, axis, zoomMargin, dynamicRange,
zoomFactor)
# Layout.
layout = QtWidgets.QVBoxLayout()
layout.setSpacing(0)
layout.addWidget(axis)
layout.addWidget(slider)
self.setLayout(layout)
# Connect signals (minus context menu)
self.proxy.sigStopMoved.connect(self.sigStopMoved)
self.proxy.sigStartMoved.connect(self.sigStartMoved)
self.proxy.sigNumChanged.connect(self.sigNumChanged)
# Context menu entries
self.menu = QtWidgets.QMenu(self)
viewRangeAct = QtWidgets.QAction("&View Range", self)
viewRangeAct.triggered.connect(self.viewRange)
self.menu.addAction(viewRangeAct)
snapRangeAct = QtWidgets.QAction("&Snap Range", self)
snapRangeAct.triggered.connect(self.snapRange)
self.menu.addAction(snapRangeAct)
def setStop(self, val):
self.proxy.moveStop(val)
def setStart(self, val):
self.proxy.moveStart(val)
def setNumPoints(self, val):
self.proxy.setNumPoints(val)
def viewRange(self):
self.proxy.viewRange()
def snapRange(self):
self.proxy.snapRange()
def contextMenuEvent(self, ev):
self.menu.popup(ev.globalPos())