1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2025-03-10 05:34:36 +00:00

Fix view resetting when selecting reference only.

* Needed to ignore the scrollbar changes in the disabled
panel, sine a null pixmap would reset the bars to 0 and affect
the selected viewer.
* Keep view as same scale accross entries from the same group.
This commit is contained in:
glubsy 2020-06-24 17:12:59 +02:00
parent 011939f5ee
commit 9f15139d5f
2 changed files with 109 additions and 82 deletions

View File

@ -83,7 +83,7 @@ class DetailsDialog(DetailsDialogBase):
# self.horizontalLayout.setColumnStretch(3,0) # self.horizontalLayout.setColumnStretch(3,0)
self.horizontalLayout.setSpacing(1) self.horizontalLayout.setSpacing(1)
self.selectedImageViewer = QWidgetImageViewer(self, "selectedImage") self.selectedImageViewer = ScrollAreaImageViewer(self, "selectedImage")
# self.selectedImage = QLabel(self) # self.selectedImage = QLabel(self)
# sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
# sizePolicy.setHorizontalStretch(0) # sizePolicy.setHorizontalStretch(0)
@ -151,7 +151,7 @@ class DetailsDialog(DetailsDialogBase):
self.horizontalLayout.addWidget(self.verticalToolBar, 1, 1, 1, 1, Qt.AlignCenter) self.horizontalLayout.addWidget(self.verticalToolBar, 1, 1, 1, 1, Qt.AlignCenter)
self.referenceImageViewer = QWidgetImageViewer(self, "referenceImage") self.referenceImageViewer = ScrollAreaImageViewer(self, "referenceImage")
# self.referenceImage = QLabel(self) # self.referenceImage = QLabel(self)
# sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
# sizePolicy.setHorizontalStretch(0) # sizePolicy.setHorizontalStretch(0)
@ -219,7 +219,7 @@ class DetailsDialog(DetailsDialogBase):
def _update(self): def _update(self):
if not self.app.model.selected_dupes: if not self.app.model.selected_dupes:
# No item from the model, disable and clear everything. # No item from the model, disable and clear everything.
self.vController.clear_all() self.vController.resetViewersState()
return return
dupe = self.app.model.selected_dupes[0] dupe = self.app.model.selected_dupes[0]
group = self.app.model.results.get_group_of_duplicate(dupe) group = self.app.model.results.get_group_of_duplicate(dupe)

View File

@ -43,6 +43,7 @@ class BaseController(QObject):
if group != self.cached_group: if group != self.cached_group:
same_group = False same_group = False
self.resetState() self.resetState()
# self.current_scale = 1.0
self.cached_group = group self.cached_group = group
@ -51,70 +52,57 @@ class BaseController(QObject):
self.referencePixmap = QPixmap() self.referencePixmap = QPixmap()
self.scaledReferencePixmap = QPixmap() self.scaledReferencePixmap = QPixmap()
self.parent.buttonImgSwap.setEnabled(False) self.parent.buttonImgSwap.setEnabled(False)
# disable the blank widget. self.parent.buttonNormalSize.setEnabled(True)
self.referenceViewer.setImage(self.referencePixmap)
else: else:
self.referencePixmap = QPixmap(str(ref.path)) self.referencePixmap = QPixmap(str(ref.path))
self.parent.buttonImgSwap.setEnabled(True) self.parent.buttonImgSwap.setEnabled(True)
self.parent.buttonNormalSize.setEnabled(True)
self.updateBothImages(same_group) self.updateBothImages(same_group)
self.centerViews(same_group and self.referencePixmap.isNull())
def updateBothImages(self, same_group=False): def updateBothImages(self, same_group=False):
ignore_update = self.referencePixmap.isNull()
if ignore_update:
self.selectedViewer.ignore_signal = True
selected_size = self._updateImage( selected_size = self._updateImage(
self.selectedPixmap, self.scaledSelectedPixmap, self.selectedViewer, None, same_group) self.selectedPixmap, self.scaledSelectedPixmap,
self.selectedViewer, None, same_group)
# the SelectedImageViewer widget sometimes ends up being bigger # the SelectedImageViewer widget sometimes ends up being bigger
# than the ReferenceImageViewer by one pixel, which distorts the # than the ReferenceImageViewer by one pixel, which distorts the
# scaled down pixmap for the reference, hence we'll reuse its size here. # scaled down pixmap for the reference, hence we'll reuse its size here.
self._updateImage(
self.referencePixmap, self.scaledReferencePixmap, self.referenceViewer, selected_size, same_group)
self._updateImage(
self.referencePixmap, self.scaledReferencePixmap,
self.referenceViewer, selected_size, same_group)
if ignore_update:
self.selectedViewer.ignore_signal = False
def _updateImage(self, pixmap, scaledpixmap, viewer, target_size=None, same_group=False): def _updateImage(self, pixmap, scaledpixmap, viewer, target_size=None, same_group=False):
# If not same_group, we need full update""" # If not same_group, we need full update"""
if not pixmap.isNull(): if pixmap.isNull():
target_size = viewer.size() # disable the blank widget.
if not self.bestFit: viewer.setImage(pixmap)
if same_group: return
viewer.setImage(pixmap)
viewer.centerViewAndUpdate() target_size = viewer.size()
return target_size if not viewer.bestFit:
# zoomed in state, expand if same_group:
scaledpixmap = pixmap.scaled( viewer.setImage(pixmap)
target_size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) return target_size
else: # zoomed in state, expand
# best fit, keep ratio always scaledpixmap = pixmap.scaled(
scaledpixmap = pixmap.scaled( target_size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)
target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) else:
viewer.setImage(scaledpixmap) # best fit, keep ratio always
viewer.centerViewAndUpdate() scaledpixmap = pixmap.scaled(
target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
viewer.setImage(scaledpixmap)
return target_size return target_size
@pyqtSlot(float)
def scaleImagesBy(self, factor):
"""Compute new scale from factor and scale."""
self.current_scale *= factor
self.selectedViewer.scaleBy(factor)
self.referenceViewer.scaleBy(factor)
self.parent.buttonZoomIn.setEnabled(self.current_scale < MAX_SCALE)
self.parent.buttonZoomOut.setEnabled(self.current_scale > MIN_SCALE)
self.parent.buttonBestFit.setEnabled(self.bestFit is False)
self.parent.buttonNormalSize.setEnabled(self.current_scale != 1.0)
@pyqtSlot(float)
def scaleImagesAt(self, scale):
"""Scale at a pre-computed scale."""
self.current_scale = scale
self.selectedViewer.scaleAt(scale)
self.referenceViewer.scaleAt(scale)
self.parent.buttonZoomIn.setEnabled(self.current_scale < MAX_SCALE)
self.parent.buttonZoomOut.setEnabled(self.current_scale > MIN_SCALE)
self.parent.buttonBestFit.setEnabled(self.bestFit is False)
self.parent.buttonNormalSize.setEnabled(self.current_scale != 1.0)
def resetState(self): def resetState(self):
"""Only called when the group of dupes has changed""" """Only called when the group of dupes has changed. We reset our
controller internal state and buttons, center view on viewers."""
self.selectedPixmap = QPixmap() self.selectedPixmap = QPixmap()
self.scaledSelectedPixmap = QPixmap() self.scaledSelectedPixmap = QPixmap()
self.referencePixmap = QPixmap() self.referencePixmap = QPixmap()
@ -123,24 +111,60 @@ class BaseController(QObject):
self.current_scale = 1.0 self.current_scale = 1.0
self.selectedViewer.resetCenter() self.selectedViewer.resetCenter()
self.referenceViewer.resetCenter() self.referenceViewer.resetCenter()
self.centerViews()
self.selectedViewer.centerViewAndUpdate() #FIXME move buttons somwhere else
self.referenceViewer.centerViewAndUpdate()
self.parent.buttonZoomIn.setEnabled(False) self.parent.buttonZoomIn.setEnabled(False)
self.parent.buttonZoomOut.setEnabled(False) self.parent.buttonZoomOut.setEnabled(False)
self.parent.buttonBestFit.setEnabled(False) # active mode by default self.parent.buttonBestFit.setEnabled(False) # active mode by default
self.parent.buttonNormalSize.setEnabled(True) self.parent.buttonNormalSize.setEnabled(True)
def clear_all(self): def resetViewersState(self):
"""No item from the model, disable and clear everything.""" """No item from the model, disable and clear everything."""
self.resetState() # only called by the details dialog
self.selectedPixmap = QPixmap()
self.scaledSelectedPixmap = QPixmap()
self.referencePixmap = QPixmap()
self.scaledReferencePixmap = QPixmap()
self.setBestFit(True)
self.current_scale = 1.0
self.selectedViewer.resetCenter()
self.referenceViewer.resetCenter()
self.centerViews()
#FIXME move buttons somwhere else
self.parent.buttonZoomIn.setEnabled(False)
self.parent.buttonZoomOut.setEnabled(False)
self.parent.buttonBestFit.setEnabled(False) # active mode by default
self.parent.buttonImgSwap.setEnabled(False)
self.parent.buttonNormalSize.setEnabled(False)
self.selectedViewer.setImage(self.selectedPixmap) # null self.selectedViewer.setImage(self.selectedPixmap) # null
self.selectedViewer.setEnabled(False) self.selectedViewer.setEnabled(False)
self.referenceViewer.setImage(self.referencePixmap) # null self.referenceViewer.setImage(self.referencePixmap) # null
self.referenceViewer.setEnabled(False) self.referenceViewer.setEnabled(False)
self.parent.buttonImgSwap.setEnabled(False)
self.parent.buttonNormalSize.setEnabled(False) @pyqtSlot(float)
def scaleImagesBy(self, factor):
"""Compute new scale from factor and scale."""
self.current_scale *= factor
self.selectedViewer.scaleBy(factor)
self.referenceViewer.scaleBy(factor)
self.updateButtons()
@pyqtSlot(float)
def scaleImagesAt(self, scale):
"""Scale at a pre-computed scale."""
self.current_scale = scale
self.selectedViewer.scaleAt(scale)
self.referenceViewer.scaleAt(scale)
self.updateButtons()
def updateButtons(self):
self.parent.buttonZoomIn.setEnabled(self.current_scale < MAX_SCALE)
self.parent.buttonZoomOut.setEnabled(self.current_scale > MIN_SCALE)
self.parent.buttonBestFit.setEnabled(self.bestFit is False)
self.parent.buttonNormalSize.setEnabled(round(self.current_scale, 1) != 1.0)
@pyqtSlot() @pyqtSlot()
def ScaleToBestFit(self): def ScaleToBestFit(self):
@ -156,6 +180,7 @@ class BaseController(QObject):
target_size = self._updateImage(self.selectedPixmap, self.scaledSelectedPixmap, self.selectedViewer, None, True) target_size = self._updateImage(self.selectedPixmap, self.scaledSelectedPixmap, self.selectedViewer, None, True)
self._updateImage(self.referencePixmap, self.scaledReferencePixmap, self.referenceViewer, target_size, True) self._updateImage(self.referencePixmap, self.scaledReferencePixmap, self.referenceViewer, target_size, True)
self.centerViews()
self.parent.buttonBestFit.setEnabled(False) self.parent.buttonBestFit.setEnabled(False)
self.parent.buttonZoomOut.setEnabled(False) self.parent.buttonZoomOut.setEnabled(False)
@ -175,8 +200,7 @@ class BaseController(QObject):
self.selectedViewer.setImage(self.selectedPixmap) self.selectedViewer.setImage(self.selectedPixmap)
self.referenceViewer.setImage(self.referencePixmap) self.referenceViewer.setImage(self.referencePixmap)
self.selectedViewer.centerViewAndUpdate() self.centerViews()
self.referenceViewer.centerViewAndUpdate()
self.selectedViewer.scaleToNormalSize() self.selectedViewer.scaleToNormalSize()
self.referenceViewer.scaleToNormalSize() self.referenceViewer.scaleToNormalSize()
@ -186,6 +210,12 @@ class BaseController(QObject):
self.parent.buttonZoomOut.setEnabled(True) self.parent.buttonZoomOut.setEnabled(True)
self.parent.buttonBestFit.setEnabled(True) self.parent.buttonBestFit.setEnabled(True)
def centerViews(self, only_selected=False):
self.selectedViewer.centerViewAndUpdate()
if only_selected:
return
self.referenceViewer.centerViewAndUpdate()
class QWidgetController(BaseController): class QWidgetController(BaseController):
"""Specialized version for QWidget-based viewers.""" """Specialized version for QWidget-based viewers."""
@ -205,11 +235,6 @@ class QWidgetController(BaseController):
self.selectedViewer.centerViewAndUpdate() self.selectedViewer.centerViewAndUpdate()
self.referenceViewer.centerViewAndUpdate() self.referenceViewer.centerViewAndUpdate()
def _updateImage(self, pixmap, scaledpixmap, viewer, target_size, same_group):
#FIXME might not need this at all, REMOVE?
super()._updateImage(pixmap, scaledpixmap, viewer, target_size, same_group)
viewer.update()
class ScrollAreaController(BaseController): class ScrollAreaController(BaseController):
"""Specialized version fro QLabel-based viewers.""" """Specialized version fro QLabel-based viewers."""
@ -221,6 +246,15 @@ class ScrollAreaController(BaseController):
self.selectedViewer.connectScrollBars() self.selectedViewer.connectScrollBars()
self.referenceViewer.connectScrollBars() self.referenceViewer.connectScrollBars()
def updateBothImages(self, same_group=False):
super().updateBothImages(same_group)
if not self.referenceViewer.isEnabled():
return
self.referenceViewer._horizontalScrollBar.setValue(
self.selectedViewer._horizontalScrollBar.value())
self.referenceViewer._verticalScrollBar.setValue(
self.selectedViewer._verticalScrollBar.value())
@pyqtSlot(QPoint) @pyqtSlot(QPoint)
def onDraggedMouse(self, delta): def onDraggedMouse(self, delta):
self.selectedViewer.ignore_signal = True self.selectedViewer.ignore_signal = True
@ -238,13 +272,6 @@ class ScrollAreaController(BaseController):
self.referenceViewer.setCachedPixmap() self.referenceViewer.setCachedPixmap()
self.selectedViewer.setCachedPixmap() self.selectedViewer.setCachedPixmap()
@pyqtSlot()
def syncCenters(self):
if self.sender() is self.referenceViewer:
self.selectedViewer.setCenter(self.referenceViewer.getCenter())
else:
self.referenceViewer.setCenter(self.selectedViewer.getCenter())
@pyqtSlot(float, QPointF) @pyqtSlot(float, QPointF)
def onMouseWheel(self, scale, delta): def onMouseWheel(self, scale, delta):
self.scaleImagesAt(scale) self.scaleImagesAt(scale)
@ -285,6 +312,7 @@ class ScrollAreaController(BaseController):
self.referenceViewer.toggleScrollBars() self.referenceViewer.toggleScrollBars()
class GraphicsViewController(BaseController): class GraphicsViewController(BaseController):
"""Specialized version fro QGraphicsView-based viewers.""" """Specialized version fro QGraphicsView-based viewers."""
def __init__(self, selectedViewer, referenceViewer, parent): def __init__(self, selectedViewer, referenceViewer, parent):
@ -366,7 +394,7 @@ class QWidgetImageViewer(QWidget):
self.disconnectMouseSignals() self.disconnectMouseSignals()
def mousePressEvent(self, event): def mousePressEvent(self, event):
if self.bestFit: if self.bestFit or not self.isEnabled():
event.ignore() event.ignore()
return return
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton:
@ -382,7 +410,7 @@ class QWidgetImageViewer(QWidget):
event.accept() event.accept()
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):
if self.bestFit: if self.bestFit or not self.isEnabled():
event.ignore() event.ignore()
return return
@ -394,7 +422,7 @@ class QWidgetImageViewer(QWidget):
self.update() self.update()
def mouseReleaseEvent(self, event): def mouseReleaseEvent(self, event):
if self.bestFit: if self.bestFit or not self.isEnabled():
event.ignore() event.ignore()
return return
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton:
@ -404,7 +432,7 @@ class QWidgetImageViewer(QWidget):
self.setMouseTracking(False) self.setMouseTracking(False)
def wheelEvent(self, event): def wheelEvent(self, event):
if self.bestFit: if self.bestFit or not self.isEnabled():
event.ignore() event.ignore()
return return
@ -421,8 +449,9 @@ class QWidgetImageViewer(QWidget):
if pixmap.isNull(): if pixmap.isNull():
if not self._pixmap.isNull(): if not self._pixmap.isNull():
self._pixmap = pixmap self._pixmap = pixmap
self.disconnectMouseSignals() self.disconnectMouseSignals()
self.update() self.setEnabled(False)
self.update()
return return
elif not self.isEnabled(): elif not self.isEnabled():
self.setEnabled(True) self.setEnabled(True)
@ -644,10 +673,9 @@ class ScrollAreaImageViewer(QScrollArea):
if pixmap.isNull(): if pixmap.isNull():
self.setEnabled(False) self.setEnabled(False)
self.disconnectMouseSignals() self.disconnectMouseSignals()
else: elif not self.isEnabled():
if not self.isEnabled(): self.setEnabled(True)
self.setEnabled(True) self.connectMouseSignals()
self.connectMouseSignals()
def centerViewAndUpdate(self): def centerViewAndUpdate(self):
self._rect = self.label.rect() self._rect = self.label.rect()
@ -755,10 +783,9 @@ class ScrollAreaImageViewer(QScrollArea):
def resetCenter(self): def resetCenter(self):
""" Resets origin """ """ Resets origin """
self._mousePanningDelta = QPoint() self._mousePanningDelta = QPoint()
# self.label._mousePanningDelta = self._mousePanningDelta
self._current_scale = 1.0 self._current_scale = 1.0
# self.scaleBy(1.0) # self.scaleBy(1.0)
# self.label.update() # already called in scaleBy² # self.label.update() # already called in scaleBy
def setCenter(self, point): def setCenter(self, point):
self._lastMouseClickPoint = point self._lastMouseClickPoint = point