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..56555c30 100644 --- a/qt/details_dialog.py +++ b/qt/details_dialog.py @@ -7,17 +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 -class DetailsDialog(QMainWindow): +class DetailsDialog(QDockWidget): def __init__(self, parent, app, **kwargs): super().__init__(parent, Qt.Tool, **kwargs) self.app = app self.model = app.model.details_panel + self.setAllowedAreas(Qt.AllDockWidgetAreas) self._setupUi() + self.update_options() # 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. self._shown_once = False @@ -36,6 +38,22 @@ class DetailsDialog(QMainWindow): self._shown_once = True super().show() + 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()) + 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: 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 15c16157..dde2cfc7 100644 --- a/qt/pe/details_dialog.py +++ b/qt/pe/details_dialog.py @@ -26,8 +26,7 @@ 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.splitter = QSplitter(Qt.Vertical) self.topFrame = QFrame() self.topFrame.setFrameShape(QFrame.StyledPanel) self.horizontalLayout = QGridLayout() @@ -74,6 +73,8 @@ 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 def _update(self): if self.vController is None: # Not yet constructed! @@ -110,15 +111,17 @@ class DetailsDialog(DetailsDialogBase): self._update() def ensure_same_sizes(self): - # HACK referenceViewer might be 1 pixel shorter in width + # 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 ensures same size while shrinking at least: - self.horizontalLayout.setColumnMinimumWidth( - 0, self.selectedImageViewer.size().width()) - self.horizontalLayout.setColumnMinimumWidth( - 2, self.selectedImageViewer.size().width()) + # 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(): 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..2603eeb4 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.")) + 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)