diff --git a/cocoa/me/dg_cocoa.py b/cocoa/me/dg_cocoa.py index 3e5b05d0..67775404 100644 --- a/cocoa/me/dg_cocoa.py +++ b/cocoa/me/dg_cocoa.py @@ -9,7 +9,7 @@ install_cocoa_trans() from hscommon.cocoa import signature -from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel +from core.app_cocoa import PyDupeGuruBase, PyDetailsPanel from core_me.app_cocoa import DupeGuruME from core_me import __appname__ from core.scanner import ScanType @@ -17,7 +17,7 @@ from core.scanner import ScanType class PyDupeGuru(PyDupeGuruBase): def init(self): self = super(PyDupeGuru,self).init() - self.py = DupeGuruME() + self._init(DupeGuruME) return self def removeDeadTracks(self): diff --git a/cocoa/pe/dg_cocoa.py b/cocoa/pe/dg_cocoa.py index 94411bc6..520f06fb 100644 --- a/cocoa/pe/dg_cocoa.py +++ b/cocoa/pe/dg_cocoa.py @@ -7,14 +7,14 @@ from hscommon.trans import install_cocoa_trans install_cocoa_trans() -from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel +from core.app_cocoa import PyDupeGuruBase, PyDetailsPanel from core_pe import app_cocoa as app_pe_cocoa, __appname__ from core.scanner import ScanType class PyDupeGuru(PyDupeGuruBase): def init(self): self = super(PyDupeGuru, self).init() - self.py = app_pe_cocoa.DupeGuruPE() + self._init(app_pe_cocoa.DupeGuruPE) return self def clearPictureCache(self): diff --git a/cocoa/se/dg_cocoa.py b/cocoa/se/dg_cocoa.py index a4bfe12b..910ae688 100644 --- a/cocoa/se/dg_cocoa.py +++ b/cocoa/se/dg_cocoa.py @@ -10,14 +10,14 @@ install_cocoa_trans() from hscommon.cocoa import signature from core.scanner import ScanType -from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel +from core.app_cocoa import PyDupeGuruBase, PyDetailsPanel from core_se.app_cocoa import DupeGuru from core_se import __appname__ class PyDupeGuru(PyDupeGuruBase): def init(self): self = super(PyDupeGuru,self).init() - self.py = DupeGuru() + self._init(DupeGuru) return self #---Properties diff --git a/core/app.py b/core/app.py index 586602e6..1f4f9c14 100644 --- a/core/app.py +++ b/core/app.py @@ -44,7 +44,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): #--- View interface # open_path(path) # reveal_path(path) - # start_job(jobid, func, *args) ( func(j, *args) ) + # start_job(jobid, func, args=()) ( func(j, *args) ) # get_default(key_name, fallback_value=None) # set_default(key_name, value) # show_extra_fairware_reminder() @@ -226,7 +226,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def delete_marked(self, replace_with_hardlinks=False): self.show_extra_fairware_reminder_if_needed() - self.view.start_job(JOB_DELETE, self._do_delete, replace_with_hardlinks) + self.view.start_job(JOB_DELETE, self._do_delete, args=[replace_with_hardlinks]) def export_to_xhtml(self, column_ids): column_ids = [colid for colid in column_ids if colid.isdigit()] diff --git a/core/app_cocoa.py b/core/app_cocoa.py index 74b34ef9..6a9a3093 100644 --- a/core/app_cocoa.py +++ b/core/app_cocoa.py @@ -7,16 +7,25 @@ # http://www.hardcoded.net/licenses/bsd_license import logging -import os.path as op from jobprogress import job from hscommon import cocoa from hscommon.cocoa import install_exception_hook, pythonify +from hscommon.cocoa.inter import (signature, PyTable, PyOutline, PyGUIObject, PyFairware, + PySelectableList) from hscommon.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults, NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask, NSWorkspace) from hscommon.trans import tr +from .gui.details_panel import DetailsPanel +from .gui.directory_tree import DirectoryTree +from .gui.problem_dialog import ProblemDialog +from .gui.problem_table import ProblemTable +from .gui.result_table import ResultTable +from .gui.stats_label import StatsLabel +from .gui.extra_fairware_reminder import ExtraFairwareReminder +from .gui.prioritize_dialog import PrioritizeDialog from . import app JOBID2TITLE = { @@ -27,23 +36,162 @@ JOBID2TITLE = { app.JOB_DELETE: tr("Sending to Trash"), } -class DupeGuruView: - def __init__(self, app): - self.app = app +class PyDupeGuruBase(PyFairware): + def _init(self, modelclass): + logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s') + install_exception_hook() + appdata = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0] + self.py = modelclass(self, appdata) + self.progress = cocoa.ThreadedJobPerformer() - @staticmethod - def open_path(path): + #---Directories + def addDirectory_(self, directory): + return self.py.add_directory(directory) + + def removeDirectory_(self, index): + self.py.remove_directory(index) + + #---Results + def clearIgnoreList(self): + self.py.scanner.ignore_list.Clear() + + def doScan(self): + return self.py.start_scanning() + + def exportToXHTMLwithColumns_(self, column_ids): + return self.py.export_to_xhtml(column_ids) + + def loadSession(self): + self.py.load() + + def loadResultsFrom_(self, filename): + self.py.load_from(filename) + + def markAll(self): + self.py.mark_all() + + def markNone(self): + self.py.mark_none() + + def markInvert(self): + self.py.mark_invert() + + def purgeIgnoreList(self): + self.py.purge_ignore_list() + + def toggleSelectedMark(self): + self.py.toggle_selected_mark_state() + + def saveSession(self): + self.py.save() + + def saveResultsAs_(self, filename): + self.py.save_as(filename) + + #---Actions + def addSelectedToIgnoreList(self): + self.py.add_selected_to_ignore_list() + + def deleteMarked(self): + self.py.delete_marked() + + def hardlinkMarked(self): + self.py.delete_marked(replace_with_hardlinks=True) + + def applyFilter_(self, filter): + self.py.apply_filter(filter) + + def makeSelectedReference(self): + self.py.make_selected_reference() + + def copyOrMove_markedTo_recreatePath_(self, copy, destination, recreate_path): + self.py.copy_or_move_marked(copy, destination, recreate_path) + + def openSelected(self): + self.py.open_selected() + + def removeMarked(self): + self.py.remove_marked() + + def renameSelected_(self,newname): + return self.py.rename_selected(newname) + + def revealSelected(self): + self.py.reveal_selected() + + def invokeCommand_(self, cmd): + self.py.invoke_command(cmd) + + #---Information + def getIgnoreListCount(self): + return len(self.py.scanner.ignore_list) + + def getMarkCount(self): + return self.py.results.mark_count + + @signature('i@:') + def scanWasProblematic(self): + return bool(self.py.results.problems) + + @signature('i@:') + def resultsAreModified(self): + return self.py.results.is_modified + + def deltaColumns(self): + return list(self.py.data.DELTA_COLUMNS) + + #---Properties + @signature('v@:c') + def setMixFileKind_(self, mix_file_kind): + self.py.scanner.mix_file_kind = mix_file_kind + + @signature('v@:c') + def setEscapeFilterRegexp_(self, escape_filter_regexp): + self.py.options['escape_filter_regexp'] = escape_filter_regexp + + @signature('v@:c') + def setRemoveEmptyFolders_(self, remove_empty_folders): + self.py.options['clean_empty_dirs'] = remove_empty_folders + + @signature('v@:c') + def setIgnoreHardlinkMatches_(self, ignore_hardlink_matches): + self.py.options['ignore_hardlink_matches'] = ignore_hardlink_matches + + #---Worker + def getJobProgress(self): + try: + return self.progress.last_progress + except AttributeError: + # I have *no idea* why this can possible happen (last_progress is always set by + # create_job() *before* any threaded job notification, which shows the progress panel, + # is sent), but it happens anyway, so there we go. ref: #106 + return -1 + + def getJobDesc(self): + try: + return self.progress.last_desc + except AttributeError: + # see getJobProgress + return '' + + def cancelJob(self): + self.progress.job_cancelled = True + + def jobCompleted_(self, jobid): + self.py._job_completed(jobid) + + #--- model --> view + def open_path(self, path): NSWorkspace.sharedWorkspace().openFile_(str(path)) - @staticmethod - def reveal_path(path): + def reveal_path(self, path): NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(str(path), '') - def start_job(self, jobid, func, *args): + def start_job(self, jobid, func, args=()): try: - j = self.app.progress.create_job() + j = self.progress.create_job() args = tuple([j] + list(args)) - self.app.progress.run_threaded(func, args=args) + self.progress.run_threaded(func, args=args) except job.JobInProgressError: NSNotificationCenter.defaultCenter().postNotificationName_object_('JobInProgress', self) else: @@ -60,24 +208,145 @@ class DupeGuruView: def show_extra_fairware_reminder(self): NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('ShowExtraFairwareReminder', self, None) + +class PyDetailsPanel(PyGUIObject): + py_class = DetailsPanel + @signature('i@:') + def numberOfRows(self): + return self.py.row_count() + + @signature('@@:@i') + def valueForColumn_row_(self, column, row): + return self.py.row(row)[int(column)] -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() +class PyDirectoryOutline(PyOutline): + py_class = DirectoryTree - #--- Public - def start_scanning(self): - self._select_dupes([]) - try: - app.DupeGuru.start_scanning(self) - return 0 - except app.NoScannableFileError: - return 3 + def addDirectory_(self, path): + self.py.add_directory(path) + # python --> cocoa + def refresh_states(self): + # Under cocoa, both refresh() and refresh_states() do the same thing. + self.cocoa.refresh() + + +class PyResultTable(PyTable): + py_class = ResultTable + + @signature('c@:') + def powerMarkerMode(self): + return self.py.power_marker + + @signature('v@:c') + def setPowerMarkerMode_(self, value): + self.py.power_marker = value + + @signature('c@:') + def deltaValuesMode(self): + return self.py.delta_values + + @signature('v@:c') + def setDeltaValuesMode_(self, value): + self.py.delta_values = value + + @signature('@@:ii') + def valueForRow_column_(self, row_index, column): + return self.py.get_row_value(row_index, column) + + @signature('c@:@') + def renameSelected_(self, newname): + return self.py.rename_selected(newname) + + @signature('v@:ic') + def sortBy_ascending_(self, key, asc): + self.py.sort(key, asc) + + def markSelected(self): + self.py.app.toggle_selected_mark_state() + + def removeSelected(self): + self.py.app.remove_selected() + + @signature('i@:') + def selectedDupeCount(self): + return self.py.selected_dupe_count + + # python --> cocoa + def invalidate_markings(self): + self.cocoa.invalidateMarkings() + + +class PyStatsLabel(PyGUIObject): + py_class = StatsLabel + + def display(self): + return self.py.display + + +class PyProblemDialog(PyGUIObject): + py_class = ProblemDialog + + def revealSelected(self): + self.py.reveal_selected_dupe() + + +class PyProblemTable(PyTable): + py_class = ProblemTable + +class PyExtraFairwareReminder(PyGUIObject): + py_class = ExtraFairwareReminder + + def start(self): + self.py.start() + + def updateButton(self): + self.py.update_button() + + # model --> view + def start_timer(self): + self.cocoa.startTimer() + + def stop_timer(self): + self.cocoa.stopTimer() + + def enable_button(self): + self.cocoa.enableButton() + + def set_button_text(self, text): + self.cocoa.setButtonText_(text) + + +class PyPrioritizeDialog(PyGUIObject): + py_class = PrioritizeDialog + + def categoryList(self): + if not hasattr(self, '_categoryList'): + self._categoryList = PySelectableList.alloc().initWithPy_(self.py.category_list) + return self._categoryList + + def criteriaList(self): + if not hasattr(self, '_criteriaList'): + self._criteriaList = PySelectableList.alloc().initWithPy_(self.py.criteria_list) + return self._criteriaList + + def prioritizationList(self): + if not hasattr(self, '_prioritizationList'): + self._prioritizationList = PyPrioritizeList.alloc().initWithPy_(self.py.prioritization_list) + return self._prioritizationList + + def addSelected(self): + self.py.add_selected() + + def removeSelected(self): + self.py.remove_selected() + + def performReprioritization(self): + self.py.perform_reprioritization() + +class PyPrioritizeList(PySelectableList): + @signature('v@:@i') + def moveIndexes_toIndex_(self, indexes, dest_index): + self.py.move_indexes(indexes, dest_index) + \ No newline at end of file diff --git a/core/app_cocoa_inter.py b/core/app_cocoa_inter.py deleted file mode 100644 index 35e4b1d1..00000000 --- a/core/app_cocoa_inter.py +++ /dev/null @@ -1,301 +0,0 @@ -# Created By: Virgil Dupras -# Created On: 2010-02-02 -# Copyright 2011 Hardcoded Software (http://www.hardcoded.net) -# -# This software is licensed under the "BSD" License as described in the "LICENSE" file, -# which should be included with this package. The terms are also available at -# http://www.hardcoded.net/licenses/bsd_license - -# Common interface for all editions' dg_cocoa unit. - -from hscommon.cocoa.inter import (signature, PyTable, PyOutline, PyGUIObject, PyFairware, - PySelectableList) - -from .gui.details_panel import DetailsPanel -from .gui.directory_tree import DirectoryTree -from .gui.problem_dialog import ProblemDialog -from .gui.problem_table import ProblemTable -from .gui.result_table import ResultTable -from .gui.stats_label import StatsLabel -from .gui.extra_fairware_reminder import ExtraFairwareReminder -from .gui.prioritize_dialog import PrioritizeDialog - -class PyDupeGuruBase(PyFairware): - #---Directories - def addDirectory_(self, directory): - return self.py.add_directory(directory) - - def removeDirectory_(self, index): - self.py.remove_directory(index) - - #---Results - def clearIgnoreList(self): - self.py.scanner.ignore_list.Clear() - - def doScan(self): - return self.py.start_scanning() - - def exportToXHTMLwithColumns_(self, column_ids): - return self.py.export_to_xhtml(column_ids) - - def loadSession(self): - self.py.load() - - def loadResultsFrom_(self, filename): - self.py.load_from(filename) - - def markAll(self): - self.py.mark_all() - - def markNone(self): - self.py.mark_none() - - def markInvert(self): - self.py.mark_invert() - - def purgeIgnoreList(self): - self.py.purge_ignore_list() - - def toggleSelectedMark(self): - self.py.toggle_selected_mark_state() - - def saveSession(self): - self.py.save() - - def saveResultsAs_(self, filename): - self.py.save_as(filename) - - #---Actions - def addSelectedToIgnoreList(self): - self.py.add_selected_to_ignore_list() - - def deleteMarked(self): - self.py.delete_marked() - - def hardlinkMarked(self): - self.py.delete_marked(replace_with_hardlinks=True) - - def applyFilter_(self, filter): - self.py.apply_filter(filter) - - def makeSelectedReference(self): - self.py.make_selected_reference() - - def copyOrMove_markedTo_recreatePath_(self, copy, destination, recreate_path): - self.py.copy_or_move_marked(copy, destination, recreate_path) - - def openSelected(self): - self.py.open_selected() - - def removeMarked(self): - self.py.remove_marked() - - def renameSelected_(self,newname): - return self.py.rename_selected(newname) - - def revealSelected(self): - self.py.reveal_selected() - - def invokeCommand_(self, cmd): - self.py.invoke_command(cmd) - - #---Information - def getIgnoreListCount(self): - return len(self.py.scanner.ignore_list) - - def getMarkCount(self): - return self.py.results.mark_count - - @signature('i@:') - def scanWasProblematic(self): - return bool(self.py.results.problems) - - @signature('i@:') - def resultsAreModified(self): - return self.py.results.is_modified - - def deltaColumns(self): - return list(self.py.data.DELTA_COLUMNS) - - #---Properties - @signature('v@:c') - def setMixFileKind_(self, mix_file_kind): - self.py.scanner.mix_file_kind = mix_file_kind - - @signature('v@:c') - def setEscapeFilterRegexp_(self, escape_filter_regexp): - self.py.options['escape_filter_regexp'] = escape_filter_regexp - - @signature('v@:c') - def setRemoveEmptyFolders_(self, remove_empty_folders): - self.py.options['clean_empty_dirs'] = remove_empty_folders - - @signature('v@:c') - def setIgnoreHardlinkMatches_(self, ignore_hardlink_matches): - self.py.options['ignore_hardlink_matches'] = ignore_hardlink_matches - - #---Worker - def getJobProgress(self): - try: - return self.py.progress.last_progress - except AttributeError: - # I have *no idea* why this can possible happen (last_progress is always set by - # create_job() *before* any threaded job notification, which shows the progress panel, - # is sent), but it happens anyway, so there we go. ref: #106 - return -1 - - def getJobDesc(self): - try: - return self.py.progress.last_desc - except AttributeError: - # see getJobProgress - return '' - - def cancelJob(self): - self.py.progress.job_cancelled = True - - def jobCompleted_(self, jobid): - self.py._job_completed(jobid) - - -class PyDetailsPanel(PyGUIObject): - py_class = DetailsPanel - @signature('i@:') - def numberOfRows(self): - return self.py.row_count() - - @signature('@@:@i') - def valueForColumn_row_(self, column, row): - return self.py.row(row)[int(column)] - - -class PyDirectoryOutline(PyOutline): - py_class = DirectoryTree - - def addDirectory_(self, path): - self.py.add_directory(path) - - # python --> cocoa - def refresh_states(self): - # Under cocoa, both refresh() and refresh_states() do the same thing. - self.cocoa.refresh() - - -class PyResultTable(PyTable): - py_class = ResultTable - - @signature('c@:') - def powerMarkerMode(self): - return self.py.power_marker - - @signature('v@:c') - def setPowerMarkerMode_(self, value): - self.py.power_marker = value - - @signature('c@:') - def deltaValuesMode(self): - return self.py.delta_values - - @signature('v@:c') - def setDeltaValuesMode_(self, value): - self.py.delta_values = value - - @signature('@@:ii') - def valueForRow_column_(self, row_index, column): - return self.py.get_row_value(row_index, column) - - @signature('c@:@') - def renameSelected_(self, newname): - return self.py.rename_selected(newname) - - @signature('v@:ic') - def sortBy_ascending_(self, key, asc): - self.py.sort(key, asc) - - def markSelected(self): - self.py.app.toggle_selected_mark_state() - - def removeSelected(self): - self.py.app.remove_selected() - - @signature('i@:') - def selectedDupeCount(self): - return self.py.selected_dupe_count - - # python --> cocoa - def invalidate_markings(self): - self.cocoa.invalidateMarkings() - - -class PyStatsLabel(PyGUIObject): - py_class = StatsLabel - - def display(self): - return self.py.display - - -class PyProblemDialog(PyGUIObject): - py_class = ProblemDialog - - def revealSelected(self): - self.py.reveal_selected_dupe() - - -class PyProblemTable(PyTable): - py_class = ProblemTable - -class PyExtraFairwareReminder(PyGUIObject): - py_class = ExtraFairwareReminder - - def start(self): - self.py.start() - - def updateButton(self): - self.py.update_button() - - # model --> view - def start_timer(self): - self.cocoa.startTimer() - - def stop_timer(self): - self.cocoa.stopTimer() - - def enable_button(self): - self.cocoa.enableButton() - - def set_button_text(self, text): - self.cocoa.setButtonText_(text) - - -class PyPrioritizeDialog(PyGUIObject): - py_class = PrioritizeDialog - - def categoryList(self): - if not hasattr(self, '_categoryList'): - self._categoryList = PySelectableList.alloc().initWithPy_(self.py.category_list) - return self._categoryList - - def criteriaList(self): - if not hasattr(self, '_criteriaList'): - self._criteriaList = PySelectableList.alloc().initWithPy_(self.py.criteria_list) - return self._criteriaList - - def prioritizationList(self): - if not hasattr(self, '_prioritizationList'): - self._prioritizationList = PyPrioritizeList.alloc().initWithPy_(self.py.prioritization_list) - return self._prioritizationList - - def addSelected(self): - self.py.add_selected() - - def removeSelected(self): - self.py.remove_selected() - - def performReprioritization(self): - self.py.perform_reprioritization() - -class PyPrioritizeList(PySelectableList): - @signature('v@:@i') - def moveIndexes_toIndex_(self, indexes, dest_index): - self.py.move_indexes(indexes, dest_index) - \ No newline at end of file diff --git a/core_me/app.py b/core_me/app.py new file mode 100644 index 00000000..92d9ead5 --- /dev/null +++ b/core_me/app.py @@ -0,0 +1,14 @@ +# Created On: 2011/09/20 +# Copyright 2011 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from core.app import DupeGuru as DupeGuruBase +from . import data + +class DupeGuru(DupeGuruBase): + def __init__(self, view, appdata): + DupeGuruBase.__init__(self, view, data, appdata) + diff --git a/core_me/app_cocoa.py b/core_me/app_cocoa.py index 5d7e6c6a..5046dd57 100644 --- a/core_me/app_cocoa.py +++ b/core_me/app_cocoa.py @@ -9,13 +9,15 @@ import logging from appscript import app, k, CommandError import time +import os.path as op from hscommon.cocoa import as_fetch from hscommon.trans import tr -from core.app_cocoa import JOBID2TITLE, DupeGuru as DupeGuruBase +from core.app_cocoa import JOBID2TITLE -from . import data, scanner, fs +from . import scanner, fs +from .app import DupeGuru as DupeGuruBase JOB_REMOVE_DEAD_TRACKS = 'jobRemoveDeadTracks' JOB_SCAN_DEAD_TRACKS = 'jobScanDeadTracks' @@ -26,8 +28,9 @@ JOBID2TITLE.update({ }) class DupeGuruME(DupeGuruBase): - def __init__(self): - DupeGuruBase.__init__(self, data, 'dupeGuru Music Edition') + def __init__(self, view, appdata): + appdata = op.join(appdata, 'dupeGuru Music Edition') + DupeGuruBase.__init__(self, view, appdata) self.scanner = scanner.ScannerME() self.directories.fileclasses = [fs.MusicFile] self.dead_tracks = [] diff --git a/core_pe/app.py b/core_pe/app.py new file mode 100644 index 00000000..92d9ead5 --- /dev/null +++ b/core_pe/app.py @@ -0,0 +1,14 @@ +# Created On: 2011/09/20 +# Copyright 2011 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from core.app import DupeGuru as DupeGuruBase +from . import data + +class DupeGuru(DupeGuruBase): + def __init__(self, view, appdata): + DupeGuruBase.__init__(self, view, data, appdata) + diff --git a/core_pe/app_cocoa.py b/core_pe/app_cocoa.py index eabb7c33..2b47c5ee 100644 --- a/core_pe/app_cocoa.py +++ b/core_pe/app_cocoa.py @@ -19,10 +19,11 @@ from hscommon.path import Path from hscommon.cocoa.objcmin import NSUserDefaults, NSURL from hscommon.trans import tr -from core import app_cocoa, directories -from . import data, _block_osx +from core import directories +from . import _block_osx from .photo import Photo as PhotoBase from .scanner import ScannerPE +from .app import DupeGuru as DupeGuruBase IPHOTO_PATH = Path('iPhoto Library') @@ -128,9 +129,10 @@ class Directories(directories.Directories): return directories.Directories.has_any_file(self) -class DupeGuruPE(app_cocoa.DupeGuru): - def __init__(self): - app_cocoa.DupeGuru.__init__(self, data, 'dupeGuru Picture Edition') +class DupeGuruPE(DupeGuruBase): + def __init__(self, view, appdata): + appdata = op.join(appdata, 'dupeGuru Picture Edition') + DupeGuruBase.__init__(self, view, appdata) self.scanner = ScannerPE() self.directories = Directories() self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db') @@ -164,17 +166,17 @@ class DupeGuruPE(app_cocoa.DupeGuru): except (CommandError, RuntimeError) as e: raise EnvironmentError(str(e)) else: - app_cocoa.DupeGuru._do_delete_dupe(self, dupe, replace_with_hardlinks) + DupeGuruBase._do_delete_dupe(self, dupe, replace_with_hardlinks) def _create_file(self, path): if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath[:-1]): return IPhoto(path) - return app_cocoa.DupeGuru._create_file(self, path) + return DupeGuruBase._create_file(self, path) def copy_or_move(self, dupe, copy, destination, dest_type): if isinstance(dupe, IPhoto): copy = True - return app_cocoa.DupeGuru.copy_or_move(self, dupe, copy, destination, dest_type) + return DupeGuruBase.copy_or_move(self, dupe, copy, destination, dest_type) def selected_dupe_path(self): if not self.selected_dupes: @@ -190,7 +192,7 @@ class DupeGuruPE(app_cocoa.DupeGuru): return ref.path def start_scanning(self): - result = app_cocoa.DupeGuru.start_scanning(self) + result = DupeGuruBase.start_scanning(self) if self.directories.has_iphoto_path(): try: app('iPhoto') diff --git a/core_se/app.py b/core_se/app.py new file mode 100644 index 00000000..92d9ead5 --- /dev/null +++ b/core_se/app.py @@ -0,0 +1,14 @@ +# Created On: 2011/09/20 +# Copyright 2011 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from core.app import DupeGuru as DupeGuruBase +from . import data + +class DupeGuru(DupeGuruBase): + def __init__(self, view, appdata): + DupeGuruBase.__init__(self, view, data, appdata) + diff --git a/core_se/app_cocoa.py b/core_se/app_cocoa.py index 98418830..98320e7c 100644 --- a/core_se/app_cocoa.py +++ b/core_se/app_cocoa.py @@ -7,15 +7,15 @@ # http://www.hardcoded.net/licenses/bsd_license import logging +import os.path as op from hscommon import io from hscommon.path import Path from hscommon.cocoa.objcmin import NSWorkspace from core import fs -from core.app_cocoa import DupeGuru as DupeGuruBase from core.directories import Directories as DirectoriesBase, DirectoryState -from . import data +from .app import DupeGuru as DupeGuruBase def is_bundle(str_path): sw = NSWorkspace.sharedWorkspace() @@ -66,7 +66,8 @@ class Directories(DirectoriesBase): class DupeGuru(DupeGuruBase): - def __init__(self): - DupeGuruBase.__init__(self, data, 'dupeGuru') + def __init__(self, view, appdata): + appdata = op.join(appdata, 'dupeGuru') + DupeGuruBase.__init__(self, view, appdata) self.directories = Directories() diff --git a/qt/base/app.py b/qt/base/app.py index 74c48136..fed7520d 100644 --- a/qt/base/app.py +++ b/qt/base/app.py @@ -46,10 +46,11 @@ class SysWrapper(io.IOBase): logging.warning(s) class DupeGuru(QObject): + MODELCLASS = None LOGO_NAME = '' NAME = '' - def __init__(self, data_module): + def __init__(self): QObject.__init__(self) appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) if not op.exists(appdata): @@ -63,7 +64,7 @@ class DupeGuru(QObject): sys.stdout = SysWrapper() self.prefs = self._create_preferences() self.prefs.load() - self.model = DupeGuruModel(view=self, data_module=data_module, appdata=appdata) + self.model = self.MODELCLASS(view=self, appdata=appdata) self._setup() #--- Private @@ -256,11 +257,11 @@ class DupeGuru(QObject): def reveal_path(path): DupeGuru.open_path(path[:-1]) - def start_job(self, jobid, func, *args): + def start_job(self, jobid, func, args=()): title = JOBID2TITLE[jobid] try: j = self._progress.create_job() - args = tuple([j] + list(args)) + args = (j, ) + tuple(args) self._progress.run(jobid, title, func, args=args) except job.JobInProgressError: msg = trmsg("TaskHangingMsg") diff --git a/qt/me/app.py b/qt/me/app.py index 6da49ad5..5d5d281b 100644 --- a/qt/me/app.py +++ b/qt/me/app.py @@ -6,7 +6,8 @@ # which should be included with this package. The terms are also available at # http://www.hardcoded.net/licenses/bsd_license -from core_me import data, scanner, fs, __appname__ +from core_me import scanner, fs, __appname__ +from core_me.app import DupeGuru as DupeGuruModel from ..base.app import DupeGuru as DupeGuruBase from .details_dialog import DetailsDialog @@ -14,13 +15,11 @@ from .preferences import Preferences from .preferences_dialog import PreferencesDialog class DupeGuru(DupeGuruBase): + MODELCLASS = DupeGuruModel EDITION = 'me' LOGO_NAME = 'logo_me' NAME = __appname__ - def __init__(self): - DupeGuruBase.__init__(self, data) - def _setup(self): self.model.scanner = scanner.ScannerME() self.model.directories.fileclasses = [fs.MusicFile] diff --git a/qt/pe/app.py b/qt/pe/app.py index fcd006bd..b7430fdf 100644 --- a/qt/pe/app.py +++ b/qt/pe/app.py @@ -11,9 +11,10 @@ import logging from PyQt4.QtGui import QImage, QImageReader, QTransform -from core_pe import data as data_pe, __appname__ +from core_pe import __appname__ from core_pe.photo import Photo as PhotoBase from core_pe.scanner import ScannerPE +from core_pe.app import DupeGuru as DupeGuruModel from ..base.app import DupeGuru as DupeGuruBase from .block import getblocks @@ -66,13 +67,11 @@ class File(PhotoBase): class DupeGuru(DupeGuruBase): + MODELCLASS = DupeGuruModel EDITION = 'pe' LOGO_NAME = 'logo_pe' NAME = __appname__ - def __init__(self): - DupeGuruBase.__init__(self, data_pe) - def _setup(self): self.model.scanner = ScannerPE() self.model.directories.fileclasses = [File] diff --git a/qt/se/app.py b/qt/se/app.py index ac34fa39..8b82c893 100644 --- a/qt/se/app.py +++ b/qt/se/app.py @@ -6,7 +6,8 @@ # which should be included with this package. The terms are also available at # http://www.hardcoded.net/licenses/bsd_license -from core_se import data, __appname__ +from core_se import __appname__ +from core_se.app import DupeGuru as DupeGuruModel from core.directories import Directories as DirectoriesBase, DirectoryState from ..base.app import DupeGuru as DupeGuruBase @@ -24,13 +25,11 @@ class Directories(DirectoriesBase): return DirectoryState.Excluded class DupeGuru(DupeGuruBase): + MODELCLASS = DupeGuruModel EDITION = 'se' LOGO_NAME = 'logo_se' NAME = __appname__ - def __init__(self): - DupeGuruBase.__init__(self, data) - def _setup(self): self.directories = Directories() DupeGuruBase._setup(self)