diff --git a/core/app.py b/core/app.py index 1de58221..586602e6 100644 --- a/core/app.py +++ b/core/app.py @@ -41,7 +41,16 @@ class DestType: Absolute = 2 class DupeGuru(RegistrableApplication, Broadcaster): - def __init__(self, data_module, appdata): + #--- View interface + # open_path(path) + # reveal_path(path) + # start_job(jobid, func, *args) ( func(j, *args) ) + # get_default(key_name, fallback_value=None) + # set_default(key_name, value) + # show_extra_fairware_reminder() + + def __init__(self, view, data_module, appdata): + self.view = view if self.get_default(DEBUG_MODE_PREFERENCE, False): logging.getLogger().setLevel(logging.DEBUG) logging.debug("Debug mode enabled") @@ -122,14 +131,6 @@ class DupeGuru(RegistrableApplication, Broadcaster): if jobid in {JOB_COPY, JOB_MOVE, JOB_DELETE}: self.notify('problems_changed') - @staticmethod - def _open_path(path): - raise NotImplementedError() - - @staticmethod - def _reveal_path(path): - raise NotImplementedError() - @staticmethod def _remove_hardlink_dupes(files): seen_inodes = set() @@ -151,19 +152,6 @@ class DupeGuru(RegistrableApplication, Broadcaster): self.selected_dupes = dupes self.notify('dupes_selected') - def _start_job(self, jobid, func, *args): - # func(j, *args) - raise NotImplementedError() - - def _get_default(self, key_name, fallback_value=None): - raise NotImplementedError() - - def _set_default(self, key_name, value): - raise NotImplementedError() - - def _show_extra_fairware_reminder(self): - raise NotImplementedError() - #--- Public def add_directory(self, d): try: @@ -194,7 +182,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def show_extra_fairware_reminder_if_needed(self): if self.results.mark_count > 100 and self.should_show_fairware_reminder: - self._show_extra_fairware_reminder() + self.view.show_extra_fairware_reminder() def clean_empty_dirs(self, path): if self.options['clean_empty_dirs']: @@ -234,11 +222,11 @@ class DupeGuru(RegistrableApplication, Broadcaster): self.show_extra_fairware_reminder_if_needed() jobid = JOB_COPY if copy else JOB_MOVE - self._start_job(jobid, do) + self.view.start_job(jobid, do) def delete_marked(self, replace_with_hardlinks=False): self.show_extra_fairware_reminder_if_needed() - self._start_job(JOB_DELETE, self._do_delete, replace_with_hardlinks) + self.view.start_job(JOB_DELETE, self._do_delete, replace_with_hardlinks) def export_to_xhtml(self, column_ids): column_ids = [colid for colid in column_ids if colid.isdigit()] @@ -288,7 +276,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def load_from(self, filename): def do(j): self.results.load_from_xml(filename, self._get_file, j) - self._start_job(JOB_LOAD, do) + self.view.start_job(JOB_LOAD, do) def make_selected_reference(self): dupes = self.without_ref(self.selected_dupes) @@ -321,7 +309,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def open_selected(self): if self.selected_dupes: - self._open_path(self.selected_dupes[0].path) + self.view.open_path(self.selected_dupes[0].path) def purge_ignore_list(self): self.scanner.ignore_list.Filter(lambda f,s:op.exists(f) and op.exists(s)) @@ -360,7 +348,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def reveal_selected(self): if self.selected_dupes: - self._reveal_path(self.selected_dupes[0].path) + self.view.reveal_path(self.selected_dupes[0].path) def save(self): if not op.exists(self.appdata): @@ -388,7 +376,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): raise NoScannableFileError() self.results.groups = [] self._results_changed() - self._start_job(JOB_SCAN, do) + self.view.start_job(JOB_SCAN, do) def toggle_selected_mark_state(self): for dupe in self.selected_dupes: @@ -399,7 +387,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): return [dupe for dupe in dupes if self.results.get_group_of_duplicate(dupe).ref is not dupe] def get_default(self, key, fallback_value=None): - result = nonone(self._get_default(key), fallback_value) + result = nonone(self.view.get_default(key), fallback_value) if fallback_value is not None and not isinstance(result, type(fallback_value)): # we don't want to end up with garbage values from the prefs try: @@ -409,7 +397,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): return result def set_default(self, key, value): - self._set_default(key, value) + self.view.set_default(key, value) #--- Properties @property diff --git a/core/app_cocoa.py b/core/app_cocoa.py index adf79231..74b34ef9 100644 --- a/core/app_cocoa.py +++ b/core/app_cocoa.py @@ -27,46 +27,51 @@ JOBID2TITLE = { app.JOB_DELETE: tr("Sending to Trash"), } -class DupeGuru(app.DupeGuru): - def __init__(self, data_module, appdata_subdir): - logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s') - install_exception_hook() - appsupport = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0] - appdata = op.join(appsupport, appdata_subdir) - app.DupeGuru.__init__(self, data_module, appdata) - self.progress = cocoa.ThreadedJobPerformer() +class DupeGuruView: + def __init__(self, app): + self.app = app - #--- Override @staticmethod - def _open_path(path): + def open_path(path): NSWorkspace.sharedWorkspace().openFile_(str(path)) @staticmethod - def _reveal_path(path): + def reveal_path(path): NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(str(path), '') - def _start_job(self, jobid, func, *args): + def start_job(self, jobid, func, *args): try: - j = self.progress.create_job() + j = self.app.progress.create_job() args = tuple([j] + list(args)) - self.progress.run_threaded(func, args=args) + self.app.progress.run_threaded(func, args=args) except job.JobInProgressError: NSNotificationCenter.defaultCenter().postNotificationName_object_('JobInProgress', self) else: ud = {'desc': JOBID2TITLE[jobid], 'jobid':jobid} NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('JobStarted', self, ud) - def _get_default(self, key_name): + def get_default(self, key_name): raw = NSUserDefaults.standardUserDefaults().objectForKey_(key_name) result = pythonify(raw) return result - def _set_default(self, key_name, value): + def set_default(self, key_name, value): NSUserDefaults.standardUserDefaults().setObject_forKey_(value, key_name) - def _show_extra_fairware_reminder(self): + def show_extra_fairware_reminder(self): NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('ShowExtraFairwareReminder', self, None) + +class DupeGuru(app.DupeGuru): + def __init__(self, data_module, appdata_subdir): + logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s') + install_exception_hook() + view = DupeGuruView(self) + appsupport = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0] + appdata = op.join(appsupport, appdata_subdir) + app.DupeGuru.__init__(self, view, data_module, appdata) + self.progress = cocoa.ThreadedJobPerformer() + #--- Public def start_scanning(self): self._select_dupes([]) diff --git a/qt/base/app.py b/qt/base/app.py index 69713222..74c48136 100644 --- a/qt/base/app.py +++ b/qt/base/app.py @@ -19,7 +19,7 @@ from jobprogress import job from jobprogress.qt import Progress from hscommon.trans import tr, trmsg -from core.app import DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE +from core.app import DupeGuru as DupeGuruModel, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE from qtlib.about_box import AboutBox from qtlib.recent import Recent @@ -45,11 +45,12 @@ class SysWrapper(io.IOBase): if s.strip(): # don't log empty stuff logging.warning(s) -class DupeGuru(DupeGuruBase, QObject): +class DupeGuru(QObject): LOGO_NAME = '' NAME = '' def __init__(self, data_module): + QObject.__init__(self) appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) if not op.exists(appdata): os.makedirs(appdata) @@ -62,8 +63,7 @@ class DupeGuru(DupeGuruBase, QObject): sys.stdout = SysWrapper() self.prefs = self._create_preferences() self.prefs.load() - DupeGuruBase.__init__(self, data_module, appdata) - QObject.__init__(self) + self.model = DupeGuruModel(view=self, data_module=data_module, appdata=appdata) self._setup() #--- Private @@ -71,7 +71,7 @@ class DupeGuru(DupeGuruBase, QObject): self._setupActions() self._update_options() self.recentResults = Recent(self, 'recentResults') - self.recentResults.mustOpenItem.connect(self.load_from) + self.recentResults.mustOpenItem.connect(self.model.load_from) self.resultWindow = self._create_result_window() self._progress = Progress(self.resultWindow) self.directories_dialog = DirectoriesDialog(self.resultWindow, self) @@ -81,16 +81,16 @@ class DupeGuru(DupeGuruBase, QObject): self.about_box = AboutBox(self.resultWindow, self) - self.reg = Registration(self) - self.set_registration(self.prefs.registration_code, self.prefs.registration_email) - if self.should_show_fairware_reminder: + self.reg = Registration(self.model) + self.model.set_registration(self.prefs.registration_code, self.prefs.registration_email) + if self.model.should_show_fairware_reminder: # The timer scheme is because if the nag is not shown before the application is # completely initialized, the nag will be shown before the app shows up in the task bar # In some circumstances, the nag is hidden by other window, which may make the user think # that the application haven't launched. QTimer.singleShot(0, self.reg.show_nag) self.directories_dialog.show() - self.load() + self.model.load() self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate) self.connect(self._progress, SIGNAL('finished(QString)'), self.job_finished) @@ -120,10 +120,10 @@ class DupeGuru(DupeGuruBase, QObject): self.about_box.registeredEmailLabel.setText(self.prefs.registration_email) def _update_options(self): - self.scanner.mix_file_kind = self.prefs.mix_file_kind - self.options['escape_filter_regexp'] = self.prefs.use_regexp - self.options['clean_empty_dirs'] = self.prefs.remove_empty_folders - self.options['ignore_hardlink_matches'] = self.prefs.ignore_hardlink_matches + self.model.scanner.mix_file_kind = self.prefs.mix_file_kind + self.model.options['escape_filter_regexp'] = self.prefs.use_regexp + self.model.options['clean_empty_dirs'] = self.prefs.remove_empty_folders + self.model.options['ignore_hardlink_matches'] = self.prefs.ignore_hardlink_matches #--- Virtual def _create_details_dialog(self, parent): @@ -138,44 +138,15 @@ class DupeGuru(DupeGuruBase, QObject): def _create_preferences_dialog(self, parent): raise NotImplementedError() - #--- Override - @staticmethod - def _open_path(path): - url = QUrl.fromLocalFile(str(path)) - QDesktopServices.openUrl(url) - - @staticmethod - def _reveal_path(path): - DupeGuru._open_path(path[:-1]) - - def _start_job(self, jobid, func, *args): - title = JOBID2TITLE[jobid] - try: - j = self._progress.create_job() - args = tuple([j] + list(args)) - self._progress.run(jobid, title, func, args=args) - except job.JobInProgressError: - msg = trmsg("TaskHangingMsg") - QMessageBox.information(self.resultWindow, 'Action in progress', msg) - - def _get_default(self, key): - return self.prefs.get_value(key) - - def _set_default(self, key, value): - self.prefs.set_value(key, value) - - def _show_extra_fairware_reminder(self): - dialog = ExtraFairwareReminder(self.directories_dialog, self) - dialog.exec_() - + #--- Public def add_selected_to_ignore_list(self): - dupes = self.without_ref(self.selected_dupes) + dupes = self.model.without_ref(self.model.selected_dupes) if not dupes: return title = tr("Add to Ignore List") msg = trmsg("IgnoreConfirmMsg").format(len(dupes)) if self.confirm(title, msg): - DupeGuruBase.add_selected_to_ignore_list(self) + self.model.add_selected_to_ignore_list(self) def copy_or_move_marked(self, copy): opname = tr("copy") if copy else tr("move") @@ -185,18 +156,17 @@ class DupeGuru(DupeGuruBase, QObject): if not destination: return recreate_path = self.prefs.destination_type - DupeGuruBase.copy_or_move_marked(self, copy, destination, recreate_path) + self.model.copy_or_move_marked(self, copy, destination, recreate_path) def remove_selected(self): - dupes = self.without_ref(self.selected_dupes) + dupes = self.model.without_ref(self.model.selected_dupes) if not dupes: return title = tr("Remove duplicates") msg = trmsg("FileRemovalConfirmMsg").format(len(dupes)) if self.confirm(title, msg): - DupeGuruBase.remove_selected(self) + self.model.remove_selected(self) - #--- Public def askForRegCode(self): self.reg.ask_for_code() @@ -209,7 +179,7 @@ class DupeGuru(DupeGuruBase, QObject): def invokeCustomCommand(self): cmd = self.prefs.custom_command if cmd: - self.invoke_command(cmd) + self.model.invoke_command(cmd) else: msg = trmsg("NoCustomCommandMsg") QMessageBox.warning(self.resultWindow, tr("Custom Command"), msg) @@ -227,21 +197,21 @@ class DupeGuru(DupeGuruBase, QObject): def application_will_terminate(self): self.willSavePrefs.emit() self.prefs.save() - self.save() + self.model.save() def checkForUpdateTriggered(self): QProcess.execute('updater.exe', ['/checknow']) def job_finished(self, jobid): - self._job_completed(jobid) + self.model._job_completed(jobid) if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE): - if self.results.problems: + if self.model.results.problems: self.problemDialog.show() else: msg = trmsg("OperationSuccessMsg") QMessageBox.information(self.resultWindow, tr("Operation Complete"), msg) elif jobid == JOB_SCAN: - if not self.results.groups: + if not self.model.results.groups: title = tr("Scan complete") msg = trmsg("NoDuplicateFoundMsg") QMessageBox.information(self.resultWindow, title, msg) @@ -251,12 +221,12 @@ class DupeGuru(DupeGuruBase, QObject): self.showResultsWindow() def openDebugLogTriggered(self): - debugLogPath = op.join(self.appdata, 'debug.log') - self._open_path(debugLogPath) + debugLogPath = op.join(self.model.appdata, 'debug.log') + self.open_path(debugLogPath) def preferencesTriggered(self): self.preferences_dialog.load() - result = self.preferences_dialog.exec_() + result = self.preferences_dialog.exec() if result == QDialog.Accepted: self.preferences_dialog.save() self.prefs.save() @@ -276,3 +246,33 @@ class DupeGuru(DupeGuruBase, QObject): url = QUrl.fromLocalFile(op.abspath(op.join(base_path, 'index.html'))) QDesktopServices.openUrl(url) + #--- model --> view + @staticmethod + def open_path(path): + url = QUrl.fromLocalFile(str(path)) + QDesktopServices.openUrl(url) + + @staticmethod + def reveal_path(path): + DupeGuru.open_path(path[:-1]) + + def start_job(self, jobid, func, *args): + title = JOBID2TITLE[jobid] + try: + j = self._progress.create_job() + args = tuple([j] + list(args)) + self._progress.run(jobid, title, func, args=args) + except job.JobInProgressError: + msg = trmsg("TaskHangingMsg") + QMessageBox.information(self.resultWindow, 'Action in progress', msg) + + def get_default(self, key): + return self.prefs.get_value(key) + + def set_default(self, key, value): + self.prefs.set_value(key, value) + + def show_extra_fairware_reminder(self): + dialog = ExtraFairwareReminder(self.directories_dialog, self) + dialog.exec() + diff --git a/qt/base/details_dialog.py b/qt/base/details_dialog.py index 45f1e62c..8d3b0092 100644 --- a/qt/base/details_dialog.py +++ b/qt/base/details_dialog.py @@ -18,7 +18,7 @@ class DetailsDialog(QDialog): def __init__(self, parent, app): QDialog.__init__(self, parent, Qt.Tool) self.app = app - self.model = DetailsPanel(self, app) + self.model = DetailsPanel(self, app.model) self._setupUi() if self.app.prefs.detailsWindowRect is not None: self.setGeometry(self.app.prefs.detailsWindowRect) diff --git a/qt/base/directories_dialog.py b/qt/base/directories_dialog.py index 38eb4b1b..68cf1b4a 100644 --- a/qt/base/directories_dialog.py +++ b/qt/base/directories_dialog.py @@ -45,7 +45,7 @@ class DirectoriesDialog(QMainWindow): self.treeView.selectionModel().selectionChanged.connect(self.selectionChanged) self.app.recentResults.itemsChanged.connect(self._updateLoadResultsButton) self.recentFolders.itemsChanged.connect(self._updateAddButton) - self.recentFolders.mustOpenItem.connect(self.app.add_directory) + self.recentFolders.mustOpenItem.connect(self.app.model.add_directory) self.directoriesModel.foldersAdded.connect(self.directoriesModelAddedFolders) self.app.willSavePrefs.connect(self.appWillSavePrefs) @@ -170,7 +170,7 @@ class DirectoriesDialog(QMainWindow): #--- QWidget overrides def closeEvent(self, event): event.accept() - if self.app.results.is_modified: + if self.app.model.results.is_modified: title = tr("Unsaved results") msg = trmsg("ReallyWantToQuitMsg") if not self.app.confirm(title, msg): @@ -186,7 +186,7 @@ class DirectoriesDialog(QMainWindow): if not dirpath: return self.lastAddedFolder = dirpath - self.app.add_directory(dirpath) + self.app.model.add_directory(dirpath) self.recentFolders.insertItem(dirpath) def appWillSavePrefs(self): @@ -201,7 +201,7 @@ class DirectoriesDialog(QMainWindow): files = ';;'.join([tr("dupeGuru Results (*.dupeguru)"), tr("All Files (*.*)")]) destination = QFileDialog.getOpenFileName(self, title, '', files) if destination: - self.app.load_from(destination) + self.app.model.load_from(destination) self.app.recentResults.insertItem(destination) def removeFolderButtonClicked(self): @@ -212,16 +212,16 @@ class DirectoriesDialog(QMainWindow): node = index.internalPointer() if node.parent is None: row = index.row() - self.app.remove_directory(row) + self.app.model.remove_directory(row) def scanButtonClicked(self): title = tr("Start a new scan") - if self.app.results.is_modified: + if self.app.model.results.is_modified: msg = trmsg("ReallyWantToContinueMsg") if not self.app.confirm(title, msg): return try: - self.app.start_scanning() + self.app.model.start_scanning() except NoScannableFileError: msg = trmsg("NoScannableFileMsg") QMessageBox.warning(self, title, msg) diff --git a/qt/base/directories_model.py b/qt/base/directories_model.py index 05935fbc..ab2387de 100644 --- a/qt/base/directories_model.py +++ b/qt/base/directories_model.py @@ -60,7 +60,7 @@ class DirectoriesDelegate(QStyledItemDelegate): class DirectoriesModel(TreeModel): def __init__(self, app): TreeModel.__init__(self) - self.model = DirectoryTree(self, app) + self.model = DirectoryTree(self, app.model) self.model.connect() def _createNode(self, ref, row): diff --git a/qt/base/prioritize_dialog.py b/qt/base/prioritize_dialog.py index e236161a..2afc89eb 100644 --- a/qt/base/prioritize_dialog.py +++ b/qt/base/prioritize_dialog.py @@ -55,7 +55,7 @@ class PrioritizeDialog(QDialog): QDialog.__init__(self, parent, flags) self.app = app self._setupUi() - self.model = PrioritizeDialogModel(view=self, app=app) + self.model = PrioritizeDialogModel(view=self, app=app.model) self.categoryList = ComboboxModel(model=self.model.category_list, view=self.categoryCombobox) self.criteriaList = ListviewModel(model=self.model.criteria_list, view=self.criteriaListView) self.prioritizationList = PrioritizationList(model=self.model.prioritization_list, view=self.prioritizationListView) diff --git a/qt/base/problem_dialog.py b/qt/base/problem_dialog.py index 0e618da0..5a1df575 100644 --- a/qt/base/problem_dialog.py +++ b/qt/base/problem_dialog.py @@ -20,7 +20,7 @@ class ProblemDialog(QDialog): QDialog.__init__(self, parent, flags) self.app = app self._setupUi() - self.model = ProblemDialogModel(view=self, app=app) + self.model = ProblemDialogModel(view=self, app=app.model) self.table = ProblemTable(problem_dialog=self, view=self.tableView) self.model.connect() self.table.model.connect() diff --git a/qt/base/result_window.py b/qt/base/result_window.py index 3b163e70..f60c1db2 100644 --- a/qt/base/result_window.py +++ b/qt/base/result_window.py @@ -140,7 +140,7 @@ class ResultWindow(QMainWindow): # Columns menu menu = self.menuColumns self._column_actions = [] - for index, column in enumerate(self.app.data.COLUMNS): + for index, column in enumerate(self.app.model.data.COLUMNS): action = menu.addAction(column.display) action.setCheckable(True) action.column_index = index @@ -224,7 +224,7 @@ class ResultWindow(QMainWindow): self.actionsButton.showMenu() def addToIgnoreListTriggered(self): - self.app.add_selected_to_ignore_list() + self.app.model.add_selected_to_ignore_list() def applyFilterTriggered(self): title = tr("Apply Filter") @@ -234,34 +234,34 @@ class ResultWindow(QMainWindow): if not ok: return answer = str(answer) - self.app.apply_filter(answer) + self.app.model.apply_filter(answer) self._last_filter = answer def cancelFilterTriggered(self): - self.app.apply_filter('') + self.app.model.apply_filter('') def clearIgnoreListTriggered(self): title = tr("Clear Ignore List") - count = len(self.app.scanner.ignore_list) + count = len(self.app.model.scanner.ignore_list) if not count: QMessageBox.information(self, title, trmsg("NothingToClearMsg")) return msg = trmsg("ClearIgnoreListConfirmMsg").format(count) if self.app.confirm(title, msg, QMessageBox.No): - self.app.scanner.ignore_list.Clear() + self.app.model.scanner.ignore_list.Clear() QMessageBox.information(self, title, trmsg("IgnoreListClearedMsg")) def copyTriggered(self): - self.app.copy_or_move_marked(True) + self.app.model.copy_or_move_marked(True) def deleteTriggered(self): - count = self.app.results.mark_count + count = self.app.model.results.mark_count if not count: return title = tr("Delete duplicates") msg = trmsg("SendToTrashConfirmMsg").format(count) if self.app.confirm(title, msg): - self.app.delete_marked() + self.app.model.delete_marked() def deltaTriggered(self): self.resultsModel.delta_values = self.actionDelta.isChecked() @@ -272,42 +272,42 @@ class ResultWindow(QMainWindow): def exportTriggered(self): h = self.resultsView.horizontalHeader() column_ids = [] - for i in range(len(self.app.data.COLUMNS)): + for i in range(len(self.app.model.data.COLUMNS)): if not h.isSectionHidden(i): column_ids.append(str(i)) - exported_path = self.app.export_to_xhtml(column_ids) + exported_path = self.app.model.export_to_xhtml(column_ids) url = QUrl.fromLocalFile(exported_path) QDesktopServices.openUrl(url) def hardlinkTriggered(self): - count = self.app.results.mark_count + count = self.app.model.results.mark_count if not count: return title = tr("Delete and hardlink duplicates") msg = trmsg("HardlinkConfirmMsg").format(count) if self.app.confirm(title, msg): - self.app.delete_marked(replace_with_hardlinks=True) + self.app.model.delete_marked(replace_with_hardlinks=True) def makeReferenceTriggered(self): - self.app.make_selected_reference() + self.app.model.make_selected_reference() def markAllTriggered(self): - self.app.mark_all() + self.app.model.mark_all() def markInvertTriggered(self): - self.app.mark_invert() + self.app.model.mark_invert() def markNoneTriggered(self): - self.app.mark_none() + self.app.model.mark_none() def markSelectedTriggered(self): - self.app.toggle_selected_mark_state() + self.app.model.toggle_selected_mark_state() def moveTriggered(self): - self.app.copy_or_move_marked(False) + self.app.model.copy_or_move_marked(False) def openTriggered(self): - self.app.open_selected() + self.app.model.open_selected() def powerMarkerTriggered(self): self.resultsModel.power_marker = self.actionPowerMarker.isChecked() @@ -316,16 +316,16 @@ class ResultWindow(QMainWindow): self.app.show_preferences() def removeMarkedTriggered(self): - count = self.app.results.mark_count + count = self.app.model.results.mark_count if not count: return title = tr("Remove duplicates") msg = trmsg("FileRemovalConfirmMsg").format(count) if self.app.confirm(title, msg): - self.app.remove_marked() + self.app.model.remove_marked() def removeSelectedTriggered(self): - self.app.remove_selected() + self.app.model.remove_selected() def renameTriggered(self): self.resultsView.edit(self.resultsView.selectionModel().currentIndex()) @@ -337,7 +337,7 @@ class ResultWindow(QMainWindow): dlg.model.perform_reprioritization() def revealTriggered(self): - self.app.reveal_selected() + self.app.model.reveal_selected() def saveResultsTriggered(self): title = trmsg("SelectResultToSaveMsg") @@ -346,7 +346,7 @@ class ResultWindow(QMainWindow): if destination: if not destination.endswith('.dupeguru'): destination = '{}.dupeguru'.format(destination) - self.app.save_as(destination) + self.app.model.save_as(destination) self.app.recentResults.insertItem(destination) #--- Events @@ -355,7 +355,7 @@ class ResultWindow(QMainWindow): h = self.resultsView.horizontalHeader() widths = [] visible = [] - for i in range(len(self.app.data.COLUMNS)): + for i in range(len(self.app.model.data.COLUMNS)): widths.append(h.sectionSize(i)) visible.append(not h.isSectionHidden(i)) prefs.columns_width = widths @@ -377,8 +377,8 @@ class ResultWindow(QMainWindow): self.actionActions.menu().exec_(event.globalPos()) def resultsDoubleClicked(self): - self.app.open_selected() + self.app.model.open_selected() def resultsSpacePressed(self): - self.app.toggle_selected_mark_state() + self.app.model.toggle_selected_mark_state() diff --git a/qt/base/results_model.py b/qt/base/results_model.py index 6aab26be..d4080996 100644 --- a/qt/base/results_model.py +++ b/qt/base/results_model.py @@ -15,10 +15,10 @@ from core.gui.result_table import ResultTable as ResultTableModel class ResultsModel(Table): def __init__(self, app, view): - model = ResultTableModel(self, app) + model = ResultTableModel(self, app.model) self._app = app - self._data = app.data - self._delta_columns = app.data.DELTA_COLUMNS + self._data = app.model.data + self._delta_columns = app.model.data.DELTA_COLUMNS Table.__init__(self, model, view) self.model.connect() diff --git a/qt/base/stats_label.py b/qt/base/stats_label.py index a8835efa..f6b2e8b0 100644 --- a/qt/base/stats_label.py +++ b/qt/base/stats_label.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Created By: Virgil Dupras # Created On: 2010-02-12 # Copyright 2011 Hardcoded Software (http://www.hardcoded.net) @@ -12,7 +11,7 @@ from core.gui.stats_label import StatsLabel as StatsLabelModel class StatsLabel(object): def __init__(self, app, view): self.view = view - self.model = StatsLabelModel(self, app) + self.model = StatsLabelModel(self, app.model) self.model.connect() def refresh(self): diff --git a/qt/me/app.py b/qt/me/app.py index 3c5ba3fb..6da49ad5 100644 --- a/qt/me/app.py +++ b/qt/me/app.py @@ -22,16 +22,16 @@ class DupeGuru(DupeGuruBase): DupeGuruBase.__init__(self, data) def _setup(self): - self.scanner = scanner.ScannerME() - self.directories.fileclasses = [fs.MusicFile] + self.model.scanner = scanner.ScannerME() + self.model.directories.fileclasses = [fs.MusicFile] DupeGuruBase._setup(self) def _update_options(self): DupeGuruBase._update_options(self) - self.scanner.min_match_percentage = self.prefs.filter_hardness - self.scanner.scan_type = self.prefs.scan_type - self.scanner.word_weighting = self.prefs.word_weighting - self.scanner.match_similar_words = self.prefs.match_similar + self.model.scanner.min_match_percentage = self.prefs.filter_hardness + self.model.scanner.scan_type = self.prefs.scan_type + self.model.scanner.word_weighting = self.prefs.word_weighting + self.model.scanner.match_similar_words = self.prefs.match_similar scanned_tags = set() if self.prefs.scan_tag_track: scanned_tags.add('track') @@ -45,7 +45,7 @@ class DupeGuru(DupeGuruBase): scanned_tags.add('genre') if self.prefs.scan_tag_year: scanned_tags.add('year') - self.scanner.scanned_tags = scanned_tags + self.model.scanner.scanned_tags = scanned_tags def _create_details_dialog(self, parent): return DetailsDialog(parent, self) diff --git a/qt/pe/app.py b/qt/pe/app.py index a7b45387..fcd006bd 100644 --- a/qt/pe/app.py +++ b/qt/pe/app.py @@ -74,16 +74,16 @@ class DupeGuru(DupeGuruBase): DupeGuruBase.__init__(self, data_pe) def _setup(self): - self.scanner = ScannerPE() - self.directories.fileclasses = [File] - self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db') + self.model.scanner = ScannerPE() + self.model.directories.fileclasses = [File] + self.model.scanner.cache_path = op.join(self.model.appdata, 'cached_pictures.db') DupeGuruBase._setup(self) def _update_options(self): DupeGuruBase._update_options(self) - self.scanner.scan_type = self.prefs.scan_type - self.scanner.match_scaled = self.prefs.match_scaled - self.scanner.threshold = self.prefs.filter_hardness + self.model.scanner.scan_type = self.prefs.scan_type + self.model.scanner.match_scaled = self.prefs.match_scaled + self.model.scanner.threshold = self.prefs.filter_hardness def _create_details_dialog(self, parent): return DetailsDialog(parent, self) diff --git a/qt/pe/details_dialog.py b/qt/pe/details_dialog.py index c01a73fd..48472679 100644 --- a/qt/pe/details_dialog.py +++ b/qt/pe/details_dialog.py @@ -60,10 +60,10 @@ class DetailsDialog(DetailsDialogBase): self.verticalLayout.addWidget(self.tableView) def _update(self): - if not self.app.selected_dupes: + if not self.app.model.selected_dupes: return - dupe = self.app.selected_dupes[0] - group = self.app.results.get_group_of_duplicate(dupe) + dupe = self.app.model.selected_dupes[0] + group = self.app.model.results.get_group_of_duplicate(dupe) ref = group.ref self.selectedPixmap = QPixmap(str(dupe.path)) diff --git a/qt/se/app.py b/qt/se/app.py index 9d9dadbe..ac34fa39 100644 --- a/qt/se/app.py +++ b/qt/se/app.py @@ -37,12 +37,12 @@ class DupeGuru(DupeGuruBase): def _update_options(self): DupeGuruBase._update_options(self) - self.scanner.min_match_percentage = self.prefs.filter_hardness - self.scanner.scan_type = self.prefs.scan_type - self.scanner.word_weighting = self.prefs.word_weighting - self.scanner.match_similar_words = self.prefs.match_similar + self.model.scanner.min_match_percentage = self.prefs.filter_hardness + self.model.scanner.scan_type = self.prefs.scan_type + self.model.scanner.word_weighting = self.prefs.word_weighting + self.model.scanner.match_similar_words = self.prefs.match_similar threshold = self.prefs.small_file_threshold if self.prefs.ignore_small_files else 0 - self.scanner.size_threshold = threshold * 1024 # threshold is in KB. the scanner wants bytes + self.model.scanner.size_threshold = threshold * 1024 # threshold is in KB. the scanner wants bytes def _create_details_dialog(self, parent): return DetailsDialog(parent, self)