mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-05-07 01:19:48 +00:00
Some type-hinting for various qt base objects
This commit is contained in:
parent
b9aabb8545
commit
ade5d7f8c1
@ -15,7 +15,7 @@ tr = trget("ui")
|
|||||||
|
|
||||||
|
|
||||||
class DetailsDialog(DetailsDialogBase):
|
class DetailsDialog(DetailsDialogBase):
|
||||||
def _setupUi(self):
|
def _setupUi(self) -> None:
|
||||||
self.setWindowTitle(tr("Details"))
|
self.setWindowTitle(tr("Details"))
|
||||||
self.resize(502, 295)
|
self.resize(502, 295)
|
||||||
self.setMinimumSize(QSize(250, 250))
|
self.setMinimumSize(QSize(250, 250))
|
||||||
|
@ -4,27 +4,22 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
from typing import Callable
|
||||||
from PyQt5.QtCore import QSize
|
from PyQt5.QtCore import QSize
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QSpacerItem, QWidget, QCheckBox
|
||||||
QVBoxLayout,
|
|
||||||
QHBoxLayout,
|
|
||||||
QLabel,
|
|
||||||
QSizePolicy,
|
|
||||||
QSpacerItem,
|
|
||||||
QWidget,
|
|
||||||
)
|
|
||||||
|
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from core.app import AppMode
|
from core.app import AppMode
|
||||||
from core.scanner import ScanType
|
from core.scanner import ScanType
|
||||||
|
from qt.preferences import Preferences
|
||||||
|
|
||||||
from qt.preferences_dialog import PreferencesDialogBase
|
from qt.preferences_dialog import PreferencesDialogBase, Sections
|
||||||
|
|
||||||
tr = trget("ui")
|
tr = trget("ui")
|
||||||
|
|
||||||
|
|
||||||
class PreferencesDialog(PreferencesDialogBase):
|
class PreferencesDialog(PreferencesDialogBase):
|
||||||
def _setupPreferenceWidgets(self):
|
def _setupPreferenceWidgets(self) -> None:
|
||||||
self._setupFilterHardnessBox()
|
self._setupFilterHardnessBox()
|
||||||
self.widgetsVLayout.addLayout(self.filterHardnessHLayout)
|
self.widgetsVLayout.addLayout(self.filterHardnessHLayout)
|
||||||
self.widget = QWidget(self)
|
self.widget = QWidget(self)
|
||||||
@ -70,7 +65,7 @@ class PreferencesDialog(PreferencesDialogBase):
|
|||||||
self.widgetsVLayout.addWidget(self.ignoreHardlinkMatches)
|
self.widgetsVLayout.addWidget(self.ignoreHardlinkMatches)
|
||||||
self._setupBottomPart()
|
self._setupBottomPart()
|
||||||
|
|
||||||
def _load(self, prefs, setchecked, section):
|
def _load(self, prefs: Preferences, setchecked: Callable[[QCheckBox, bool], None], section: Sections) -> None:
|
||||||
setchecked(self.tagTrackBox, prefs.scan_tag_track)
|
setchecked(self.tagTrackBox, prefs.scan_tag_track)
|
||||||
setchecked(self.tagArtistBox, prefs.scan_tag_artist)
|
setchecked(self.tagArtistBox, prefs.scan_tag_artist)
|
||||||
setchecked(self.tagAlbumBox, prefs.scan_tag_album)
|
setchecked(self.tagAlbumBox, prefs.scan_tag_album)
|
||||||
@ -99,7 +94,7 @@ class PreferencesDialog(PreferencesDialogBase):
|
|||||||
self.tagGenreBox.setEnabled(tag_based)
|
self.tagGenreBox.setEnabled(tag_based)
|
||||||
self.tagYearBox.setEnabled(tag_based)
|
self.tagYearBox.setEnabled(tag_based)
|
||||||
|
|
||||||
def _save(self, prefs, ischecked):
|
def _save(self, prefs: Preferences, ischecked: Callable[[QCheckBox], bool]) -> None:
|
||||||
prefs.scan_tag_track = ischecked(self.tagTrackBox)
|
prefs.scan_tag_track = ischecked(self.tagTrackBox)
|
||||||
prefs.scan_tag_artist = ischecked(self.tagArtistBox)
|
prefs.scan_tag_artist = ischecked(self.tagArtistBox)
|
||||||
prefs.scan_tag_album = ischecked(self.tagAlbumBox)
|
prefs.scan_tag_album = ischecked(self.tagAlbumBox)
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
from typing import Union
|
||||||
from PyQt5.QtWidgets import QAbstractItemView, QSizePolicy, QGridLayout, QSplitter, QFrame
|
from PyQt5.QtCore import Qt, QSize, pyqtSignal
|
||||||
|
from PyQt5.QtWidgets import QWidget, QAbstractItemView, QSizePolicy, QGridLayout, QSplitter, QFrame
|
||||||
from PyQt5.QtGui import QResizeEvent
|
from PyQt5.QtGui import QResizeEvent
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
|
from qt import app
|
||||||
from qt.details_dialog import DetailsDialog as DetailsDialogBase
|
from qt.details_dialog import DetailsDialog as DetailsDialogBase
|
||||||
from qt.details_table import DetailsTable
|
from qt.details_table import DetailsTable
|
||||||
from qt.pe.image_viewer import ViewerToolBar, ScrollAreaImageViewer, ScrollAreaController
|
from qt.pe.image_viewer import ViewerToolBar, ScrollAreaImageViewer, ScrollAreaController
|
||||||
@ -16,15 +18,15 @@ tr = trget("ui")
|
|||||||
|
|
||||||
|
|
||||||
class DetailsDialog(DetailsDialogBase):
|
class DetailsDialog(DetailsDialogBase):
|
||||||
def __init__(self, parent, app):
|
def __init__(self, parent: QWidget, app: "app.DupeGuru") -> None:
|
||||||
self.vController = None
|
self.vController: Union[ScrollAreaController, None] = None
|
||||||
super().__init__(parent, app)
|
super().__init__(parent, app)
|
||||||
|
|
||||||
def _setupUi(self):
|
def _setupUi(self) -> None:
|
||||||
self.setWindowTitle(tr("Details"))
|
self.setWindowTitle(tr("Details"))
|
||||||
self.resize(502, 502)
|
self.resize(502, 502)
|
||||||
self.setMinimumSize(QSize(250, 250))
|
self.setMinimumSize(QSize(250, 250))
|
||||||
self.splitter = QSplitter(Qt.Vertical)
|
self.splitter = QSplitter(Qt.Orientation.Vertical)
|
||||||
self.topFrame = EmittingFrame()
|
self.topFrame = EmittingFrame()
|
||||||
self.topFrame.setFrameShape(QFrame.StyledPanel)
|
self.topFrame.setFrameShape(QFrame.StyledPanel)
|
||||||
self.horizontalLayout = QGridLayout()
|
self.horizontalLayout = QGridLayout()
|
||||||
@ -47,8 +49,8 @@ class DetailsDialog(DetailsDialogBase):
|
|||||||
self.vController = ScrollAreaController(self)
|
self.vController = ScrollAreaController(self)
|
||||||
|
|
||||||
self.verticalToolBar = ViewerToolBar(self, self.vController)
|
self.verticalToolBar = ViewerToolBar(self, self.vController)
|
||||||
self.verticalToolBar.setOrientation(Qt.Orientation(Qt.Vertical))
|
self.verticalToolBar.setOrientation(Qt.Orientation.Vertical)
|
||||||
self.horizontalLayout.addWidget(self.verticalToolBar, 1, 1, 1, 1, Qt.AlignCenter)
|
self.horizontalLayout.addWidget(self.verticalToolBar, 1, 1, 1, 1, Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
self.referenceImageViewer = ScrollAreaImageViewer(self, "referenceImage")
|
self.referenceImageViewer = ScrollAreaImageViewer(self, "referenceImage")
|
||||||
self.horizontalLayout.addWidget(self.referenceImageViewer, 0, 2, 3, 1)
|
self.horizontalLayout.addWidget(self.referenceImageViewer, 0, 2, 3, 1)
|
||||||
@ -73,7 +75,7 @@ class DetailsDialog(DetailsDialogBase):
|
|||||||
|
|
||||||
self.topFrame.resized.connect(self.resizeEvent)
|
self.topFrame.resized.connect(self.resizeEvent)
|
||||||
|
|
||||||
def _update(self):
|
def _update(self) -> None:
|
||||||
if self.vController is None: # Not yet constructed!
|
if self.vController is None: # Not yet constructed!
|
||||||
return
|
return
|
||||||
if not self.app.model.selected_dupes:
|
if not self.app.model.selected_dupes:
|
||||||
@ -87,15 +89,14 @@ class DetailsDialog(DetailsDialogBase):
|
|||||||
self.vController.updateView(ref, dupe, group)
|
self.vController.updateView(ref, dupe, group)
|
||||||
|
|
||||||
# --- Override
|
# --- Override
|
||||||
@pyqtSlot(QResizeEvent)
|
def resizeEvent(self, event: QResizeEvent) -> None:
|
||||||
def resizeEvent(self, event):
|
|
||||||
self.ensure_same_sizes()
|
self.ensure_same_sizes()
|
||||||
if self.vController is None or not self.vController.bestFit:
|
if self.vController is None or not self.vController.bestFit:
|
||||||
return
|
return
|
||||||
# Only update the scaled down pixmaps
|
# Only update the scaled down pixmaps
|
||||||
self.vController.updateBothImages()
|
self.vController.updateBothImages()
|
||||||
|
|
||||||
def show(self):
|
def show(self) -> None:
|
||||||
# Give the splitter a maximum height to reach. This is assuming that
|
# Give the splitter a maximum height to reach. This is assuming that
|
||||||
# all rows below their headers have the same height
|
# all rows below their headers have the same height
|
||||||
self.tableView.setMaximumHeight(
|
self.tableView.setMaximumHeight(
|
||||||
@ -108,7 +109,7 @@ class DetailsDialog(DetailsDialogBase):
|
|||||||
self.ensure_same_sizes()
|
self.ensure_same_sizes()
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def ensure_same_sizes(self):
|
def ensure_same_sizes(self) -> None:
|
||||||
# HACK This ensures same size while shrinking.
|
# HACK This ensures same size while shrinking.
|
||||||
# ReferenceViewer might be 1 pixel shorter in width
|
# ReferenceViewer might be 1 pixel shorter in width
|
||||||
# due to the toolbar in the middle keeping the same width,
|
# due to the toolbar in the middle keeping the same width,
|
||||||
@ -126,7 +127,7 @@ class DetailsDialog(DetailsDialogBase):
|
|||||||
self.selectedImageViewer.resize(self.referenceImageViewer.size())
|
self.selectedImageViewer.resize(self.referenceImageViewer.size())
|
||||||
|
|
||||||
# model --> view
|
# model --> view
|
||||||
def refresh(self):
|
def refresh(self) -> None:
|
||||||
DetailsDialogBase.refresh(self)
|
DetailsDialogBase.refresh(self)
|
||||||
if self.isVisible():
|
if self.isVisible():
|
||||||
self._update()
|
self._update()
|
||||||
@ -137,5 +138,5 @@ class EmittingFrame(QFrame):
|
|||||||
|
|
||||||
resized = pyqtSignal(QResizeEvent)
|
resized = pyqtSignal(QResizeEvent)
|
||||||
|
|
||||||
def resizeEvent(self, event):
|
def resizeEvent(self, event: QResizeEvent) -> None:
|
||||||
self.resized.emit(event)
|
self.resized.emit(event)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
from typing import Union, cast
|
||||||
from PyQt5.QtCore import QObject, Qt, QSize, QRectF, QPointF, QPoint, pyqtSlot, pyqtSignal, QEvent
|
from PyQt5.QtCore import QObject, Qt, QSize, QRectF, QPointF, QPoint, pyqtSlot, pyqtSignal, QEvent
|
||||||
from PyQt5.QtGui import QPixmap, QPainter, QPalette, QCursor, QIcon, QKeySequence
|
from PyQt5.QtGui import QPixmap, QPainter, QPalette, QCursor, QIcon, QKeySequence
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
@ -17,6 +18,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QAbstractScrollArea,
|
QAbstractScrollArea,
|
||||||
QStyle,
|
QStyle,
|
||||||
)
|
)
|
||||||
|
from qt.details_dialog import DetailsDialog
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from hscommon.plat import ISLINUX
|
from hscommon.plat import ISLINUX
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ MAX_SCALE = 12.0
|
|||||||
MIN_SCALE = 0.1
|
MIN_SCALE = 0.1
|
||||||
|
|
||||||
|
|
||||||
def create_actions(actions, target):
|
def create_actions(actions: list, target: QObject) -> None:
|
||||||
# actions are list of (name, shortcut, icon, desc, func)
|
# actions are list of (name, shortcut, icon, desc, func)
|
||||||
for name, shortcut, icon, desc, func in actions:
|
for name, shortcut, icon, desc, func in actions:
|
||||||
action = QAction(target)
|
action = QAction(target)
|
||||||
@ -40,9 +42,9 @@ def create_actions(actions, target):
|
|||||||
|
|
||||||
|
|
||||||
class ViewerToolBar(QToolBar):
|
class ViewerToolBar(QToolBar):
|
||||||
def __init__(self, parent, controller):
|
def __init__(self, parent: DetailsDialog, controller: "BaseController") -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.parent = parent
|
self.setParent(parent)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.setupActions(controller)
|
self.setupActions(controller)
|
||||||
self.createButtons()
|
self.createButtons()
|
||||||
@ -52,24 +54,21 @@ class ViewerToolBar(QToolBar):
|
|||||||
self.buttonNormalSize.setEnabled(False)
|
self.buttonNormalSize.setEnabled(False)
|
||||||
self.buttonBestFit.setEnabled(False)
|
self.buttonBestFit.setEnabled(False)
|
||||||
|
|
||||||
def setupActions(self, controller):
|
def setupActions(self, controller: "BaseController") -> None:
|
||||||
|
override_icons = cast(DetailsDialog, self.parent()).app.prefs.details_dialog_override_theme_icons
|
||||||
# actions are list of (name, shortcut, icon, desc, func)
|
# actions are list of (name, shortcut, icon, desc, func)
|
||||||
ACTIONS = [
|
ACTIONS = [
|
||||||
(
|
(
|
||||||
"actionZoomIn",
|
"actionZoomIn",
|
||||||
QKeySequence.ZoomIn,
|
QKeySequence.ZoomIn,
|
||||||
QIcon.fromTheme("zoom-in")
|
QIcon.fromTheme("zoom-in") if ISLINUX and not override_icons else QIcon(QPixmap(":/" + "zoom_in")),
|
||||||
if ISLINUX and not self.parent.app.prefs.details_dialog_override_theme_icons
|
|
||||||
else QIcon(QPixmap(":/" + "zoom_in")),
|
|
||||||
tr("Increase zoom"),
|
tr("Increase zoom"),
|
||||||
controller.zoomIn,
|
controller.zoomIn,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"actionZoomOut",
|
"actionZoomOut",
|
||||||
QKeySequence.ZoomOut,
|
QKeySequence.ZoomOut,
|
||||||
QIcon.fromTheme("zoom-out")
|
QIcon.fromTheme("zoom-out") if ISLINUX and not override_icons else QIcon(QPixmap(":/" + "zoom_out")),
|
||||||
if ISLINUX and not self.parent.app.prefs.details_dialog_override_theme_icons
|
|
||||||
else QIcon(QPixmap(":/" + "zoom_out")),
|
|
||||||
tr("Decrease zoom"),
|
tr("Decrease zoom"),
|
||||||
controller.zoomOut,
|
controller.zoomOut,
|
||||||
),
|
),
|
||||||
@ -77,7 +76,7 @@ class ViewerToolBar(QToolBar):
|
|||||||
"actionNormalSize",
|
"actionNormalSize",
|
||||||
tr("Ctrl+/"),
|
tr("Ctrl+/"),
|
||||||
QIcon.fromTheme("zoom-original")
|
QIcon.fromTheme("zoom-original")
|
||||||
if ISLINUX and not self.parent.app.prefs.details_dialog_override_theme_icons
|
if ISLINUX and not override_icons
|
||||||
else QIcon(QPixmap(":/" + "zoom_original")),
|
else QIcon(QPixmap(":/" + "zoom_original")),
|
||||||
tr("Normal size"),
|
tr("Normal size"),
|
||||||
controller.zoomNormalSize,
|
controller.zoomNormalSize,
|
||||||
@ -86,7 +85,7 @@ class ViewerToolBar(QToolBar):
|
|||||||
"actionBestFit",
|
"actionBestFit",
|
||||||
tr("Ctrl+*"),
|
tr("Ctrl+*"),
|
||||||
QIcon.fromTheme("zoom-best-fit")
|
QIcon.fromTheme("zoom-best-fit")
|
||||||
if ISLINUX and not self.parent.app.prefs.details_dialog_override_theme_icons
|
if ISLINUX and not override_icons
|
||||||
else QIcon(QPixmap(":/" + "zoom_best_fit")),
|
else QIcon(QPixmap(":/" + "zoom_best_fit")),
|
||||||
tr("Best fit"),
|
tr("Best fit"),
|
||||||
controller.zoomBestFit,
|
controller.zoomBestFit,
|
||||||
@ -96,12 +95,12 @@ class ViewerToolBar(QToolBar):
|
|||||||
# the popup menu work in the toolbar (if resized below minimum height)
|
# the popup menu work in the toolbar (if resized below minimum height)
|
||||||
create_actions(ACTIONS, self)
|
create_actions(ACTIONS, self)
|
||||||
|
|
||||||
def createButtons(self):
|
def createButtons(self) -> None:
|
||||||
self.buttonImgSwap = QToolButton(self)
|
self.buttonImgSwap = QToolButton(self)
|
||||||
self.buttonImgSwap.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
self.buttonImgSwap.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.buttonImgSwap.setIcon(
|
self.buttonImgSwap.setIcon(
|
||||||
QIcon.fromTheme("view-refresh", self.style().standardIcon(QStyle.SP_BrowserReload))
|
QIcon.fromTheme("view-refresh", self.style().standardIcon(QStyle.StandardPixmap.SP_BrowserReload))
|
||||||
if ISLINUX and not self.parent.app.prefs.details_dialog_override_theme_icons
|
if ISLINUX and not cast(DetailsDialog, self.parent()).app.prefs.details_dialog_override_theme_icons
|
||||||
else QIcon(QPixmap(":/" + "exchange"))
|
else QIcon(QPixmap(":/" + "exchange"))
|
||||||
)
|
)
|
||||||
self.buttonImgSwap.setText("Swap images")
|
self.buttonImgSwap.setText("Swap images")
|
||||||
@ -110,22 +109,22 @@ class ViewerToolBar(QToolBar):
|
|||||||
self.buttonImgSwap.released.connect(self.controller.swapImages)
|
self.buttonImgSwap.released.connect(self.controller.swapImages)
|
||||||
|
|
||||||
self.buttonZoomIn = QToolButton(self)
|
self.buttonZoomIn = QToolButton(self)
|
||||||
self.buttonZoomIn.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
self.buttonZoomIn.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.buttonZoomIn.setDefaultAction(self.actionZoomIn)
|
self.buttonZoomIn.setDefaultAction(self.actionZoomIn)
|
||||||
self.buttonZoomIn.setEnabled(False)
|
self.buttonZoomIn.setEnabled(False)
|
||||||
|
|
||||||
self.buttonZoomOut = QToolButton(self)
|
self.buttonZoomOut = QToolButton(self)
|
||||||
self.buttonZoomOut.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
self.buttonZoomOut.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.buttonZoomOut.setDefaultAction(self.actionZoomOut)
|
self.buttonZoomOut.setDefaultAction(self.actionZoomOut)
|
||||||
self.buttonZoomOut.setEnabled(False)
|
self.buttonZoomOut.setEnabled(False)
|
||||||
|
|
||||||
self.buttonNormalSize = QToolButton(self)
|
self.buttonNormalSize = QToolButton(self)
|
||||||
self.buttonNormalSize.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
self.buttonNormalSize.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.buttonNormalSize.setDefaultAction(self.actionNormalSize)
|
self.buttonNormalSize.setDefaultAction(self.actionNormalSize)
|
||||||
self.buttonNormalSize.setEnabled(True)
|
self.buttonNormalSize.setEnabled(True)
|
||||||
|
|
||||||
self.buttonBestFit = QToolButton(self)
|
self.buttonBestFit = QToolButton(self)
|
||||||
self.buttonBestFit.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
self.buttonBestFit.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
||||||
self.buttonBestFit.setDefaultAction(self.actionBestFit)
|
self.buttonBestFit.setDefaultAction(self.actionBestFit)
|
||||||
self.buttonBestFit.setEnabled(False)
|
self.buttonBestFit.setEnabled(False)
|
||||||
|
|
||||||
@ -141,10 +140,10 @@ class BaseController(QObject):
|
|||||||
Base proxy interface to keep image viewers synchronized.
|
Base proxy interface to keep image viewers synchronized.
|
||||||
Relays function calls, keep tracks of things."""
|
Relays function calls, keep tracks of things."""
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QObject) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.selectedViewer = None
|
self.selectedViewer: Union[ScrollAreaImageViewer, None] = None
|
||||||
self.referenceViewer = None
|
self.referenceViewer: Union[ScrollAreaImageViewer, None] = None
|
||||||
# cached pixmaps
|
# cached pixmaps
|
||||||
self.selectedPixmap = QPixmap()
|
self.selectedPixmap = QPixmap()
|
||||||
self.referencePixmap = QPixmap()
|
self.referencePixmap = QPixmap()
|
||||||
@ -152,22 +151,24 @@ class BaseController(QObject):
|
|||||||
self.scaledReferencePixmap = QPixmap()
|
self.scaledReferencePixmap = QPixmap()
|
||||||
self.current_scale = 1.0
|
self.current_scale = 1.0
|
||||||
self.bestFit = True
|
self.bestFit = True
|
||||||
self.parent = parent # To change buttons' states
|
self.setParent(parent) # To change buttons' states
|
||||||
self.cached_group = None
|
self.cached_group = None
|
||||||
self.same_dimensions = True
|
self.same_dimensions = True
|
||||||
|
|
||||||
def setupViewers(self, selected_viewer, reference_viewer):
|
def setupViewers(self, selected_viewer: "ScrollAreaImageViewer", reference_viewer: "ScrollAreaImageViewer") -> None:
|
||||||
self.selectedViewer = selected_viewer
|
self.selectedViewer = selected_viewer
|
||||||
self.referenceViewer = reference_viewer
|
self.referenceViewer = reference_viewer
|
||||||
self.selectedViewer.controller = self
|
self.selectedViewer.controller = self
|
||||||
self.referenceViewer.controller = self
|
self.referenceViewer.controller = self
|
||||||
self._setupConnections()
|
self._setupConnections()
|
||||||
|
|
||||||
def _setupConnections(self):
|
def _setupConnections(self) -> None:
|
||||||
self.selectedViewer.connectMouseSignals()
|
if self.selectedViewer is not None:
|
||||||
self.referenceViewer.connectMouseSignals()
|
self.selectedViewer.connectMouseSignals()
|
||||||
|
if self.referenceViewer is not None:
|
||||||
|
self.referenceViewer.connectMouseSignals()
|
||||||
|
|
||||||
def updateView(self, ref, dupe, group):
|
def updateView(self, ref, dupe, group) -> None:
|
||||||
# To keep current scale accross dupes from the same group
|
# To keep current scale accross dupes from the same group
|
||||||
previous_same_dimensions = self.same_dimensions
|
previous_same_dimensions = self.same_dimensions
|
||||||
self.same_dimensions = True
|
self.same_dimensions = True
|
||||||
@ -206,13 +207,15 @@ class BaseController(QObject):
|
|||||||
if ignore_update:
|
if ignore_update:
|
||||||
self.selectedViewer.ignore_signal = False
|
self.selectedViewer.ignore_signal = False
|
||||||
|
|
||||||
def _updateImage(self, pixmap, viewer, same_group=False):
|
def _updateImage(
|
||||||
|
self, pixmap: QPixmap, viewer: "ScrollAreaImageViewer", same_group: bool = False
|
||||||
|
) -> Union[QSize, None]:
|
||||||
# WARNING this is called on every resize event, might need to split
|
# WARNING this is called on every resize event, might need to split
|
||||||
# into a separate function depending on the implementation used
|
# into a separate function depending on the implementation used
|
||||||
if pixmap.isNull():
|
if pixmap.isNull():
|
||||||
# This should disable the blank widget
|
# This should disable the blank widget
|
||||||
viewer.setImage(pixmap)
|
viewer.setImage(pixmap)
|
||||||
return
|
return None
|
||||||
target_size = viewer.size()
|
target_size = viewer.size()
|
||||||
if not viewer.bestFit:
|
if not viewer.bestFit:
|
||||||
if same_group:
|
if same_group:
|
||||||
@ -220,14 +223,18 @@ class BaseController(QObject):
|
|||||||
return target_size
|
return target_size
|
||||||
# zoomed in state, expand
|
# zoomed in state, expand
|
||||||
# only if not same_group, we need full update
|
# only if not same_group, we need full update
|
||||||
scaledpixmap = pixmap.scaled(target_size, Qt.KeepAspectRatioByExpanding, Qt.FastTransformation)
|
scaledpixmap = pixmap.scaled(
|
||||||
|
target_size, Qt.AspectRatioMode.KeepAspectRatioByExpanding, Qt.TransformationMode.FastTransformation
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# best fit, keep ratio always
|
# best fit, keep ratio always
|
||||||
scaledpixmap = pixmap.scaled(target_size, Qt.KeepAspectRatio, Qt.FastTransformation)
|
scaledpixmap = pixmap.scaled(
|
||||||
|
target_size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.FastTransformation
|
||||||
|
)
|
||||||
viewer.setImage(scaledpixmap)
|
viewer.setImage(scaledpixmap)
|
||||||
return target_size
|
return target_size
|
||||||
|
|
||||||
def resetState(self):
|
def resetState(self) -> None:
|
||||||
"""Only called when the group of dupes has changed. We reset our
|
"""Only called when the group of dupes has changed. We reset our
|
||||||
controller internal state and buttons, center view on viewers."""
|
controller internal state and buttons, center view on viewers."""
|
||||||
self.selectedPixmap = QPixmap()
|
self.selectedPixmap = QPixmap()
|
||||||
@ -248,7 +255,7 @@ class BaseController(QObject):
|
|||||||
self.parent.verticalToolBar.buttonNormalSize.setEnabled(True)
|
self.parent.verticalToolBar.buttonNormalSize.setEnabled(True)
|
||||||
self.parent.verticalToolBar.buttonBestFit.setEnabled(False) # active mode by default
|
self.parent.verticalToolBar.buttonBestFit.setEnabled(False) # active mode by default
|
||||||
|
|
||||||
def resetViewersState(self):
|
def resetViewersState(self) -> None:
|
||||||
"""No item from the model, disable and clear everything."""
|
"""No item from the model, disable and clear everything."""
|
||||||
# only called by the details dialog
|
# only called by the details dialog
|
||||||
self.selectedPixmap = QPixmap()
|
self.selectedPixmap = QPixmap()
|
||||||
@ -277,36 +284,40 @@ class BaseController(QObject):
|
|||||||
self.referenceViewer.setEnabled(False)
|
self.referenceViewer.setEnabled(False)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def zoomIn(self):
|
def zoomIn(self) -> None:
|
||||||
self.scaleImagesBy(1.25)
|
self.scaleImagesBy(1.25)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def zoomOut(self):
|
def zoomOut(self) -> None:
|
||||||
self.scaleImagesBy(0.8)
|
self.scaleImagesBy(0.8)
|
||||||
|
|
||||||
@pyqtSlot(float)
|
@pyqtSlot(float)
|
||||||
def scaleImagesBy(self, factor):
|
def scaleImagesBy(self, factor: float) -> None:
|
||||||
"""Compute new scale from factor and scale."""
|
"""Compute new scale from factor and scale."""
|
||||||
self.current_scale *= factor
|
self.current_scale *= factor
|
||||||
self.selectedViewer.scaleBy(factor)
|
if self.selectedViewer is not None:
|
||||||
self.referenceViewer.scaleBy(factor)
|
self.selectedViewer.scaleBy(factor)
|
||||||
|
if self.referenceViewer is not None:
|
||||||
|
self.referenceViewer.scaleBy(factor)
|
||||||
self.updateButtons()
|
self.updateButtons()
|
||||||
|
|
||||||
@pyqtSlot(float)
|
@pyqtSlot(float)
|
||||||
def scaleImagesAt(self, scale):
|
def scaleImagesAt(self, scale: float) -> None:
|
||||||
"""Scale at a pre-computed scale."""
|
"""Scale at a pre-computed scale."""
|
||||||
self.current_scale = scale
|
self.current_scale = scale
|
||||||
self.selectedViewer.scaleAt(scale)
|
if self.selectedViewer is not None:
|
||||||
self.referenceViewer.scaleAt(scale)
|
self.selectedViewer.scaleAt(scale)
|
||||||
|
if self.referenceViewer is not None:
|
||||||
|
self.referenceViewer.scaleAt(scale)
|
||||||
self.updateButtons()
|
self.updateButtons()
|
||||||
|
|
||||||
def updateButtons(self):
|
def updateButtons(self) -> None:
|
||||||
self.parent.verticalToolBar.buttonZoomIn.setEnabled(self.current_scale < MAX_SCALE)
|
self.parent.verticalToolBar.buttonZoomIn.setEnabled(self.current_scale < MAX_SCALE)
|
||||||
self.parent.verticalToolBar.buttonZoomOut.setEnabled(self.current_scale > MIN_SCALE)
|
self.parent.verticalToolBar.buttonZoomOut.setEnabled(self.current_scale > MIN_SCALE)
|
||||||
self.parent.verticalToolBar.buttonNormalSize.setEnabled(round(self.current_scale, 1) != 1.0)
|
self.parent.verticalToolBar.buttonNormalSize.setEnabled(round(self.current_scale, 1) != 1.0)
|
||||||
self.parent.verticalToolBar.buttonBestFit.setEnabled(self.bestFit is False)
|
self.parent.verticalToolBar.buttonBestFit.setEnabled(self.bestFit is False)
|
||||||
|
|
||||||
def updateButtonsAsPerDimensions(self, previous_same_dimensions):
|
def updateButtonsAsPerDimensions(self, previous_same_dimensions: bool) -> None:
|
||||||
if not self.same_dimensions:
|
if not self.same_dimensions:
|
||||||
self.parent.verticalToolBar.buttonZoomIn.setEnabled(False)
|
self.parent.verticalToolBar.buttonZoomIn.setEnabled(False)
|
||||||
self.parent.verticalToolBar.buttonZoomOut.setEnabled(False)
|
self.parent.verticalToolBar.buttonZoomOut.setEnabled(False)
|
||||||
@ -323,7 +334,7 @@ class BaseController(QObject):
|
|||||||
self.parent.verticalToolBar.buttonImgSwap.setEnabled(False)
|
self.parent.verticalToolBar.buttonImgSwap.setEnabled(False)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def zoomBestFit(self):
|
def zoomBestFit(self) -> None:
|
||||||
"""Setup before scaling to bestfit"""
|
"""Setup before scaling to bestfit"""
|
||||||
self.setBestFit(True)
|
self.setBestFit(True)
|
||||||
self.current_scale = 1.0
|
self.current_scale = 1.0
|
||||||
@ -352,7 +363,7 @@ class BaseController(QObject):
|
|||||||
self.referenceViewer.bestFit = value
|
self.referenceViewer.bestFit = value
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def zoomNormalSize(self):
|
def zoomNormalSize(self) -> None:
|
||||||
self.setBestFit(False)
|
self.setBestFit(False)
|
||||||
self.current_scale = 1.0
|
self.current_scale = 1.0
|
||||||
|
|
||||||
@ -373,14 +384,14 @@ class BaseController(QObject):
|
|||||||
self.parent.verticalToolBar.buttonNormalSize.setEnabled(False)
|
self.parent.verticalToolBar.buttonNormalSize.setEnabled(False)
|
||||||
self.parent.verticalToolBar.buttonBestFit.setEnabled(True)
|
self.parent.verticalToolBar.buttonBestFit.setEnabled(True)
|
||||||
|
|
||||||
def centerViews(self, only_selected=False):
|
def centerViews(self, only_selected: bool = False) -> None:
|
||||||
self.selectedViewer.centerViewAndUpdate()
|
self.selectedViewer.centerViewAndUpdate()
|
||||||
if only_selected:
|
if only_selected:
|
||||||
return
|
return
|
||||||
self.referenceViewer.centerViewAndUpdate()
|
self.referenceViewer.centerViewAndUpdate()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def swapImages(self):
|
def swapImages(self) -> None:
|
||||||
# swap the columns in the details table as well
|
# swap the columns in the details table as well
|
||||||
self.parent.tableView.horizontalHeader().swapSections(0, 1)
|
self.parent.tableView.horizontalHeader().swapSections(0, 1)
|
||||||
|
|
||||||
@ -388,17 +399,17 @@ class BaseController(QObject):
|
|||||||
class QWidgetController(BaseController):
|
class QWidgetController(BaseController):
|
||||||
"""Specialized version for QWidget-based viewers."""
|
"""Specialized version for QWidget-based viewers."""
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QObject) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
def _updateImage(self, *args):
|
def _updateImage(self, *args) -> Union[QSize, None]:
|
||||||
ret = super()._updateImage(*args)
|
ret = super()._updateImage(*args)
|
||||||
# Fix alignment when resizing window
|
# Fix alignment when resizing window
|
||||||
self.centerViews()
|
self.centerViews()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@pyqtSlot(QPointF)
|
@pyqtSlot(QPointF)
|
||||||
def onDraggedMouse(self, delta):
|
def onDraggedMouse(self, delta) -> None:
|
||||||
if not self.same_dimensions:
|
if not self.same_dimensions:
|
||||||
return
|
return
|
||||||
if self.sender() is self.referenceViewer:
|
if self.sender() is self.referenceViewer:
|
||||||
@ -407,7 +418,7 @@ class QWidgetController(BaseController):
|
|||||||
self.referenceViewer.onDraggedMouse(delta)
|
self.referenceViewer.onDraggedMouse(delta)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def swapImages(self):
|
def swapImages(self) -> None:
|
||||||
self.selectedViewer._pixmap.swap(self.referenceViewer._pixmap)
|
self.selectedViewer._pixmap.swap(self.referenceViewer._pixmap)
|
||||||
self.selectedViewer.centerViewAndUpdate()
|
self.selectedViewer.centerViewAndUpdate()
|
||||||
self.referenceViewer.centerViewAndUpdate()
|
self.referenceViewer.centerViewAndUpdate()
|
||||||
@ -417,15 +428,15 @@ class QWidgetController(BaseController):
|
|||||||
class ScrollAreaController(BaseController):
|
class ScrollAreaController(BaseController):
|
||||||
"""Specialized version fro QLabel-based viewers."""
|
"""Specialized version fro QLabel-based viewers."""
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QObject) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
def _setupConnections(self):
|
def _setupConnections(self) -> None:
|
||||||
super()._setupConnections()
|
super()._setupConnections()
|
||||||
self.selectedViewer.connectScrollBars()
|
self.selectedViewer.connectScrollBars()
|
||||||
self.referenceViewer.connectScrollBars()
|
self.referenceViewer.connectScrollBars()
|
||||||
|
|
||||||
def updateBothImages(self, same_group=False):
|
def updateBothImages(self, same_group: bool = False) -> None:
|
||||||
super().updateBothImages(same_group)
|
super().updateBothImages(same_group)
|
||||||
if not self.referenceViewer.isEnabled():
|
if not self.referenceViewer.isEnabled():
|
||||||
return
|
return
|
||||||
@ -433,7 +444,7 @@ class ScrollAreaController(BaseController):
|
|||||||
self.referenceViewer._verticalScrollBar.setValue(self.selectedViewer._verticalScrollBar.value())
|
self.referenceViewer._verticalScrollBar.setValue(self.selectedViewer._verticalScrollBar.value())
|
||||||
|
|
||||||
@pyqtSlot(QPoint)
|
@pyqtSlot(QPoint)
|
||||||
def onDraggedMouse(self, delta):
|
def onDraggedMouse(self, delta) -> None:
|
||||||
self.selectedViewer.ignore_signal = True
|
self.selectedViewer.ignore_signal = True
|
||||||
self.referenceViewer.ignore_signal = True
|
self.referenceViewer.ignore_signal = True
|
||||||
|
|
||||||
@ -450,21 +461,21 @@ class ScrollAreaController(BaseController):
|
|||||||
self.referenceViewer.ignore_signal = False
|
self.referenceViewer.ignore_signal = False
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def swapImages(self):
|
def swapImages(self) -> None:
|
||||||
self.referenceViewer._pixmap.swap(self.selectedViewer._pixmap)
|
self.referenceViewer._pixmap.swap(self.selectedViewer._pixmap)
|
||||||
self.referenceViewer.setCachedPixmap()
|
self.referenceViewer.setCachedPixmap()
|
||||||
self.selectedViewer.setCachedPixmap()
|
self.selectedViewer.setCachedPixmap()
|
||||||
super().swapImages()
|
super().swapImages()
|
||||||
|
|
||||||
@pyqtSlot(float, QPointF)
|
@pyqtSlot(float, QPointF)
|
||||||
def onMouseWheel(self, scale, delta):
|
def onMouseWheel(self, scale: float, delta: QPointF) -> None:
|
||||||
self.scaleImagesAt(scale)
|
self.scaleImagesAt(scale)
|
||||||
self.selectedViewer.adjustScrollBarsScaled(delta)
|
self.selectedViewer.adjustScrollBarsScaled(delta)
|
||||||
# Signal from scrollbars will automatically change the other:
|
# Signal from scrollbars will automatically change the other:
|
||||||
# self.referenceViewer.adjustScrollBarsScaled(delta)
|
# self.referenceViewer.adjustScrollBarsScaled(delta)
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def onVScrollBarChanged(self, value):
|
def onVScrollBarChanged(self, value: int) -> None:
|
||||||
if not self.same_dimensions:
|
if not self.same_dimensions:
|
||||||
return
|
return
|
||||||
if self.sender() is self.referenceViewer._verticalScrollBar:
|
if self.sender() is self.referenceViewer._verticalScrollBar:
|
||||||
@ -475,7 +486,7 @@ class ScrollAreaController(BaseController):
|
|||||||
self.referenceViewer._verticalScrollBar.setValue(value)
|
self.referenceViewer._verticalScrollBar.setValue(value)
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def onHScrollBarChanged(self, value):
|
def onHScrollBarChanged(self, value: int) -> None:
|
||||||
if not self.same_dimensions:
|
if not self.same_dimensions:
|
||||||
return
|
return
|
||||||
if self.sender() is self.referenceViewer._horizontalScrollBar:
|
if self.sender() is self.referenceViewer._horizontalScrollBar:
|
||||||
@ -486,13 +497,13 @@ class ScrollAreaController(BaseController):
|
|||||||
self.referenceViewer._horizontalScrollBar.setValue(value)
|
self.referenceViewer._horizontalScrollBar.setValue(value)
|
||||||
|
|
||||||
@pyqtSlot(float)
|
@pyqtSlot(float)
|
||||||
def scaleImagesBy(self, factor):
|
def scaleImagesBy(self, factor: float) -> None:
|
||||||
super().scaleImagesBy(factor)
|
super().scaleImagesBy(factor)
|
||||||
# The other is automatically updated via sigals
|
# The other is automatically updated via sigals
|
||||||
self.selectedViewer.adjustScrollBarsFactor(factor)
|
self.selectedViewer.adjustScrollBarsFactor(factor)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def zoomBestFit(self):
|
def zoomBestFit(self) -> None:
|
||||||
# Disable scrollbars to avoid GridLayout size rounding glitch
|
# Disable scrollbars to avoid GridLayout size rounding glitch
|
||||||
super().zoomBestFit()
|
super().zoomBestFit()
|
||||||
if self.referencePixmap.isNull():
|
if self.referencePixmap.isNull():
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
from typing import Callable, Union, cast
|
||||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog,
|
QDialog,
|
||||||
@ -28,11 +29,12 @@ from PyQt5.QtWidgets import (
|
|||||||
QGroupBox,
|
QGroupBox,
|
||||||
QFormLayout,
|
QFormLayout,
|
||||||
)
|
)
|
||||||
from PyQt5.QtGui import QPixmap, QIcon
|
from PyQt5.QtGui import QPixmap, QIcon, QShowEvent
|
||||||
from hscommon import desktop, plat
|
from hscommon import desktop, plat
|
||||||
|
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from hscommon.plat import ISLINUX
|
from hscommon.plat import ISLINUX
|
||||||
|
from qt import app
|
||||||
from qt.util import horizontal_wrap, move_to_screen_center
|
from qt.util import horizontal_wrap, move_to_screen_center
|
||||||
from qt.preferences import get_langnames
|
from qt.preferences import get_langnames
|
||||||
from enum import Flag, auto
|
from enum import Flag, auto
|
||||||
@ -52,8 +54,10 @@ class Sections(Flag):
|
|||||||
|
|
||||||
|
|
||||||
class PreferencesDialogBase(QDialog):
|
class PreferencesDialogBase(QDialog):
|
||||||
def __init__(self, parent, app, **kwargs):
|
def __init__(self, parent: QWidget, app: "app.DupeGuru", **kwargs) -> None:
|
||||||
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
|
flags = Qt.WindowType(
|
||||||
|
Qt.WindowType.CustomizeWindowHint | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowSystemMenuHint
|
||||||
|
)
|
||||||
super().__init__(parent, flags, **kwargs)
|
super().__init__(parent, flags, **kwargs)
|
||||||
self.app = app
|
self.app = app
|
||||||
self.supportedLanguages = dict(sorted(get_langnames().items(), key=lambda item: item[1]))
|
self.supportedLanguages = dict(sorted(get_langnames().items(), key=lambda item: item[1]))
|
||||||
@ -65,7 +69,7 @@ class PreferencesDialogBase(QDialog):
|
|||||||
self.buttonBox.accepted.connect(self.accept)
|
self.buttonBox.accepted.connect(self.accept)
|
||||||
self.buttonBox.rejected.connect(self.reject)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
|
|
||||||
def _setupFilterHardnessBox(self):
|
def _setupFilterHardnessBox(self) -> None:
|
||||||
self.filterHardnessHLayout = QHBoxLayout()
|
self.filterHardnessHLayout = QHBoxLayout()
|
||||||
self.filterHardnessLabel = QLabel(self)
|
self.filterHardnessLabel = QLabel(self)
|
||||||
self.filterHardnessLabel.setText(tr("Filter Hardness:"))
|
self.filterHardnessLabel.setText(tr("Filter Hardness:"))
|
||||||
@ -84,7 +88,7 @@ class PreferencesDialogBase(QDialog):
|
|||||||
self.filterHardnessSlider.setMinimum(1)
|
self.filterHardnessSlider.setMinimum(1)
|
||||||
self.filterHardnessSlider.setMaximum(100)
|
self.filterHardnessSlider.setMaximum(100)
|
||||||
self.filterHardnessSlider.setTracking(True)
|
self.filterHardnessSlider.setTracking(True)
|
||||||
self.filterHardnessSlider.setOrientation(Qt.Horizontal)
|
self.filterHardnessSlider.setOrientation(Qt.Orientation.Horizontal)
|
||||||
self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessSlider)
|
self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessSlider)
|
||||||
self.filterHardnessLabel = QLabel(self)
|
self.filterHardnessLabel = QLabel(self)
|
||||||
self.filterHardnessLabel.setText("100")
|
self.filterHardnessLabel.setText("100")
|
||||||
@ -104,7 +108,7 @@ class PreferencesDialogBase(QDialog):
|
|||||||
self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub2)
|
self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub2)
|
||||||
self.filterHardnessHLayout.addLayout(self.filterHardnessVLayout)
|
self.filterHardnessHLayout.addLayout(self.filterHardnessVLayout)
|
||||||
|
|
||||||
def _setupBottomPart(self):
|
def _setupBottomPart(self) -> None:
|
||||||
# The bottom part of the pref panel is always the same in all editions.
|
# The bottom part of the pref panel is always the same in all editions.
|
||||||
self.copyMoveLabel = QLabel(self)
|
self.copyMoveLabel = QLabel(self)
|
||||||
self.copyMoveLabel.setText(tr("Copy and Move:"))
|
self.copyMoveLabel.setText(tr("Copy and Move:"))
|
||||||
@ -120,7 +124,7 @@ class PreferencesDialogBase(QDialog):
|
|||||||
self.customCommandEdit = QLineEdit(self)
|
self.customCommandEdit = QLineEdit(self)
|
||||||
self.widgetsVLayout.addWidget(self.customCommandEdit)
|
self.widgetsVLayout.addWidget(self.customCommandEdit)
|
||||||
|
|
||||||
def _setupDisplayPage(self):
|
def _setupDisplayPage(self) -> None:
|
||||||
self.ui_groupbox = QGroupBox("&" + tr("General Interface"))
|
self.ui_groupbox = QGroupBox("&" + tr("General Interface"))
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
self.languageLabel = QLabel(tr("Language:"), self)
|
self.languageLabel = QLabel(tr("Language:"), self)
|
||||||
@ -171,7 +175,7 @@ On MacOS, the tab bar will fill up the window's width instead."
|
|||||||
formlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color)
|
formlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color)
|
||||||
self.result_table_delta_foreground_color = ColorPickerButton(self)
|
self.result_table_delta_foreground_color = ColorPickerButton(self)
|
||||||
formlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color)
|
formlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color)
|
||||||
formlayout.setLabelAlignment(Qt.AlignLeft)
|
formlayout.setLabelAlignment(Qt.AlignmentFlag.AlignLeft)
|
||||||
|
|
||||||
# Keep same vertical spacing as parent layout for consistency
|
# Keep same vertical spacing as parent layout for consistency
|
||||||
formlayout.setVerticalSpacing(self.displayVLayout.spacing())
|
formlayout.setVerticalSpacing(self.displayVLayout.spacing())
|
||||||
@ -213,7 +217,7 @@ use the modifier key to drag the floating window around"
|
|||||||
details_groupbox.setLayout(self.details_groupbox_layout)
|
details_groupbox.setLayout(self.details_groupbox_layout)
|
||||||
self.displayVLayout.addWidget(details_groupbox)
|
self.displayVLayout.addWidget(details_groupbox)
|
||||||
|
|
||||||
def _setupDebugPage(self):
|
def _setupDebugPage(self) -> None:
|
||||||
self._setupAddCheckbox("debugModeBox", tr("Debug mode (restart required)"))
|
self._setupAddCheckbox("debugModeBox", tr("Debug mode (restart required)"))
|
||||||
self._setupAddCheckbox("profile_scan_box", tr("Profile scan operation"))
|
self._setupAddCheckbox("profile_scan_box", tr("Profile scan operation"))
|
||||||
self.profile_scan_box.setToolTip(tr("Profile the scan operation and save logs for optimization."))
|
self.profile_scan_box.setToolTip(tr("Profile the scan operation and save logs for optimization."))
|
||||||
@ -221,22 +225,22 @@ use the modifier key to drag the floating window around"
|
|||||||
self.debugVLayout.addWidget(self.profile_scan_box)
|
self.debugVLayout.addWidget(self.profile_scan_box)
|
||||||
self.debug_location_label = QLabel(
|
self.debug_location_label = QLabel(
|
||||||
tr('Logs located in: <a href="{}">{}</a>').format(self.app.model.appdata, self.app.model.appdata),
|
tr('Logs located in: <a href="{}">{}</a>').format(self.app.model.appdata, self.app.model.appdata),
|
||||||
wordWrap=True,
|
|
||||||
)
|
)
|
||||||
|
self.debug_location_label.setWordWrap(True)
|
||||||
self.debugVLayout.addWidget(self.debug_location_label)
|
self.debugVLayout.addWidget(self.debug_location_label)
|
||||||
|
|
||||||
def _setupAddCheckbox(self, name, label, parent=None):
|
def _setupAddCheckbox(self, name: str, label: str, parent: Union[QWidget, None] = None) -> None:
|
||||||
if parent is None:
|
if parent is None:
|
||||||
parent = self
|
parent = self
|
||||||
cb = QCheckBox(parent)
|
cb = QCheckBox(parent)
|
||||||
cb.setText(label)
|
cb.setText(label)
|
||||||
setattr(self, name, cb)
|
setattr(self, name, cb)
|
||||||
|
|
||||||
def _setupPreferenceWidgets(self):
|
def _setupPreferenceWidgets(self) -> None:
|
||||||
# Edition-specific
|
# Edition-specific
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _setupUi(self):
|
def _setupUi(self) -> None:
|
||||||
self.setWindowTitle(tr("Options"))
|
self.setWindowTitle(tr("Options"))
|
||||||
self.setSizeGripEnabled(False)
|
self.setSizeGripEnabled(False)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
@ -262,7 +266,7 @@ use the modifier key to drag the floating window around"
|
|||||||
)
|
)
|
||||||
self.mainVLayout.addWidget(self.tabwidget)
|
self.mainVLayout.addWidget(self.tabwidget)
|
||||||
self.mainVLayout.addWidget(self.buttonBox)
|
self.mainVLayout.addWidget(self.buttonBox)
|
||||||
self.layout().setSizeConstraint(QLayout.SetFixedSize)
|
self.layout().setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
|
||||||
self.tabwidget.addTab(self.page_general, tr("General"))
|
self.tabwidget.addTab(self.page_general, tr("General"))
|
||||||
self.tabwidget.addTab(self.page_display, tr("Display"))
|
self.tabwidget.addTab(self.page_display, tr("Display"))
|
||||||
self.tabwidget.addTab(self.page_debug, tr("Debug"))
|
self.tabwidget.addTab(self.page_debug, tr("Debug"))
|
||||||
@ -270,20 +274,20 @@ use the modifier key to drag the floating window around"
|
|||||||
self.widgetsVLayout.addStretch(0)
|
self.widgetsVLayout.addStretch(0)
|
||||||
self.debugVLayout.addStretch(0)
|
self.debugVLayout.addStretch(0)
|
||||||
|
|
||||||
def _load(self, prefs, setchecked, section):
|
def _load(self, prefs: Preferences, setchecked: Callable[[QCheckBox, bool], None], section: Sections) -> None:
|
||||||
# Edition-specific
|
# Edition-specific
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _save(self, prefs, ischecked):
|
def _save(self, prefs: Preferences, ischecked: Callable[[QCheckBox], bool]) -> None:
|
||||||
# Edition-specific
|
# Edition-specific
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def load(self, prefs=None, section=Sections.ALL):
|
def load(self, prefs: Union[Preferences, None] = None, section: Sections = Sections.ALL) -> None:
|
||||||
if prefs is None:
|
if prefs is None:
|
||||||
prefs = self.app.prefs
|
prefs = self.app.prefs
|
||||||
|
|
||||||
def setchecked(cb, b):
|
def setchecked(cb: QCheckBox, b: bool) -> None:
|
||||||
cb.setCheckState(Qt.Checked if b else Qt.Unchecked)
|
cb.setCheckState(Qt.CheckState.Checked if b else Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
if section & Sections.GENERAL:
|
if section & Sections.GENERAL:
|
||||||
self.filterHardnessSlider.setValue(prefs.filter_hardness)
|
self.filterHardnessSlider.setValue(prefs.filter_hardness)
|
||||||
@ -323,12 +327,12 @@ use the modifier key to drag the floating window around"
|
|||||||
setchecked(self.profile_scan_box, prefs.profile_scan)
|
setchecked(self.profile_scan_box, prefs.profile_scan)
|
||||||
self._load(prefs, setchecked, section)
|
self._load(prefs, setchecked, section)
|
||||||
|
|
||||||
def save(self):
|
def save(self) -> None:
|
||||||
prefs = self.app.prefs
|
prefs = self.app.prefs
|
||||||
prefs.filter_hardness = self.filterHardnessSlider.value()
|
prefs.filter_hardness = self.filterHardnessSlider.value()
|
||||||
|
|
||||||
def ischecked(cb):
|
def ischecked(cb: QCheckBox) -> bool:
|
||||||
return cb.checkState() == Qt.Checked
|
return cb.checkState() == Qt.CheckState.Checked
|
||||||
|
|
||||||
prefs.mix_file_kind = ischecked(self.mixFileKindBox)
|
prefs.mix_file_kind = ischecked(self.mixFileKindBox)
|
||||||
prefs.use_regexp = ischecked(self.useRegexpBox)
|
prefs.use_regexp = ischecked(self.useRegexpBox)
|
||||||
@ -363,11 +367,11 @@ use the modifier key to drag the floating window around"
|
|||||||
self.app.prefs.language = lang_code
|
self.app.prefs.language = lang_code
|
||||||
self._save(prefs, ischecked)
|
self._save(prefs, ischecked)
|
||||||
|
|
||||||
def resetToDefaults(self, section_to_update):
|
def resetToDefaults(self, section_to_update: Sections) -> None:
|
||||||
self.load(Preferences(), section_to_update)
|
self.load(Preferences(), section_to_update)
|
||||||
|
|
||||||
# --- Events
|
# --- Events
|
||||||
def buttonClicked(self, button):
|
def buttonClicked(self, button: QDialogButtonBox) -> None:
|
||||||
role = self.buttonBox.buttonRole(button)
|
role = self.buttonBox.buttonRole(button)
|
||||||
if role == QDialogButtonBox.ResetRole:
|
if role == QDialogButtonBox.ResetRole:
|
||||||
current_tab = self.tabwidget.currentWidget()
|
current_tab = self.tabwidget.currentWidget()
|
||||||
@ -380,30 +384,32 @@ use the modifier key to drag the floating window around"
|
|||||||
section_to_update = Sections.DEBUG
|
section_to_update = Sections.DEBUG
|
||||||
self.resetToDefaults(section_to_update)
|
self.resetToDefaults(section_to_update)
|
||||||
|
|
||||||
def showEvent(self, event):
|
def showEvent(self, event: QShowEvent) -> None:
|
||||||
# have to do this here as the frameGeometry is not correct until shown
|
# have to do this here as the frameGeometry is not correct until shown
|
||||||
move_to_screen_center(self)
|
move_to_screen_center(self)
|
||||||
super().showEvent(event)
|
super().showEvent(event)
|
||||||
|
|
||||||
|
|
||||||
class ColorPickerButton(QPushButton):
|
class ColorPickerButton(QPushButton):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent: QWidget) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.parent = parent
|
self.setParent(parent)
|
||||||
self.color = None
|
self.color = None
|
||||||
self.clicked.connect(self.onClicked)
|
self.clicked.connect(self.onClicked)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def onClicked(self):
|
def onClicked(self) -> None:
|
||||||
color = QColorDialog.getColor(self.color if self.color is not None else Qt.white, self.parent)
|
color = QColorDialog.getColor(
|
||||||
|
self.color if self.color is not None else Qt.GlobalColor.white, cast(QWidget, self.parent())
|
||||||
|
)
|
||||||
self.setColor(color)
|
self.setColor(color)
|
||||||
|
|
||||||
def setColor(self, color):
|
def setColor(self, color) -> None:
|
||||||
size = QSize(16, 16)
|
size = QSize(16, 16)
|
||||||
px = QPixmap(size)
|
px = QPixmap(size)
|
||||||
if color is None:
|
if color is None:
|
||||||
size.width = 0
|
size.setWidth(0)
|
||||||
size.height = 0
|
size.setHeight(0)
|
||||||
elif not color.isValid():
|
elif not color.isValid():
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user