From 6213d506702fb3fbf5fdf9e5365121457b6bff28 Mon Sep 17 00:00:00 2001 From: glubsy Date: Thu, 16 Jul 2020 22:31:54 +0200 Subject: [PATCH] Squashed commit of the following: commit ac941037ff51158b64daa65c244df26346af10cf Author: glubsy Date: Thu Jul 16 22:21:24 2020 +0200 Fix resize of top frame not updating scaled pixmap * Also limit viewing features such as zoom levels when files have different dimensions * GraphicsViewImageViewer is still a bit buggy: the scrollbars are toggled on when the pixmap is null in the reference viewer (we do not use that class right anyway) commit 733b3b0ed4fbd6de908c968402af03879df3336f Author: glubsy Date: Thu Jul 16 01:31:24 2020 +0200 Prevent zoom for images of differing dimensions * If images are not the same size, prevent zooming features from being used by disabling the normal size button, only enable swap commit 9168d72f38faaf0a12230cd544f14190cd29fca4 Author: glubsy Date: Wed Jul 15 22:47:32 2020 +0200 Update preferences on show(), not in constructor * If the dialog window shouldn't have a titlebar during construction, update accordingly only when showing to fix Windows displaying a window without titlebar on first show * Only save geometry if the window is floating. Otherwise geometry while docked is saved whih gives weird results on subsequent starts, since it may be floating by default anyway (at least on Linux where titlebar being disabled is allowed while floating) * Vertical title bar doesn't seem to work on Windows, add note in preferences dialog commit 75621cc816120597f493e0debc6d88e2e0bbd30a Author: glubsy Date: Wed Jul 15 22:04:19 2020 +0200 Prevent Windows from floating if no decoration * Windows users cannot move a window which has no native decorations. Toggling a dock widget's titlebar off also removes native decorations on a floating window. Until we implement a replacement titlebar by overriding paintEvents, simply force the floating window to go back to docked state after we toggled the titlebar off. commit 3c816b2f11ddc66a78cdc6327ee102df46d1a552 Author: glubsy Date: Wed Jul 15 21:43:01 2020 +0200 Fix computing and setting offset to 0 for tableview commit 85d6e05cd406b999e8f6ae421a9746a0c9f146bb Merge: 66127d02 3eddeb6a Author: glubsy Date: Wed Jul 15 21:25:44 2020 +0200 Merge branch 'dockable_windows' into details_dialog_improvements_dev commit 66127d025e9a497ee13126f955166946acdb35a8 Author: glubsy Date: Wed Jul 15 20:22:13 2020 +0200 Add credit for icons used, upscale exchange icon * Jason Cho gave his express permission to use the icon (it was made 10 years ago and he doesn't have the source files anymore) * Used waifu2x to upscale the icon * Used GIMP to draw dark outline around the icon * Source files are included commit 58c675d1fa90a7247233d9887a460cf5a8e4cbf5 Author: glubsy Date: Wed Jul 15 05:25:47 2020 +0200 Add custom icons * Use custom icons on platforms which do not provide theme * Old zoom icons credits to "schollidesign" from icon pack Office and Entertainment (GPL licence). * Exchange icon credit to Jason Cho (Unknown license). * Use hack to resize viewers on first show() as well commit 95b8406c7b97aab170d127b466ff506b724def3c Author: glubsy Date: Wed Jul 15 04:14:24 2020 +0200 Fix scrollbar displayed while splitter maxed out * For some reason the table's height is a few pixel longer on Windows so we work around the issue by adding a small offset to the maximum height hint. * No idea about MacOS yet but this might need the same treatment. commit 3eddeb6aebc99126e62eb05af60333ba3bd22e82 Author: glubsy Date: Tue Jul 14 17:37:48 2020 +0200 Fix ME/SE details dialogs, add preferences * Fix ME and SE versions of details dialog not displaying their content properly after change to QDockWidget * Add option to toggle titlebar and orientation of titlebar in preferences dialog * Fix setting layout on PE details dialog window while layout already set, by removing the self (parent) reference in constructing the QSplitter commit 56912a71084415eac2f447650279d833d9857686 Author: glubsy Date: Mon Jul 13 05:06:04 2020 +0200 Make details dialog dockable --- images/exchange.icns | Bin 0 -> 1774 bytes images/exchange.ico | Bin 0 -> 4286 bytes images/exchange.png | Bin 0 -> 797 bytes images/exchange_purple.png | Bin 0 -> 685 bytes images/exchange_purple_upscaled.png | Bin 0 -> 9042 bytes images/exchange_purple_waifu_s4_tta8.png | Bin 0 -> 7118 bytes images/exchange_purple_waifu_s4_tta8.xcf | Bin 0 -> 18409 bytes images/exchange_waifu_s4_tta8.png | Bin 0 -> 5589 bytes images/old_zoom_best_fit.png | Bin 0 -> 12499 bytes images/old_zoom_in.png | Bin 0 -> 11564 bytes images/old_zoom_original.png | Bin 0 -> 12189 bytes images/old_zoom_out.png | Bin 0 -> 11522 bytes qt/app.py | 9 +- qt/details_dialog.py | 30 +++++- qt/dg.qrc | 5 + qt/me/details_dialog.py | 5 +- qt/pe/details_dialog.py | 67 ++++++++----- qt/pe/image_viewer.py | 115 +++++++++++++++++++---- qt/preferences.py | 6 ++ qt/preferences_dialog.py | 19 +++- qt/se/details_dialog.py | 5 +- qtlib/about_box.py | 17 +++- 22 files changed, 226 insertions(+), 52 deletions(-) create mode 100644 images/exchange.icns create mode 100644 images/exchange.ico create mode 100644 images/exchange.png create mode 100644 images/exchange_purple.png create mode 100644 images/exchange_purple_upscaled.png create mode 100644 images/exchange_purple_waifu_s4_tta8.png create mode 100644 images/exchange_purple_waifu_s4_tta8.xcf create mode 100644 images/exchange_waifu_s4_tta8.png create mode 100644 images/old_zoom_best_fit.png create mode 100644 images/old_zoom_in.png create mode 100644 images/old_zoom_original.png create mode 100644 images/old_zoom_out.png diff --git a/images/exchange.icns b/images/exchange.icns new file mode 100644 index 0000000000000000000000000000000000000000..f93828b4d89a7f1935e1947eb9e01e03af844af7 GIT binary patch literal 1774 zcmeHEJ8s)R5FI-~;F3q+5eTPA>2gaRfj}yMAs~G)q9lJ}OQPL5Zd4lxz$5SoJVCH0 z2-u|@znNWGvZ)AgYh;1lc{A_Ln_cqo>)AJ=Pk#^ zHH`r6T!6UBmm`isLqk9-UsQ8!s zfARbO$0uJ-kBL6+(OXu=+tpQhLRW0RS5qxIiS?W##~W-ijjzrJPk X%r{Jrl!c^s`E?e!vA4e}ZcU#6q^z&A literal 0 HcmV?d00001 diff --git a/images/exchange.ico b/images/exchange.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf5226c9dfb6ff168b604852af86c37e6b714d32 GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/images/exchange_purple_waifu_s4_tta8.png b/images/exchange_purple_waifu_s4_tta8.png new file mode 100644 index 0000000000000000000000000000000000000000..21bbcf531b967498e845d06f0034d2391d6746bd GIT binary patch literal 7118 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 literal 0 HcmV?d00001 diff --git a/images/old_zoom_best_fit.png b/images/old_zoom_best_fit.png new file mode 100644 index 0000000000000000000000000000000000000000..444d4dcf1590ddda34d50cea3e6b11ee2bb02b6d GIT binary patch literal 12499 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 literal 0 HcmV?d00001 diff --git a/images/old_zoom_in.png b/images/old_zoom_in.png new file mode 100644 index 0000000000000000000000000000000000000000..fbcbe2c169fff1a7a348ee6b4a15cd1c67251f41 GIT binary patch literal 11564 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 I-a7LC044CYApigX literal 0 HcmV?d00001 diff --git a/images/old_zoom_out.png b/images/old_zoom_out.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e84c98e160ebe86263fc9658e808f43d7b854e GIT binary patch literal 11522 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 P%7DDAvP`A4Y4HC6euIu3 literal 0 HcmV?d00001 diff --git a/qt/app.py b/qt/app.py index ac59dd0a..7a5b60f6 100644 --- a/qt/app.py +++ b/qt/app.py @@ -7,7 +7,7 @@ import sys import os.path as op -from PyQt5.QtCore import QTimer, QObject, QUrl, pyqtSignal +from PyQt5.QtCore import QTimer, QObject, QUrl, pyqtSignal, Qt from PyQt5.QtGui import QDesktopServices from PyQt5.QtWidgets import QApplication, QFileDialog, QDialog, QMessageBox @@ -54,11 +54,11 @@ class DupeGuru(QObject): def _setup(self): core.pe.photo.PLAT_SPECIFIC_PHOTO_CLASS = PlatSpecificPhoto self._setupActions() + self.details_dialog = None self._update_options() self.recentResults = Recent(self, "recentResults") self.recentResults.mustOpenItem.connect(self.model.load_from) self.resultWindow = None - self.details_dialog = None self.directories_dialog = DirectoriesDialog(self) self.progress_window = ProgressWindow( self.directories_dialog, self.model.progress_window @@ -152,6 +152,9 @@ class DupeGuru(QObject): self.model.options["match_scaled"] = self.prefs.match_scaled self.model.options["picture_cache_type"] = self.prefs.picture_cache_type + if self.details_dialog: + self.details_dialog.update_options() + # --- Private def _get_details_dialog_class(self): if self.model.app_mode == AppMode.Picture: @@ -284,6 +287,8 @@ class DupeGuru(QObject): self.resultWindow.setParent(None) self.resultWindow = ResultWindow(self.directories_dialog, self) self.details_dialog = self._get_details_dialog_class()(self.resultWindow, self) + self.resultWindow.addDockWidget( + Qt.BottomDockWidgetArea, self.details_dialog) def show_results_window(self): self.showResultsWindow() diff --git a/qt/details_dialog.py b/qt/details_dialog.py index 57cc650b..7b3f07d5 100644 --- a/qt/details_dialog.py +++ b/qt/details_dialog.py @@ -7,16 +7,19 @@ # http://www.gnu.org/licenses/gpl-3.0.html from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QMainWindow +from PyQt5.QtWidgets import QDockWidget, QWidget from .details_table import DetailsModel +from hscommon.plat import ISLINUX -class DetailsDialog(QMainWindow): +class DetailsDialog(QDockWidget): def __init__(self, parent, app, **kwargs): super().__init__(parent, Qt.Tool, **kwargs) + self.parent = parent self.app = app self.model = app.model.details_panel + self.setAllowedAreas(Qt.AllDockWidgetAreas) self._setupUi() # To avoid saving uninitialized geometry on appWillSavePrefs, we track whether our dialog # has been shown. If it has, we know that our geometry should be saved. @@ -35,10 +38,31 @@ class DetailsDialog(QMainWindow): def show(self): self._shown_once = True super().show() + self.update_options() + + def update_options(self): + # This disables the title bar (if we had not set one before already) + # essentially making it a simple floating window, not dockable anymore + if not self.app.prefs.details_dialog_titlebar_enabled \ + and not self.titleBarWidget(): + self.setTitleBarWidget(QWidget()) + # Windows (and MacOS?) users cannot move a floating window which + # has not native decoration so we force it to dock for now + if not ISLINUX: + self.setFloating(False) + elif self.titleBarWidget() is not None: + # resets to the default title bar + self.setTitleBarWidget(None) + + features = self.features() + if self.app.prefs.details_dialog_vertical_titlebar: + self.setFeatures(features | QDockWidget.DockWidgetVerticalTitleBar) + elif features & QDockWidget.DockWidgetVerticalTitleBar: + self.setFeatures(features ^ QDockWidget.DockWidgetVerticalTitleBar) # --- Events def appWillSavePrefs(self): - if self._shown_once: + if self._shown_once and self.isFloating(): self.app.prefs.saveGeometry("DetailsWindowRect", self) # --- model --> view diff --git a/qt/dg.qrc b/qt/dg.qrc index 545a9806..760f2a85 100644 --- a/qt/dg.qrc +++ b/qt/dg.qrc @@ -5,5 +5,10 @@ ../images/plus_8.png ../images/minus_8.png ../qtlib/images/search_clear_13.png + ../images/exchange_purple_upscaled.png + ../images/old_zoom_in.png + ../images/old_zoom_out.png + ../images/old_zoom_original.png + ../images/old_zoom_best_fit.png diff --git a/qt/me/details_dialog.py b/qt/me/details_dialog.py index 935a34c6..ecb947d0 100644 --- a/qt/me/details_dialog.py +++ b/qt/me/details_dialog.py @@ -5,7 +5,7 @@ # http://www.gnu.org/licenses/gpl-3.0.html from PyQt5.QtCore import QSize -from PyQt5.QtWidgets import QVBoxLayout, QAbstractItemView +from PyQt5.QtWidgets import QVBoxLayout, QAbstractItemView, QWidget from hscommon.trans import trget from ..details_dialog import DetailsDialog as DetailsDialogBase @@ -27,3 +27,6 @@ class DetailsDialog(DetailsDialogBase): self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setShowGrid(False) self.verticalLayout.addWidget(self.tableView) + self.centralWidget = QWidget() + self.centralWidget.setLayout(self.verticalLayout) + self.setWidget(self.centralWidget) diff --git a/qt/pe/details_dialog.py b/qt/pe/details_dialog.py index 07ecdfcb..d96dba17 100644 --- a/qt/pe/details_dialog.py +++ b/qt/pe/details_dialog.py @@ -4,11 +4,12 @@ # which should be included with this package. The terms are also available at # http://www.gnu.org/licenses/gpl-3.0.html -from PyQt5.QtCore import Qt, QSize +from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( QAbstractItemView, QSizePolicy, QGridLayout, QSplitter, QFrame) - +from PyQt5.QtGui import QResizeEvent from hscommon.trans import trget +from hscommon.plat import ISWINDOWS from ..details_dialog import DetailsDialog as DetailsDialogBase from ..details_table import DetailsTable from .image_viewer import ( @@ -25,9 +26,8 @@ class DetailsDialog(DetailsDialogBase): self.setWindowTitle(tr("Details")) self.resize(502, 502) self.setMinimumSize(QSize(250, 250)) - self.splitter = QSplitter(Qt.Vertical, self) - self.setCentralWidget(self.splitter) - self.topFrame = QFrame() + self.splitter = QSplitter(Qt.Vertical) + self.topFrame = EmittingFrame() self.topFrame.setFrameShape(QFrame.StyledPanel) self.horizontalLayout = QGridLayout() # Minimum width for the toolbar in the middle: @@ -73,6 +73,10 @@ class DetailsDialog(DetailsDialogBase): # Late population needed here for connections to the toolbar self.vController.setupViewers( self.selectedImageViewer, self.referenceImageViewer) + # self.setCentralWidget(self.splitter) # only as QMainWindow + self.setWidget(self.splitter) # only as QDockWidget + + self.topFrame.resized.connect(self.resizeEvent) def _update(self): if self.vController is None: # Not yet constructed! @@ -88,24 +92,9 @@ class DetailsDialog(DetailsDialogBase): self.vController.updateView(ref, dupe, group) # --- Override + @pyqtSlot(QResizeEvent) def resizeEvent(self, event): - # HACK referenceViewer might be 1 pixel shorter in width - # due to the toolbar in the middle keeping the same width, - # so resizing in the GridLayout's engine leads to not enough space - # left for the panel on the right. - # This ensures same size while shrinking at least: - self.horizontalLayout.setColumnMinimumWidth( - 0, self.selectedImageViewer.size().width()) - self.horizontalLayout.setColumnMinimumWidth( - 2, self.selectedImageViewer.size().width()) - # This works when expanding but it's ugly: - if self.selectedImageViewer.size().width() > self.referenceImageViewer.size().width(): - # print(f"""Before selected size: {self.selectedImageViewer.size()}\n""", - # f"""Before reference size: {self.referenceImageViewer.size()}""") - self.selectedImageViewer.resize(self.referenceImageViewer.size()) - # print(f"""After selected size: {self.selectedImageViewer.size()}\n""", - # f"""After reference size: {self.referenceImageViewer.size()}""") - + self.ensure_same_sizes() if self.vController is None or not self.vController.bestFit: return # Only update the scaled down pixmaps @@ -117,12 +106,44 @@ class DetailsDialog(DetailsDialogBase): self.tableView.setMaximumHeight( self.tableView.rowHeight(1) * self.tableModel.model.row_count() - + self.tableView.verticalHeader().sectionSize(0)) + + self.tableView.verticalHeader().sectionSize(0) + # Windows seems to add a few pixels more to the table somehow + + (5 if ISWINDOWS else 0)) DetailsDialogBase.show(self) + self.ensure_same_sizes() self._update() + def ensure_same_sizes(self): + # HACK This ensures same size while shrinking. + # ReferenceViewer might be 1 pixel shorter in width + # due to the toolbar in the middle keeping the same width, + # so resizing in the GridLayout's engine leads to not enough space + # left for the panel on the right. + # This work as a QMainWindow, but doesn't work as a QDockWidget: + # resize can only grow. Might need some custom sizeHint somewhere... + # self.horizontalLayout.setColumnMinimumWidth( + # 0, self.selectedImageViewer.size().width()) + # self.horizontalLayout.setColumnMinimumWidth( + # 2, self.selectedImageViewer.size().width()) + + # This works when expanding but it's ugly: + if self.selectedImageViewer.size().width() > self.referenceImageViewer.size().width(): + # print(f"""Before selected size: {self.selectedImageViewer.size()}\n""", + # f"""Before reference size: {self.referenceImageViewer.size()}""") + self.selectedImageViewer.resize(self.referenceImageViewer.size()) + # print(f"""After selected size: {self.selectedImageViewer.size()}\n""", + # f"""After reference size: {self.referenceImageViewer.size()}""") + # model --> view def refresh(self): DetailsDialogBase.refresh(self) if self.isVisible(): self._update() + + +class EmittingFrame(QFrame): + """Emits a signal whenever is resized""" + resized = pyqtSignal(QResizeEvent) + + def resizeEvent(self, event): + self.resized.emit(event) diff --git a/qt/pe/image_viewer.py b/qt/pe/image_viewer.py index 54366e98..08a70db8 100644 --- a/qt/pe/image_viewer.py +++ b/qt/pe/image_viewer.py @@ -10,6 +10,7 @@ from PyQt5.QtWidgets import ( QToolBar, QToolButton, QAction, QWidget, QScrollArea, QApplication, QAbstractScrollArea, QStyle) from hscommon.trans import trget +from hscommon.plat import ISLINUX tr = trget("ui") MAX_SCALE = 12.0 @@ -21,7 +22,7 @@ def createActions(actions, target): for name, shortcut, icon, desc, func in actions: action = QAction(target) if icon: - action.setIcon(QIcon.fromTheme(icon)) + action.setIcon(icon) if shortcut: action.setShortcut(shortcut) action.setText(desc) @@ -48,28 +49,32 @@ class ViewerToolBar(QToolBar): ( "actionZoomIn", QKeySequence.ZoomIn, - "zoom-in", + QIcon.fromTheme("zoom-in") if ISLINUX + else QIcon(QPixmap(":/" + "zoom_in")), tr("Increase zoom"), controller.zoomIn, ), ( "actionZoomOut", QKeySequence.ZoomOut, - "zoom-out", + QIcon.fromTheme("zoom-out") if ISLINUX + else QIcon(QPixmap(":/" + "zoom_out")), tr("Decrease zoom"), controller.zoomOut, ), ( "actionNormalSize", tr("Ctrl+/"), - "zoom-original", + QIcon.fromTheme("zoom-original") if ISLINUX + else QIcon(QPixmap(":/" + "zoom_original")), tr("Normal size"), controller.zoomNormalSize, ), ( "actionBestFit", tr("Ctrl+*"), - "zoom-best-fit", + QIcon.fromTheme("zoom-best-fit") if ISLINUX + else QIcon(QPixmap(":/" + "zoom_best_fit")), tr("Best fit"), controller.zoomBestFit, ) @@ -83,7 +88,9 @@ class ViewerToolBar(QToolBar): self.buttonImgSwap.setToolButtonStyle(Qt.ToolButtonIconOnly) self.buttonImgSwap.setIcon( QIcon.fromTheme('view-refresh', - self.style().standardIcon(QStyle.SP_BrowserReload))) + self.style().standardIcon(QStyle.SP_BrowserReload)) + if ISLINUX + else QIcon(QPixmap(":/" + "exchange"))) self.buttonImgSwap.setText('Swap images') self.buttonImgSwap.setToolTip('Swap images') self.buttonImgSwap.pressed.connect(self.controller.swapImages) @@ -142,6 +149,7 @@ class BaseController(QObject): self.bestFit = True self.parent = parent # To change buttons' states self.cached_group = None + self.same_dimensions = True def setupViewers(self, selectedViewer, referenceViewer): self.selectedViewer = selectedViewer @@ -156,6 +164,8 @@ class BaseController(QObject): def updateView(self, ref, dupe, group): # To keep current scale accross dupes from the same group + previous_same_dimensions = self.same_dimensions + self.same_dimensions = True same_group = True if group != self.cached_group: same_group = False @@ -164,6 +174,7 @@ class BaseController(QObject): self.selectedPixmap = QPixmap(str(dupe.path)) if ref is dupe: # currently selected file is the actual reference file + # self.same_dimensions = False self.referencePixmap = QPixmap() self.scaledReferencePixmap = QPixmap() self.parent.verticalToolBar.buttonImgSwap.setEnabled(False) @@ -171,7 +182,10 @@ class BaseController(QObject): else: self.referencePixmap = QPixmap(str(ref.path)) self.parent.verticalToolBar.buttonImgSwap.setEnabled(True) + if ref.dimensions != dupe.dimensions: + self.same_dimensions = False self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) + self.updateButtonsAsPerDimensions(previous_same_dimensions) self.updateBothImages(same_group) self.centerViews(same_group and self.referencePixmap.isNull()) @@ -207,11 +221,11 @@ class BaseController(QObject): # zoomed in state, expand # only if not same_group, we need full update scaledpixmap = pixmap.scaled( - target_size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) + target_size, Qt.KeepAspectRatioByExpanding, Qt.FastTransformation) else: # best fit, keep ratio always scaledpixmap = pixmap.scaled( - target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) + target_size, Qt.KeepAspectRatio, Qt.FastTransformation) viewer.setImage(scaledpixmap) return target_size @@ -294,6 +308,22 @@ class BaseController(QObject): self.parent.verticalToolBar.buttonNormalSize.setEnabled(round(self.current_scale, 1) != 1.0) self.parent.verticalToolBar.buttonBestFit.setEnabled(self.bestFit is False) + def updateButtonsAsPerDimensions(self, previous_same_dimensions): + if not self.same_dimensions: + self.parent.verticalToolBar.buttonZoomIn.setEnabled(False) + self.parent.verticalToolBar.buttonZoomOut.setEnabled(False) + if not self.bestFit: + self.zoomBestFit() + self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) + if not self.referencePixmap.isNull(): + self.parent.verticalToolBar.buttonImgSwap.setEnabled(True) + return + if not self.bestFit and not previous_same_dimensions: + self.zoomBestFit() + self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) + if self.referencePixmap.isNull(): + self.parent.verticalToolBar.buttonImgSwap.setEnabled(False) + @pyqtSlot() def zoomBestFit(self): """Setup before scaling to bestfit""" @@ -320,6 +350,7 @@ class BaseController(QObject): self.parent.verticalToolBar.buttonZoomOut.setEnabled(False) self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) self.parent.verticalToolBar.buttonBestFit.setEnabled(False) + self.parent.verticalToolBar.buttonImgSwap.setEnabled(True) def setBestFit(self, value): self.bestFit = value @@ -339,8 +370,12 @@ class BaseController(QObject): self.selectedViewer.scaleToNormalSize() self.referenceViewer.scaleToNormalSize() - self.parent.verticalToolBar.buttonZoomIn.setEnabled(True) - self.parent.verticalToolBar.buttonZoomOut.setEnabled(True) + if self.same_dimensions: + self.parent.verticalToolBar.buttonZoomIn.setEnabled(True) + self.parent.verticalToolBar.buttonZoomOut.setEnabled(True) + else: + # we can't allow swapping pixmaps of different dimensions + self.parent.verticalToolBar.buttonImgSwap.setEnabled(False) self.parent.verticalToolBar.buttonNormalSize.setEnabled(False) self.parent.verticalToolBar.buttonBestFit.setEnabled(True) @@ -361,8 +396,16 @@ class QWidgetController(BaseController): def __init__(self, parent): super().__init__(parent) + def _updateImage(self, *args): + ret = super()._updateImage(*args) + # Fix alignment when resizing window + self.centerViews() + return ret + @pyqtSlot(QPointF) def onDraggedMouse(self, delta): + if not self.same_dimensions: + return if self.sender() is self.referenceViewer: self.selectedViewer.onDraggedMouse(delta) else: @@ -400,8 +443,14 @@ class ScrollAreaController(BaseController): self.selectedViewer.ignore_signal = True self.referenceViewer.ignore_signal = True - self.selectedViewer.onDraggedMouse(delta) - self.referenceViewer.onDraggedMouse(delta) + if self.same_dimensions: + self.selectedViewer.onDraggedMouse(delta) + self.referenceViewer.onDraggedMouse(delta) + else: + if self.sender() is self.selectedViewer: + self.selectedViewer.onDraggedMouse(delta) + else: + self.referenceViewer.onDraggedMouse(delta) self.selectedViewer.ignore_signal = False self.referenceViewer.ignore_signal = False @@ -422,6 +471,8 @@ class ScrollAreaController(BaseController): @pyqtSlot(int) def onVScrollBarChanged(self, value): + if not self.same_dimensions: + return if self.sender() is self.referenceViewer._verticalScrollBar: if not self.selectedViewer.ignore_signal: self.selectedViewer._verticalScrollBar.setValue(value) @@ -431,6 +482,8 @@ class ScrollAreaController(BaseController): @pyqtSlot(int) def onHScrollBarChanged(self, value): + if not self.same_dimensions: + return if self.sender() is self.referenceViewer._horizontalScrollBar: if not self.selectedViewer.ignore_signal: self.selectedViewer._horizontalScrollBar.setValue(value) @@ -448,6 +501,8 @@ class ScrollAreaController(BaseController): def zoomBestFit(self): # Disable scrollbars to avoid GridLayout size rounding glitch super().zoomBestFit() + if self.referencePixmap.isNull(): + self.parent.verticalToolBar.buttonImgSwap.setEnabled(False) self.selectedViewer.toggleScrollBars() self.referenceViewer.toggleScrollBars() @@ -484,6 +539,8 @@ class GraphicsViewController(BaseController): @pyqtSlot(int) def onVScrollBarChanged(self, value): + if not self.same_dimensions: + return if self.sender() is self.referenceViewer._verticalScrollBar: if not self.selectedViewer.ignore_signal: self.selectedViewer._verticalScrollBar.setValue(value) @@ -493,6 +550,8 @@ class GraphicsViewController(BaseController): @pyqtSlot(int) def onHScrollBarChanged(self, value): + if not self.same_dimensions: + return if self.sender() is self.referenceViewer._horizontalScrollBar: if not self.selectedViewer.ignore_signal: self.selectedViewer._horizontalScrollBar.setValue(value) @@ -518,9 +577,16 @@ class GraphicsViewController(BaseController): self.parent.verticalToolBar.buttonZoomOut.setEnabled(False) self.parent.verticalToolBar.buttonZoomIn.setEnabled(False) self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) + if not self.referencePixmap.isNull(): + self.parent.verticalToolBar.buttonImgSwap.setEnabled(True) + # else: + # self.referenceViewer.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + # self.referenceViewer.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) def updateView(self, ref, dupe, group): # Keep current scale accross dupes from the same group + previous_same_dimensions = self.same_dimensions + self.same_dimensions = True same_group = True if group != self.cached_group: same_group = False @@ -529,16 +595,19 @@ class GraphicsViewController(BaseController): self.selectedPixmap = QPixmap(str(dupe.path)) if ref is dupe: # currently selected file is the actual reference file + self.same_dimensions = False self.referencePixmap = QPixmap() self.parent.verticalToolBar.buttonImgSwap.setEnabled(False) self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) else: self.referencePixmap = QPixmap(str(ref.path)) self.parent.verticalToolBar.buttonImgSwap.setEnabled(True) + if ref.dimensions != dupe.dimensions: + self.same_dimensions = False self.parent.verticalToolBar.buttonNormalSize.setEnabled(True) - - self.selectedViewer.setImage(self.selectedPixmap) - self.referenceViewer.setImage(self.referencePixmap) + # self.selectedViewer.setImage(self.selectedPixmap) + # self.referenceViewer.setImage(self.referencePixmap) + self.updateButtonsAsPerDimensions(previous_same_dimensions) self.updateBothImages(same_group) def updateBothImages(self, same_group=False): @@ -557,7 +626,9 @@ class GraphicsViewController(BaseController): def _updateFitImage(self, pixmap, viewer): # If not same_group, we need full update""" + viewer.setImage(pixmap) if pixmap.isNull(): + # viewer._item = None return if viewer.bestFit: viewer.fitScale() @@ -717,7 +788,7 @@ class QWidgetImageViewer(QWidget): self.setMouseTracking(False) def wheelEvent(self, event): - if self.bestFit or not self.isEnabled(): + if self.bestFit or not self.controller.same_dimensions or not self.isEnabled(): event.ignore() return @@ -910,7 +981,7 @@ class ScrollAreaImageViewer(QScrollArea): super().mouseReleaseEvent(event) def wheelEvent(self, event): - if self.bestFit: + if self.bestFit or not self.controller.same_dimensions: event.ignore() return oldScale = self.current_scale @@ -1034,7 +1105,7 @@ class ScrollAreaImageViewer(QScrollArea): class GraphicsViewViewer(QGraphicsView): - """Re-Implementation using a more full fledged class.""" + """Re-Implementation a full-fledged GraphicsView but is a bit buggy.""" mouseDragged = pyqtSignal() mouseWheeled = pyqtSignal(float, QPointF) @@ -1163,7 +1234,7 @@ class GraphicsViewViewer(QGraphicsView): self._centerPoint = self.mapToScene(self.rect().center()) def wheelEvent(self, event): - if self.bestFit or MIN_SCALE > self.current_scale > MAX_SCALE: + if self.bestFit or MIN_SCALE > self.current_scale > MAX_SCALE or not self.controller.same_dimensions: event.ignore() return pointBeforeScale = QPointF(self.mapToScene(self.mapFromGlobal(QCursor.pos()))) @@ -1186,6 +1257,10 @@ class GraphicsViewViewer(QGraphicsView): self.other_viewer.ignore_signal = False def setImage(self, pixmap): + if pixmap.isNull(): + self.ignore_signal = True + elif self.ignore_signal: + self.ignore_signal = False self._pixmap = pixmap self._item.setPixmap(pixmap) self.translate(1, 1) @@ -1241,7 +1316,7 @@ class GraphicsViewViewer(QGraphicsView): """Called when the pixmap is set back to original size.""" self.bestFit = False self.scaleAt(1.0) - self.toggleScrollBars() + self.toggleScrollBars(True) self.update() def adjustScrollBarsScaled(self, delta): diff --git a/qt/preferences.py b/qt/preferences.py index c9691cca..39e55b1e 100644 --- a/qt/preferences.py +++ b/qt/preferences.py @@ -31,6 +31,8 @@ class Preferences(PreferencesBase): self.tableFontSize = get("TableFontSize", self.tableFontSize) self.reference_bold_font = get('ReferenceBoldFont', self.reference_bold_font) + self.details_dialog_titlebar_enabled = get('DetailsDialogTitleBarEnabled', self.details_dialog_titlebar_enabled) + self.details_dialog_vertical_titlebar = get('DetailsDialogVerticalTitleBar', self.details_dialog_vertical_titlebar) self.resultWindowIsMaximized = get( "ResultWindowIsMaximized", self.resultWindowIsMaximized ) @@ -67,6 +69,8 @@ class Preferences(PreferencesBase): self.tableFontSize = QApplication.font().pointSize() self.reference_bold_font = True + self.details_dialog_titlebar_enabled = True + self.details_dialog_vertical_titlebar = True self.resultWindowIsMaximized = False self.resultWindowRect = None self.directoriesWindowRect = None @@ -100,6 +104,8 @@ class Preferences(PreferencesBase): set_("TableFontSize", self.tableFontSize) set_('ReferenceBoldFont', self.reference_bold_font) + set_('DetailsDialogTitleBarEnabled', self.details_dialog_titlebar_enabled) + set_('DetailsDialogVerticalTitleBar', self.details_dialog_vertical_titlebar) set_("ResultWindowIsMaximized", self.resultWindowIsMaximized) self.set_rect("ResultWindowRect", self.resultWindowRect) self.set_rect("DirectoriesWindowRect", self.directoriesWindowRect) diff --git a/qt/preferences_dialog.py b/qt/preferences_dialog.py index eb3462e3..95eb1b67 100644 --- a/qt/preferences_dialog.py +++ b/qt/preferences_dialog.py @@ -117,8 +117,21 @@ class PreferencesDialogBase(QDialog): self.widgetsVLayout.addLayout( horizontalWrap([self.fontSizeLabel, self.fontSizeSpinBox, None]) ) - self._setupAddCheckbox("reference_bold_font", tr("Bold font for reference.")) + self._setupAddCheckbox("reference_bold_font", + tr("Bold font for reference")) self.widgetsVLayout.addWidget(self.reference_bold_font) + + self._setupAddCheckbox("details_dialog_titlebar_enabled", + tr("Details dialog displays a title bar and is dockable")) + self.widgetsVLayout.addWidget(self.details_dialog_titlebar_enabled) + self._setupAddCheckbox("details_dialog_vertical_titlebar", + tr("Details dialog displays a vertical title bar (Linux only)")) + self.widgetsVLayout.addWidget(self.details_dialog_vertical_titlebar) + self.details_dialog_vertical_titlebar.setEnabled( + self.details_dialog_titlebar_enabled.isChecked()) + self.details_dialog_titlebar_enabled.stateChanged.connect( + self.details_dialog_vertical_titlebar.setEnabled) + self.languageLabel = QLabel(tr("Language:"), self) self.languageComboBox = QComboBox(self) for lang in self.supportedLanguages: @@ -190,6 +203,8 @@ class PreferencesDialogBase(QDialog): setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) setchecked(self.debugModeBox, prefs.debug_mode) setchecked(self.reference_bold_font, prefs.reference_bold_font) + setchecked(self.details_dialog_titlebar_enabled , prefs.details_dialog_titlebar_enabled) + setchecked(self.details_dialog_vertical_titlebar, prefs.details_dialog_vertical_titlebar) self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) self.customCommandEdit.setText(prefs.custom_command) self.fontSizeSpinBox.setValue(prefs.tableFontSize) @@ -210,6 +225,8 @@ class PreferencesDialogBase(QDialog): prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) prefs.debug_mode = ischecked(self.debugModeBox) prefs.reference_bold_font = ischecked(self.reference_bold_font) + prefs.details_dialog_titlebar_enabled = ischecked(self.details_dialog_titlebar_enabled) + prefs.details_dialog_vertical_titlebar = ischecked(self.details_dialog_vertical_titlebar) prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() prefs.custom_command = str(self.customCommandEdit.text()) prefs.tableFontSize = self.fontSizeSpinBox.value() diff --git a/qt/se/details_dialog.py b/qt/se/details_dialog.py index 812c649f..0f922dc4 100644 --- a/qt/se/details_dialog.py +++ b/qt/se/details_dialog.py @@ -5,7 +5,7 @@ # http://www.gnu.org/licenses/gpl-3.0.html from PyQt5.QtCore import QSize -from PyQt5.QtWidgets import QVBoxLayout, QAbstractItemView +from PyQt5.QtWidgets import QVBoxLayout, QAbstractItemView, QWidget from hscommon.trans import trget from ..details_dialog import DetailsDialog as DetailsDialogBase @@ -27,3 +27,6 @@ class DetailsDialog(DetailsDialogBase): self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setShowGrid(False) self.verticalLayout.addWidget(self.tableView) + self.centralWidget = QWidget() + self.centralWidget.setLayout(self.verticalLayout) + self.setWidget(self.centralWidget) diff --git a/qtlib/about_box.py b/qtlib/about_box.py index 88512666..99c3a059 100644 --- a/qtlib/about_box.py +++ b/qtlib/about_box.py @@ -42,7 +42,7 @@ class AboutBox(QDialog): self.setWindowTitle( tr("About {}").format(QCoreApplication.instance().applicationName()) ) - self.resize(400, 190) + self.resize(400, 290) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -69,6 +69,21 @@ class AboutBox(QDialog): self.verticalLayout.addWidget(self.label_3) self.label_3.setText(tr("Licensed under GPLv3")) self.label = QLabel(self) + self.label_4 = QLabel(self) + self.label_4.setWordWrap(True) + self.label_4.setTextFormat(Qt.RichText) + self.label_4.setOpenExternalLinks(True) + self.label_4.setText(tr( + """Exchange icon + made by Jason Cho (used with permission). +
+Zoom In +Zoom Out +Zoomt Best Fit +Zoom Original + icons made by schollidesign + (licensed under GPL).""")) + self.verticalLayout.addWidget(self.label_4) font = QFont() font.setWeight(75) font.setBold(True)