Wrapped data modules around edition-specific core.app subclasses to prepare for data modules removal.

This commit is contained in:
Virgil Dupras 2011-09-20 18:40:27 -04:00
parent f730f4f55a
commit f2164924f7
16 changed files with 384 additions and 370 deletions

View File

@ -9,7 +9,7 @@ install_cocoa_trans()
from hscommon.cocoa import signature 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.app_cocoa import DupeGuruME
from core_me import __appname__ from core_me import __appname__
from core.scanner import ScanType from core.scanner import ScanType
@ -17,7 +17,7 @@ from core.scanner import ScanType
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):
self = super(PyDupeGuru,self).init() self = super(PyDupeGuru,self).init()
self.py = DupeGuruME() self._init(DupeGuruME)
return self return self
def removeDeadTracks(self): def removeDeadTracks(self):

View File

@ -7,14 +7,14 @@
from hscommon.trans import install_cocoa_trans from hscommon.trans import install_cocoa_trans
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_pe import app_cocoa as app_pe_cocoa, __appname__
from core.scanner import ScanType from core.scanner import ScanType
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):
self = super(PyDupeGuru, self).init() self = super(PyDupeGuru, self).init()
self.py = app_pe_cocoa.DupeGuruPE() self._init(app_pe_cocoa.DupeGuruPE)
return self return self
def clearPictureCache(self): def clearPictureCache(self):

View File

@ -10,14 +10,14 @@ install_cocoa_trans()
from hscommon.cocoa import signature from hscommon.cocoa import signature
from core.scanner import ScanType 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.app_cocoa import DupeGuru
from core_se import __appname__ from core_se import __appname__
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):
self = super(PyDupeGuru,self).init() self = super(PyDupeGuru,self).init()
self.py = DupeGuru() self._init(DupeGuru)
return self return self
#---Properties #---Properties

View File

@ -44,7 +44,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
#--- View interface #--- View interface
# open_path(path) # open_path(path)
# reveal_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) # get_default(key_name, fallback_value=None)
# set_default(key_name, value) # set_default(key_name, value)
# show_extra_fairware_reminder() # show_extra_fairware_reminder()
@ -226,7 +226,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def delete_marked(self, replace_with_hardlinks=False): def delete_marked(self, replace_with_hardlinks=False):
self.show_extra_fairware_reminder_if_needed() 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): def export_to_xhtml(self, column_ids):
column_ids = [colid for colid in column_ids if colid.isdigit()] column_ids = [colid for colid in column_ids if colid.isdigit()]

View File

@ -7,16 +7,25 @@
# http://www.hardcoded.net/licenses/bsd_license # http://www.hardcoded.net/licenses/bsd_license
import logging import logging
import os.path as op
from jobprogress import job from jobprogress import job
from hscommon import cocoa from hscommon import cocoa
from hscommon.cocoa import install_exception_hook, pythonify 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, from hscommon.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask, NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
NSWorkspace) NSWorkspace)
from hscommon.trans import tr 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 from . import app
JOBID2TITLE = { JOBID2TITLE = {
@ -27,23 +36,162 @@ JOBID2TITLE = {
app.JOB_DELETE: tr("Sending to Trash"), app.JOB_DELETE: tr("Sending to Trash"),
} }
class DupeGuruView: class PyDupeGuruBase(PyFairware):
def __init__(self, app): def _init(self, modelclass):
self.app = app 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 #---Directories
def open_path(path): 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)) NSWorkspace.sharedWorkspace().openFile_(str(path))
@staticmethod def reveal_path(self, path):
def reveal_path(path):
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(str(path), '') NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(str(path), '')
def start_job(self, jobid, func, *args): def start_job(self, jobid, func, args=()):
try: try:
j = self.app.progress.create_job() j = self.progress.create_job()
args = tuple([j] + list(args)) args = tuple([j] + list(args))
self.app.progress.run_threaded(func, args=args) self.progress.run_threaded(func, args=args)
except job.JobInProgressError: except job.JobInProgressError:
NSNotificationCenter.defaultCenter().postNotificationName_object_('JobInProgress', self) NSNotificationCenter.defaultCenter().postNotificationName_object_('JobInProgress', self)
else: else:
@ -61,23 +209,144 @@ class DupeGuruView:
def show_extra_fairware_reminder(self): def show_extra_fairware_reminder(self):
NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('ShowExtraFairwareReminder', self, None) NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('ShowExtraFairwareReminder', self, None)
class PyDetailsPanel(PyGUIObject):
py_class = DetailsPanel
@signature('i@:')
def numberOfRows(self):
return self.py.row_count()
class DupeGuru(app.DupeGuru): @signature('@@:@i')
def __init__(self, data_module, appdata_subdir): def valueForColumn_row_(self, column, row):
logging.basicConfig(level=logging.WARNING, format='%(levelname)s %(message)s') return self.py.row(row)[int(column)]
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): class PyDirectoryOutline(PyOutline):
self._select_dupes([]) py_class = DirectoryTree
try:
app.DupeGuru.start_scanning(self) def addDirectory_(self, path):
return 0 self.py.add_directory(path)
except app.NoScannableFileError:
return 3 # 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)

View File

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

14
core_me/app.py Normal file
View File

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

View File

@ -9,13 +9,15 @@
import logging import logging
from appscript import app, k, CommandError from appscript import app, k, CommandError
import time import time
import os.path as op
from hscommon.cocoa import as_fetch from hscommon.cocoa import as_fetch
from hscommon.trans import tr 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_REMOVE_DEAD_TRACKS = 'jobRemoveDeadTracks'
JOB_SCAN_DEAD_TRACKS = 'jobScanDeadTracks' JOB_SCAN_DEAD_TRACKS = 'jobScanDeadTracks'
@ -26,8 +28,9 @@ JOBID2TITLE.update({
}) })
class DupeGuruME(DupeGuruBase): class DupeGuruME(DupeGuruBase):
def __init__(self): def __init__(self, view, appdata):
DupeGuruBase.__init__(self, data, 'dupeGuru Music Edition') appdata = op.join(appdata, 'dupeGuru Music Edition')
DupeGuruBase.__init__(self, view, appdata)
self.scanner = scanner.ScannerME() self.scanner = scanner.ScannerME()
self.directories.fileclasses = [fs.MusicFile] self.directories.fileclasses = [fs.MusicFile]
self.dead_tracks = [] self.dead_tracks = []

14
core_pe/app.py Normal file
View File

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

View File

@ -19,10 +19,11 @@ from hscommon.path import Path
from hscommon.cocoa.objcmin import NSUserDefaults, NSURL from hscommon.cocoa.objcmin import NSUserDefaults, NSURL
from hscommon.trans import tr from hscommon.trans import tr
from core import app_cocoa, directories from core import directories
from . import data, _block_osx from . import _block_osx
from .photo import Photo as PhotoBase from .photo import Photo as PhotoBase
from .scanner import ScannerPE from .scanner import ScannerPE
from .app import DupeGuru as DupeGuruBase
IPHOTO_PATH = Path('iPhoto Library') IPHOTO_PATH = Path('iPhoto Library')
@ -128,9 +129,10 @@ class Directories(directories.Directories):
return directories.Directories.has_any_file(self) return directories.Directories.has_any_file(self)
class DupeGuruPE(app_cocoa.DupeGuru): class DupeGuruPE(DupeGuruBase):
def __init__(self): def __init__(self, view, appdata):
app_cocoa.DupeGuru.__init__(self, data, 'dupeGuru Picture Edition') appdata = op.join(appdata, 'dupeGuru Picture Edition')
DupeGuruBase.__init__(self, view, appdata)
self.scanner = ScannerPE() self.scanner = ScannerPE()
self.directories = Directories() self.directories = Directories()
self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db') 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: except (CommandError, RuntimeError) as e:
raise EnvironmentError(str(e)) raise EnvironmentError(str(e))
else: 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): def _create_file(self, path):
if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath[:-1]): if (self.directories.iphoto_libpath is not None) and (path in self.directories.iphoto_libpath[:-1]):
return IPhoto(path) 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): def copy_or_move(self, dupe, copy, destination, dest_type):
if isinstance(dupe, IPhoto): if isinstance(dupe, IPhoto):
copy = True 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): def selected_dupe_path(self):
if not self.selected_dupes: if not self.selected_dupes:
@ -190,7 +192,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
return ref.path return ref.path
def start_scanning(self): def start_scanning(self):
result = app_cocoa.DupeGuru.start_scanning(self) result = DupeGuruBase.start_scanning(self)
if self.directories.has_iphoto_path(): if self.directories.has_iphoto_path():
try: try:
app('iPhoto') app('iPhoto')

14
core_se/app.py Normal file
View File

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

View File

@ -7,15 +7,15 @@
# http://www.hardcoded.net/licenses/bsd_license # http://www.hardcoded.net/licenses/bsd_license
import logging import logging
import os.path as op
from hscommon import io from hscommon import io
from hscommon.path import Path from hscommon.path import Path
from hscommon.cocoa.objcmin import NSWorkspace from hscommon.cocoa.objcmin import NSWorkspace
from core import fs from core import fs
from core.app_cocoa import DupeGuru as DupeGuruBase
from core.directories import Directories as DirectoriesBase, DirectoryState from core.directories import Directories as DirectoriesBase, DirectoryState
from . import data from .app import DupeGuru as DupeGuruBase
def is_bundle(str_path): def is_bundle(str_path):
sw = NSWorkspace.sharedWorkspace() sw = NSWorkspace.sharedWorkspace()
@ -66,7 +66,8 @@ class Directories(DirectoriesBase):
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
def __init__(self): def __init__(self, view, appdata):
DupeGuruBase.__init__(self, data, 'dupeGuru') appdata = op.join(appdata, 'dupeGuru')
DupeGuruBase.__init__(self, view, appdata)
self.directories = Directories() self.directories = Directories()

View File

@ -46,10 +46,11 @@ class SysWrapper(io.IOBase):
logging.warning(s) logging.warning(s)
class DupeGuru(QObject): class DupeGuru(QObject):
MODELCLASS = None
LOGO_NAME = '<replace this>' LOGO_NAME = '<replace this>'
NAME = '<replace this>' NAME = '<replace this>'
def __init__(self, data_module): def __init__(self):
QObject.__init__(self) QObject.__init__(self)
appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
if not op.exists(appdata): if not op.exists(appdata):
@ -63,7 +64,7 @@ class DupeGuru(QObject):
sys.stdout = SysWrapper() sys.stdout = SysWrapper()
self.prefs = self._create_preferences() self.prefs = self._create_preferences()
self.prefs.load() self.prefs.load()
self.model = DupeGuruModel(view=self, data_module=data_module, appdata=appdata) self.model = self.MODELCLASS(view=self, appdata=appdata)
self._setup() self._setup()
#--- Private #--- Private
@ -256,11 +257,11 @@ class DupeGuru(QObject):
def reveal_path(path): def reveal_path(path):
DupeGuru.open_path(path[:-1]) DupeGuru.open_path(path[:-1])
def start_job(self, jobid, func, *args): def start_job(self, jobid, func, args=()):
title = JOBID2TITLE[jobid] title = JOBID2TITLE[jobid]
try: try:
j = self._progress.create_job() j = self._progress.create_job()
args = tuple([j] + list(args)) args = (j, ) + tuple(args)
self._progress.run(jobid, title, func, args=args) self._progress.run(jobid, title, func, args=args)
except job.JobInProgressError: except job.JobInProgressError:
msg = trmsg("TaskHangingMsg") msg = trmsg("TaskHangingMsg")

View File

@ -6,7 +6,8 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license # 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 ..base.app import DupeGuru as DupeGuruBase
from .details_dialog import DetailsDialog from .details_dialog import DetailsDialog
@ -14,13 +15,11 @@ from .preferences import Preferences
from .preferences_dialog import PreferencesDialog from .preferences_dialog import PreferencesDialog
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
MODELCLASS = DupeGuruModel
EDITION = 'me' EDITION = 'me'
LOGO_NAME = 'logo_me' LOGO_NAME = 'logo_me'
NAME = __appname__ NAME = __appname__
def __init__(self):
DupeGuruBase.__init__(self, data)
def _setup(self): def _setup(self):
self.model.scanner = scanner.ScannerME() self.model.scanner = scanner.ScannerME()
self.model.directories.fileclasses = [fs.MusicFile] self.model.directories.fileclasses = [fs.MusicFile]

View File

@ -11,9 +11,10 @@ import logging
from PyQt4.QtGui import QImage, QImageReader, QTransform 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.photo import Photo as PhotoBase
from core_pe.scanner import ScannerPE from core_pe.scanner import ScannerPE
from core_pe.app import DupeGuru as DupeGuruModel
from ..base.app import DupeGuru as DupeGuruBase from ..base.app import DupeGuru as DupeGuruBase
from .block import getblocks from .block import getblocks
@ -66,13 +67,11 @@ class File(PhotoBase):
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
MODELCLASS = DupeGuruModel
EDITION = 'pe' EDITION = 'pe'
LOGO_NAME = 'logo_pe' LOGO_NAME = 'logo_pe'
NAME = __appname__ NAME = __appname__
def __init__(self):
DupeGuruBase.__init__(self, data_pe)
def _setup(self): def _setup(self):
self.model.scanner = ScannerPE() self.model.scanner = ScannerPE()
self.model.directories.fileclasses = [File] self.model.directories.fileclasses = [File]

View File

@ -6,7 +6,8 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license # 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 core.directories import Directories as DirectoriesBase, DirectoryState
from ..base.app import DupeGuru as DupeGuruBase from ..base.app import DupeGuru as DupeGuruBase
@ -24,13 +25,11 @@ class Directories(DirectoriesBase):
return DirectoryState.Excluded return DirectoryState.Excluded
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
MODELCLASS = DupeGuruModel
EDITION = 'se' EDITION = 'se'
LOGO_NAME = 'logo_se' LOGO_NAME = 'logo_se'
NAME = __appname__ NAME = __appname__
def __init__(self):
DupeGuruBase.__init__(self, data)
def _setup(self): def _setup(self):
self.directories = Directories() self.directories = Directories()
DupeGuruBase._setup(self) DupeGuruBase._setup(self)