Decoupled app in core.app from apps in qt.app and core.app_cocoa. Instead of subclassing it, they now hold a reference to it while fulfilling the role of core.app's "view".

This commit is contained in:
Virgil Dupras 2011-09-20 15:06:29 -04:00
parent 841b249b67
commit f730f4f55a
15 changed files with 162 additions and 170 deletions

View File

@ -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

View File

@ -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([])

View File

@ -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 = '<replace this>'
NAME = '<replace this>'
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()

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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):

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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)