diff --git a/core/app.py b/core/app.py index 55d9c308..204dd913 100644 --- a/core/app.py +++ b/core/app.py @@ -405,6 +405,12 @@ class DupeGuru(Broadcaster): while delete_if_empty(path, ['.DS_Store']): path = path.parent() + def clear_picture_cache(self): + from core_pe.cache import Cache + cache = Cache(self.options['cache_path']) + cache.clear() + cache.close() + def copy_or_move(self, dupe, copy: bool, destination: str, dest_type: DestType): source_path = dupe.path location_path = first(p for p in self.directories if dupe.path in p) diff --git a/core_pe/scanner.py b/core_pe/scanner.py index 44c3a5e4..dcc9dd9c 100644 --- a/core_pe/scanner.py +++ b/core_pe/scanner.py @@ -9,7 +9,6 @@ from hscommon.trans import tr from core.scanner import Scanner, ScanType, ScanOption from . import matchblock, matchexif -from .cache import Cache class ScannerPE(Scanner): cache_path = None @@ -31,8 +30,3 @@ class ScannerPE(Scanner): else: raise Exception("Invalid scan type") - def clear_picture_cache(self): - cache = Cache(self.cache_path) - cache.clear() - cache.close() - diff --git a/qt/base/app.py b/qt/base/app.py index 2366afb1..23697593 100644 --- a/qt/base/app.py +++ b/qt/base/app.py @@ -36,7 +36,6 @@ class DupeGuru(QObject): NAME = '' DETAILS_DIALOG_CLASS = None - RESULT_WINDOW_CLASS = ResultWindow RESULT_MODEL_CLASS = None PREFERENCES_CLASS = None PREFERENCES_DIALOG_CLASS = None @@ -80,6 +79,7 @@ class DupeGuru(QObject): ('actionQuit', 'Ctrl+Q', '', tr("Quit"), self.quitTriggered), ('actionPreferences', 'Ctrl+P', '', tr("Options"), self.preferencesTriggered), ('actionIgnoreList', '', '', tr("Ignore List"), self.ignoreListTriggered), + ('actionClearPictureCache', 'Ctrl+Shift+P', '', tr("Clear Picture Cache"), self.clearPictureCacheTriggered), ('actionShowHelp', 'F1', '', tr("dupeGuru Help"), self.showHelpTriggered), ('actionAbout', '', '', tr("About dupeGuru"), self.showAboutBoxTriggered), ('actionOpenDebugLog', '', '', tr("Open Debug Log"), self.openDebugLogTriggered), @@ -135,6 +135,14 @@ class DupeGuru(QObject): self.prefs.save() self.model.save() + def clearPictureCacheTriggered(self): + title = tr("Clear Picture Cache") + msg = tr("Do you really want to remove all your cached picture analysis?") + if self.confirm(title, msg, QMessageBox.No): + self.model.clear_picture_cache() + active = QApplication.activeWindow() + QMessageBox.information(active, title, tr("Picture cache cleared.")) + def ignoreListTriggered(self): self.model.ignore_list_dialog.show() @@ -186,7 +194,7 @@ class DupeGuru(QObject): if self.resultWindow is not None: self.resultWindow.close() self.resultWindow.setParent(None) - self.resultWindow = self.RESULT_WINDOW_CLASS(self.directories_dialog, self) + self.resultWindow = ResultWindow(self.directories_dialog, self) self.details_dialog = self.DETAILS_DIALOG_CLASS(self.resultWindow, self) def show_results_window(self): diff --git a/qt/base/cxfreeze_fix.py b/qt/base/cxfreeze_fix.py deleted file mode 100644 index d659d077..00000000 --- a/qt/base/cxfreeze_fix.py +++ /dev/null @@ -1,8 +0,0 @@ -# cxfreeze has some problems detecting all dependencies. -# This modules explicitly import those problematic modules. -# flake8: noqa - -import xml.etree.ElementPath -import gzip - -import os diff --git a/qt/base/directories_dialog.py b/qt/base/directories_dialog.py index 95eaf71d..db61d4fa 100644 --- a/qt/base/directories_dialog.py +++ b/qt/base/directories_dialog.py @@ -83,6 +83,8 @@ class DirectoriesDialog(QMainWindow): self.menuFile.addAction(self.actionLoadResults) self.menuFile.addAction(self.menuLoadRecent.menuAction()) self.menuFile.addSeparator() + self.menuFile.addAction(self.app.actionClearPictureCache) + self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menuView.addAction(self.app.actionPreferences) self.menuView.addAction(self.actionShowResultsWindow) diff --git a/qt/pe/app.py b/qt/pe/app.py deleted file mode 100644 index cb733c1d..00000000 --- a/qt/pe/app.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2016 Hardcoded Software (http://www.hardcoded.net) -# -# This software is licensed under the "GPLv3" License as described in the "LICENSE" file, -# which should be included with this package. The terms are also available at -# http://www.gnu.org/licenses/gpl-3.0.html - -import logging - -from PyQt5.QtGui import QImage, QImageReader, QTransform - -from core_pe import __appname__ -from core_pe.photo import Photo as PhotoBase -from core_pe.app import DupeGuru as DupeGuruModel - -from ..base.app import DupeGuru as DupeGuruBase -from .block import getblocks -from .details_dialog import DetailsDialog -from .result_window import ResultWindow -from .results_model import ResultsModel -from .preferences import Preferences -from .preferences_dialog import PreferencesDialog - -class File(PhotoBase): - def _plat_get_dimensions(self): - try: - ir = QImageReader(str(self.path)) - size = ir.size() - if size.isValid(): - return (size.width(), size.height()) - else: - return (0, 0) - except EnvironmentError: - logging.warning("Could not read image '%s'", str(self.path)) - return (0, 0) - - def _plat_get_blocks(self, block_count_per_side, orientation): - image = QImage(str(self.path)) - image = image.convertToFormat(QImage.Format_RGB888) - # MYSTERY TO SOLVE: For reasons I cannot explain, orientations 5 and 7 don't work for - # duplicate scanning. The transforms seems to work fine (if I try to save the image after - # the transform, we see that the image has been correctly flipped and rotated), but the - # analysis part yields wrong blocks. I spent enought time with this feature, so I'll leave - # like that for now. (by the way, orientations 5 and 7 work fine under Cocoa) - if 2 <= orientation <= 8: - t = QTransform() - if orientation == 2: - t.scale(-1, 1) - elif orientation == 3: - t.rotate(180) - elif orientation == 4: - t.scale(1, -1) - elif orientation == 5: - t.scale(-1, 1) - t.rotate(90) - elif orientation == 6: - t.rotate(90) - elif orientation == 7: - t.scale(-1, 1) - t.rotate(270) - elif orientation == 8: - t.rotate(270) - image = image.transformed(t) - return getblocks(image, block_count_per_side) - - -class DupeGuru(DupeGuruBase): - MODELCLASS = DupeGuruModel - EDITION = 'pe' - LOGO_NAME = 'logo_pe' - NAME = __appname__ - - DETAILS_DIALOG_CLASS = DetailsDialog - RESULT_WINDOW_CLASS = ResultWindow - RESULT_MODEL_CLASS = ResultsModel - PREFERENCES_CLASS = Preferences - PREFERENCES_DIALOG_CLASS = PreferencesDialog - - def _setup(self): - self.model.fileclasses = [File] - DupeGuruBase._setup(self) - self.directories_dialog.menuFile.insertAction( - self.directories_dialog.actionLoadResults, self.resultWindow.actionClearPictureCache - ) - - def _update_options(self): - DupeGuruBase._update_options(self) - self.model.options['scan_type'] = self.prefs.scan_type - self.model.options['match_scaled'] = self.prefs.match_scaled - self.model.options['threshold'] = self.prefs.filter_hardness - diff --git a/qt/pe/result_window.py b/qt/pe/result_window.py deleted file mode 100644 index f5aca049..00000000 --- a/qt/pe/result_window.py +++ /dev/null @@ -1,30 +0,0 @@ -# Created By: Virgil Dupras -# Created On: 2009-05-23 -# Copyright 2015 Hardcoded Software (http://www.hardcoded.net) -# -# This software is licensed under the "GPLv3" License as described in the "LICENSE" file, -# which should be included with this package. The terms are also available at -# http://www.gnu.org/licenses/gpl-3.0.html - -from PyQt5.QtWidgets import QMessageBox, QAction - -from hscommon.trans import trget -from ..base.result_window import ResultWindow as ResultWindowBase - -tr = trget('ui') - -class ResultWindow(ResultWindowBase): - def _setupMenu(self): - ResultWindowBase._setupMenu(self) - self.actionClearPictureCache = QAction(tr("Clear Picture Cache"), self) - self.actionClearPictureCache.setShortcut('Ctrl+Shift+P') - self.menuFile.insertAction(self.actionSaveResults, self.actionClearPictureCache) - self.actionClearPictureCache.triggered.connect(self.clearPictureCacheTriggered) - - def clearPictureCacheTriggered(self): - title = tr("Clear Picture Cache") - msg = tr("Do you really want to remove all your cached picture analysis?") - if self.app.confirm(title, msg, QMessageBox.No): - self.app.model.scanner.clear_picture_cache() - QMessageBox.information(self, title, tr("Picture cache cleared.")) - \ No newline at end of file