1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-25 16:11:39 +00:00

Compare commits

...

86 Commits

Author SHA1 Message Date
Virgil Dupras
f72db8dd1d pe v2.0.0 2011-01-29 11:39:51 +01:00
Virgil Dupras
c5bf0f228a Changed error logging in core_pe.cache because it would sometimes result in huge logs of no value. Also, added debug logging during the analysis of pictures. 2011-01-29 11:31:17 +01:00
Virgil Dupras
e150b26cab Forgot a litteral --> constant conversion in the last commit. 2011-01-29 11:20:19 +01:00
Virgil Dupras
da41d07dae [#115 state:fixed] Re-factored the data columns (and delta columns) and made the Dimensions column a delta one. 2011-01-29 11:07:33 +01:00
Virgil Dupras
c885cb35d8 Added tag se3.0.1 for changeset 778876a8a978 2011-01-27 12:11:11 +01:00
Virgil Dupras
7c38217308 Fixed pref dialog UI for Linux. 2011-01-27 02:22:10 -08:00
Virgil Dupras
a88519b814 Fixed pref window UI on Windows. 2011-01-27 10:11:23 +00:00
Virgil Dupras
0aa91b170c se v3.0.1 2011-01-27 10:53:13 +01:00
Virgil Dupras
e9bb1c01f7 [#136 state:fixed] Add dropped folders to recent added folders list in the folder selection window. 2011-01-27 10:27:17 +01:00
Virgil Dupras
883875e88e [#135 state:fixed] Removed focus from cancel button in progress dialog. 2011-01-27 09:58:43 +01:00
Virgil Dupras
4cab6b0ad2 Added a 'More Info' button to the Qt Fairware pop up. 2011-01-26 17:15:15 +01:00
Virgil Dupras
91a2664830 Internationalized (and localized to french) column names under Qt, which I had forgot to do. 2011-01-26 13:06:54 +01:00
Virgil Dupras
6abbeaf987 [#132 state:fixed] Added a debug mode preference as well as extra debug loggings. 2011-01-26 12:50:44 +01:00
Virgil Dupras
21efef42f7 [#134 state:fixed] Removing all dupes from the results sets it in 'not modified' state. 2011-01-26 11:49:30 +01:00
Virgil Dupras
9d0e8d94ca Fixed dummy DupeGuru app so it implements get/set defaults methods (their lack made all tests fail). 2011-01-26 11:48:48 +01:00
Virgil Dupras
0f57ca698c [#133 state:fixed] Restored the context menu in the results window. 2011-01-26 11:34:47 +01:00
Virgil Dupras
69c572e875 Added tag se3.0.0 for changeset 8d12cab3b12b 2011-01-24 17:22:17 +01:00
Virgil Dupras
4083b60ff3 se v3.0.0 2011-01-24 15:40:01 +01:00
Virgil Dupras
41fbeb7ec9 Fixed changelog formatting (again). 2011-01-24 14:54:29 +01:00
Virgil Dupras
1162357b9b Fixed changelog formatting. 2011-01-24 14:48:45 +01:00
Virgil Dupras
a2a526866f Don't show bundles as subfolders in Folder Selection dialog. 2011-01-24 12:35:07 +01:00
Virgil Dupras
d3338b699e Added a short timeout to fairware unpaid hours fetching to avoid delaying the app's launch too much. 2011-01-24 11:40:41 +01:00
Virgil Dupras
6c60e76b55 Localized Fairware dialogs to french and made a few fixes here and there. 2011-01-24 11:30:45 +01:00
Virgil Dupras
8a0d31f612 Fixed linux-specific crashes and glitches. 2011-01-23 07:09:47 -08:00
Virgil Dupras
6fc7e5ace1 Fixed windows-specific crash in pref panel under Qt. 2011-01-23 14:49:59 +00:00
Virgil Dupras
8175762e74 Fixed auto update checks in Cocoa which were broken. 2011-01-23 12:47:21 +01:00
Virgil Dupras
f48e14af8a Removed appname duplication between dg_cocoa and core_*.__init__. 2011-01-23 12:20:44 +01:00
Virgil Dupras
cd2a61d926 Removed py2app import workarounds, they're not needed anymore. 2011-01-23 12:12:28 +01:00
Virgil Dupras
f45997afe4 Added prompt in folders dialog under Qt. 2011-01-23 11:24:33 +01:00
Virgil Dupras
b6f56721cb Changed sphinxgen's mechanism so that we don't have to copy the whole sphinx source dir every time we generate help.
--HG--
rename : help/en/changelog.rst => help/en/changelog.tmpl
rename : help/en/conf.py => help/en/conf.tmpl
rename : help/fr/changelog.rst => help/fr/changelog.tmpl
rename : help/fr/conf.py => help/fr/conf.tmpl
2011-01-22 17:06:04 +01:00
Virgil Dupras
f9e7e82772 Fixed a few bugs here and there. 2011-01-22 16:12:18 +01:00
Virgil Dupras
dbcd7b63d8 Tweaked FAQ in help file to use topic directives instead of section. This way it doesn't bug when using 'only' directives (and it kind of looks cute). 2011-01-22 13:17:45 +01:00
Virgil Dupras
bf807684dd [#32] Translated the help file in french. 2011-01-22 12:12:08 +01:00
Virgil Dupras
f02fcb5e4b Added a --only-help option to build.py 2011-01-21 14:39:33 +01:00
Virgil Dupras
2c127adf59 [#32] Internationalized the qt layer and localized it to French.
In the process of doing so, I also added a new preferences_dialog base class to reduce code duplication in the three pref dialogs (I didn't want to copy/paste the language combobox addition three times).
2011-01-21 13:57:54 +01:00
Virgil Dupras
7f8a357019 (Cocoa) Converted .strings files from UTF-16 to UTF-8. 2011-01-21 13:49:39 +01:00
Virgil Dupras
99daf5b7b7 Added core translation to qt. 2011-01-19 09:47:00 +01:00
Virgil Dupras
42cff20710 [#32] Internationalized the core and localized it to french. 2011-01-18 17:33:33 +01:00
Virgil Dupras
04d7880a0c [#32] Internationalized the cocoa layer and localized it to french.
--HG--
rename : cocoa/base/xib/DetailsPanel.xib => cocoa/base/en.lproj/DetailsPanel.xib
rename : cocoa/base/xib/DirectoryPanel.xib => cocoa/base/en.lproj/DirectoryPanel.xib
rename : cocoa/base/xib/MainMenu.xib => cocoa/base/en.lproj/MainMenu.xib
rename : cocoa/base/xib/ProblemDialog.xib => cocoa/base/en.lproj/ProblemDialog.xib
rename : cocoa/base/xib/ResultWindow.xib => cocoa/base/en.lproj/ResultWindow.xib
rename : cocoa/me/xib/Preferences.xib => cocoa/me/en.lproj/Preferences.xib
rename : cocoa/pe/xib/DetailsPanel.xib => cocoa/pe/en.lproj/DetailsPanel.xib
rename : cocoa/pe/xib/Preferences.xib => cocoa/pe/en.lproj/Preferences.xib
rename : cocoa/se/xib/Preferences.xib => cocoa/se/en.lproj/Preferences.xib
2011-01-18 15:35:14 +01:00
Virgil Dupras
e7d26e3f82 Replaced 'Add' and 'Remove' by + and - icons in the directories dialog under Qt. 2011-01-18 11:07:56 +01:00
Virgil Dupras
19308bf686 Made a few wording fixes in the doc and in Qt. 2011-01-18 10:45:40 +01:00
Virgil Dupras
92970489c5 Straightened out actions pictures and keybindings, added a Recent Folders menu and a link to Recent Results menu in a dialog button. 2011-01-17 17:15:16 +01:00
Virgil Dupras
d51f5184d7 The directories dialog is now the main window. There's probably many glitches left to fix due to that change, but the basic functionalities are there.
--HG--
rename : qt/base/main_window.py => qt/base/result_window.py
rename : qt/pe/main_window.py => qt/pe/result_window.py
2011-01-15 16:29:35 +01:00
Virgil Dupras
30eb26af7d Fixed ambiguities in Directories/Folder vocabulary. 2011-01-15 14:14:30 +01:00
Virgil Dupras
3ea43f8213 Adapted help to recent UI changes.
--HG--
rename : help/en/directories.rst => help/en/folders.rst
2011-01-15 14:10:16 +01:00
Virgil Dupras
9833067ba7 Added a 'Load Results' button in the Directory window. 2011-01-15 12:08:10 +01:00
Virgil Dupras
ad3114c56b Cleaned ResultWindow's code up. 2011-01-15 11:38:59 +01:00
Virgil Dupras
9da9c269c1 Prettyfied the directories panel. 2011-01-14 15:51:19 +01:00
Virgil Dupras
0a22bb8469 Made a few UI fixes. Mostly, it's about main menu item not pointing the appropriate target. 2011-01-14 15:34:10 +01:00
Virgil Dupras
c9fd1b1a17 Don't consider results as modified if they're empty. 2011-01-14 15:12:02 +01:00
Virgil Dupras
19b40d45c0 Brought DirectoryPanel in ME and PE up to speed with latest developments and fixed ResultsWindow.awakeFromNib (in ME and PE also). 2011-01-14 15:07:11 +01:00
Virgil Dupras
90e2a1cda0 The main window of dupeGuru is now the directories window (and its Done button is replaced by a Start Scanning button). 2011-01-14 14:41:43 +01:00
Virgil Dupras
5e47b9f4a7 Transfered ownership of pref panel from result window to app delegate. 2011-01-14 14:06:54 +01:00
Virgil Dupras
50b6948250 Extracted ResultWindow.xib from MainMenu.xib. 2011-01-14 13:56:50 +01:00
Virgil Dupras
3ef118c9fa Results are not automatically saved/load anymore. There's a reminder on quitting if you haven't saved your results. Also, for easier re-loading, there's a 'open recent results' menu item. 2011-01-13 16:20:03 +01:00
Virgil Dupras
064707db43 Merged heads 2011-01-13 13:53:28 +01:00
Virgil Dupras
8f71a1318d [#129] Replaced details, power marker and delta values button by one segmented control on OS X. 2011-01-13 13:51:00 +01:00
Virgil Dupras
1b8ab35fdd Fixed debian packaging. 2011-01-13 03:23:21 -08:00
Virgil Dupras
4a1fe2f8ab Fixed packaging versioning and help building for Qt. 2011-01-13 10:56:46 +00:00
Virgil Dupras
e6e4e14781 Centralized version information in core_* package so that they only live at one place (instead of several).
--HG--
rename : cocoa/me/Info.plist => cocoa/me/InfoTemplate.plist
rename : cocoa/pe/Info.plist => cocoa/pe/InfoTemplate.plist
rename : cocoa/se/Info.plist => cocoa/se/InfoTemplate.plist
2011-01-13 11:29:01 +01:00
Virgil Dupras
d139157234 [#130 state:fixed] Converted help file to Sphinx.
--HG--
rename : help_me/CHANGELOG => help/changelog_me
rename : help_pe/CHANGELOG => help/changelog_pe
rename : help_se/CHANGELOG => help/changelog_se
2011-01-12 17:30:57 +01:00
Virgil Dupras
94104f4e03 Removed duplication among help files of the different editions.
--HG--
rename : help_se/en/credits.md => help_base/en/credits.md
rename : help_se/en/directories.md => help_base/en/directories.md
rename : help_se/en/power_marker.md => help_base/en/power_marker.md
rename : help_se/en/quick_start.md => help_base/en/quick_start.md
rename : help_se/en/results.md => help_base/en/results.md
rename : help_se/skeleton/hardcoded.css => help_base/skeleton/hardcoded.css
rename : help_se/skeleton/images/hs_title.png => help_base/skeleton/images/hs_title.png
2011-01-11 17:58:28 +01:00
Virgil Dupras
8bea978715 Removed dependencies for yaml everywhere except for the documentation generation (it's going to be converted to sphinx).
--HG--
rename : help_me/changelog.yaml => help_me/CHANGELOG
rename : help_pe/changelog.yaml => help_pe/CHANGELOG
2011-01-11 16:21:36 +01:00
Virgil Dupras
eefe464fba Replaced dependencies from hsutil to hscommon. 2011-01-11 13:36:05 +01:00
Virgil Dupras
33c0ba808c Changed references to what has already been moved from hsutil to hscommon (io, path, testutil). 2011-01-11 11:59:53 +01:00
Virgil Dupras
e0cc8ecda2 Stop using hsutil.testcase. 2011-01-05 11:11:21 +01:00
Virgil Dupras
2d423b2358 Added test skipping if os.link() is not available. 2011-01-01 16:22:38 +00:00
Virgil Dupras
b5b27b141c Modernized core_pe tests and added skipping when the modules haven't been compiled (rather than a hard crash). 2011-01-01 17:17:27 +01:00
Virgil Dupras
800a879927 Added tag se2.12.3 for changeset 0056293b0dad 2011-01-01 13:32:54 +01:00
Virgil Dupras
f6806e42db se v2.12.3 2011-01-01 12:45:39 +01:00
Virgil Dupras
3aae21b810 Added tag pe1.11.3 for changeset 3f71a8f5bf8f 2010-12-31 15:51:52 +01:00
Virgil Dupras
75239d6a64 pe v1.11.3 2010-12-31 14:43:00 +01:00
Virgil Dupras
09082955a3 [#125 state:fixed] Wrapped error message around a crash when the iPhoto app can't be found. 2010-12-31 12:10:44 +01:00
Virgil Dupras
6a6f2d51aa Added tag me5.10.4 for changeset 44f6ff67066c 2010-12-30 16:11:17 +01:00
Virgil Dupras
7b0d3ea8ac me v5.10.4 2010-12-30 14:55:13 +01:00
Virgil Dupras
1c88b6bb26 Tweaked the wording of the fairware pop up. 2010-12-30 13:07:04 +01:00
Virgil Dupras
e5e8e5d908 Replaced the about box with one that supports fairware registering. 2010-12-30 13:00:44 +01:00
Virgil Dupras
92fadd26b7 [#120 state:fixed] Fixed dangling bogus results after cancelled scan. 2010-12-30 10:24:37 +01:00
Virgil Dupras
45d783ac43 Removed CallLogger-related code in app_test. This code was duplicating the code that was recently added to hscommon.testutil. 2010-12-30 10:00:29 +01:00
Virgil Dupras
ea9e76e7ae Removed conftest.py modules in tests, which aren't required anymore with pytest v2.0 2010-12-30 09:47:22 +01:00
Virgil Dupras
28426c0e91 [#121 state:fixed] Catch HTTPException in Fairware fetching. 2010-12-30 09:35:45 +01:00
Virgil Dupras
3a9f51b600 [#122 state:fixed] Fixed crash on scanning when file is being deleted during the scan. 2010-12-29 15:41:12 +01:00
Virgil Dupras
f1b4db368e [#123 state:fixed] Updated codebase to use hsaudiotag v1.1.0 (which fixed the AIFF bug) and made it use the new auto.File wrapper. 2010-12-29 13:17:30 +01:00
Virgil Dupras
95efac187b Updated hscommon and adapted to changes in hscommon.gui.table.Table.refresh(). 2010-11-24 16:12:10 +01:00
Virgil Dupras
6770d22438 Updated hscommon subrepo. 2010-11-22 10:06:42 +01:00
Virgil Dupras
4ce97613c4 Added tag me5.10.3 for changeset ca93352ce351 2010-11-21 17:56:37 +01:00
223 changed files with 30992 additions and 9465 deletions

View File

@@ -8,7 +8,7 @@ run.py
*.pbxuser
*.tm_build_errors
*.pyd
conf.yaml
conf.json
build
dist
install
@@ -17,6 +17,7 @@ cocoa/*/Info.plist
cocoa/*/build
cocoa/*/dg_cocoa.plugin
qt/base/*_rc.py
help_se/dupeguru_help
help_me/dupeguru_me_help
help_pe/dupeguru_pe_help
qt/lang/fr.qm
qt/lang/en.qm
help/*/conf.py
help/*/changelog.rst

View File

@@ -36,3 +36,9 @@ b07ac1398703dd358912c1f3d20bd995633db9fe pe1.11.0
22239f94589baf2a9fad2123045b8a718dbd68f5 se2.12.2
f9cae82a0752191276b24ffb2cc4e4a8afb5d754 me5.10.2
154c8cb6f018d446d88fa099490c900906e86386 pe1.11.2
ca93352ce35184853ad9fcb881935a43a8b1e249 me5.10.3
44f6ff67066c083f79daa18a9d2f1ab909e0a62e me5.10.4
3f71a8f5bf8f6d0729748a27af9163e013723294 pe1.11.3
0056293b0dade8b8230f68c1fe6f0c2d1e0b74d8 se2.12.3
8d12cab3b12b723e3a86d02cf8002731a0f73f95 se3.0.0
778876a8a9787658aa6adf6944b53aebcb7faeea se3.0.1

24
README
View File

@@ -1,19 +1,20 @@
Contents
=====
This package contains the source for dupeGuru. To learns how to build it, refer to the "Build dupeGuru" section. Below is the description of the various subfolders:
This package contains the source for dupeGuru. To learn how to build it, refer to the "Build dupeGuru" section. Below is the description of the various subfolders:
- core: Contains the core logic code for dupeGuru. It's Python code written in TDD style.
- core_*: Edition-specific-cross-toolkit code written in Python.
- cocoa: UI code for the Cocoa toolkit. It's Objective-C code.
- qt: UI code for the Qt toolkit. It's written in Python and uses PyQt. Before redistributing changes in this part of the code, read the "qt/WARNING" file.
- qt: UI code for the Qt toolkit. It's written in Python and uses PyQt.
- images: Images used by the different UI codebases.
- debian_*: Skeleton files required to create a .deb package
- help: Help document, written for Sphinx.
There are also other sub-folder that comes from external repositories (automatically checked out
with svn:externals):
with as mercurial subrepos):
- hscommon: A collection of helpers used across HS applications.
- hsgui: Cross-toolkit GUI-related helper classes.
- cocoalib: A collection of helpers used across Cocoa UI codebases of HS applications.
- qtlib: A collection of helpers used across Qt UI codebases of HS applications.
@@ -27,20 +28,23 @@ General dependencies
- Python 3.1 (http://www.python.org)
- Send2Trash3k (http://hg.hardcoded.net/send2trash)
- hsutil3k (http://hg.hardcoded.net/hsutil)
- hsaudiotag3k (for ME) (http://hg.hardcoded.net/hsaudiotag)
- hsaudiotag3k 1.1.0 (for ME) (http://hg.hardcoded.net/hsaudiotag)
- jobprogress (http://hg.hardcoded.net/jobprogress)
- Markdown, to generate help files. (http://pypi.python.org/pypi/Markdown)
- PyYaml, for help files and the build system. (http://pyyaml.org/)
- py.test, to run unit tests. (http://codespeak.net/py/dist/test/)
- Sphinx 1.0.6 (http://sphinx.pocoo.org/)
- pytest 2.0.0, to run unit tests. (http://pytest.org/)
Note: Sphinx doesn't officially support Python 3.x yet, but it doesn't matter because it is invoked
by the build system through command line, so you can build dupeGuru even if Sphinx is installed in
your Python 2.x install.
OS X prerequisites
-----
- XCode 3.1 (http://developer.apple.com/TOOLS/xcode/)
- Sparkle (http://sparkle.andymatuschak.org/)
- PyObjC 2.3. (http://pyobjc.sourceforge.net/)
- PyObjC 2.3 (http://pyobjc.sourceforge.net/)
- py2app 0.5.4 (http://bitbucket.org/ronaldoussoren/py2app)
- appscript 0.22.0 for ME and PE (http://appscript.sourceforge.net/)
Windows prerequisites
---

View File

@@ -7,27 +7,35 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
import sys
import os
import os.path as op
from optparse import OptionParser
import shutil
import json
from setuptools import setup
from distutils.extension import Extension
import yaml
from hscommon import helpgen
from hscommon.build import add_to_pythonpath, print_and_do, build_all_qt_ui, copy_packages
from hscommon import sphinxgen
from hscommon.build import (add_to_pythonpath, print_and_do, copy_packages,
filereplace, get_module_version, build_all_cocoa_locs, build_all_qt_locs)
def build_cocoa(edition, dev, help_destpath):
if not dev:
print("Building help index")
os.system('open -a /Developer/Applications/Utilities/Help\\ Indexer.app {0}'.format(help_destpath))
def parse_args():
usage = "usage: %prog [options]"
parser = OptionParser(usage=usage)
parser.add_option('--clean', action='store_true', dest='clean',
help="Clean build folder before building")
parser.add_option('--only-help', action='store_true', dest='only_help',
help="Build only help file")
(options, args) = parser.parse_args()
return options
def build_cocoa(edition, dev):
build_all_cocoa_locs('cocoalib')
build_all_cocoa_locs(op.join('cocoa', 'base'))
build_all_cocoa_locs(op.join('cocoa', edition))
print("Building dg_cocoa.plugin")
if op.exists('build'):
shutil.rmtree('build')
os.mkdir('build')
if not dev:
specific_packages = {
'se': ['core_se'],
@@ -55,6 +63,9 @@ def build_cocoa(edition, dev, help_destpath):
pthpath = op.join(pluginpath, 'Contents/Resources/dev.pth')
open(pthpath, 'w').write(op.abspath('.'))
os.chdir(cocoa_project_path)
print('Generating Info.plist')
app_version = get_module_version('core_{}'.format(edition))
filereplace('InfoTemplate.plist', 'Info.plist', version=app_version)
print("Building the XCode project")
args = []
if dev:
@@ -76,6 +87,8 @@ def build_cocoa(edition, dev, help_destpath):
open('run.py', 'wt').write(run_contents)
def build_qt(edition, dev):
print("Building .ts files")
build_all_qt_locs(op.join('qt', 'lang'), extradirs=[op.join('qtlib', 'lang')])
print("Building Qt stuff")
print_and_do("pyrcc4 -py3 {0} > {1}".format(op.join('qt', 'base', 'dg.qrc'), op.join('qt', 'base', 'dg_rc.py')))
print("Creating the run.py file")
@@ -83,6 +96,18 @@ def build_qt(edition, dev):
run_contents = tmpl.replace('{{edition}}', edition)
open('run.py', 'wt').write(run_contents)
def build_help(edition):
print("Generating Help")
current_path = op.abspath('.')
help_basepath = op.join(current_path, 'help', 'en')
help_destpath = op.join(current_path, 'build', 'help'.format(edition))
changelog_path = op.join(current_path, 'help', 'changelog_{}'.format(edition))
tixurl = "https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}"
appname = {'se': 'dupeGuru', 'me': 'dupeGuru Music Edition', 'pe': 'dupeGuru Picture Edition'}[edition]
homepage = 'http://www.hardcoded.net/dupeguru{}/'.format('_' + edition if edition != 'se' else '')
confrepl = {'edition': edition, 'appname': appname, 'homepage': homepage}
sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl)
def build_pe_modules(ui):
def move(src, dst):
if not op.exists(src):
@@ -119,30 +144,35 @@ def build_pe_modules(ui):
move('_block_qt.so', op.join('qt', 'pe', '_block_qt.so'))
move('_block_qt.pyd', op.join('qt', 'pe', '_block_qt.pyd'))
def main():
conf = yaml.load(open('conf.yaml'))
edition = conf['edition']
ui = conf['ui']
dev = conf['dev']
def build_normal(edition, ui, dev):
print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui))
if dev:
print("Building in Dev mode")
add_to_pythonpath('.')
print("Generating Help")
windows = sys.platform == 'win32'
profile = 'win_en' if windows else 'osx_en'
help_dir = 'help_{0}'.format(edition)
dest_dir = 'dupeguru_{0}_help'.format(edition) if edition != 'se' else 'dupeguru_help'
help_basepath = op.abspath(help_dir)
help_destpath = op.abspath(op.join(help_dir, dest_dir))
helpgen.gen(help_basepath, help_destpath, profile=profile)
build_help(edition)
print("Building dupeGuru")
if edition == 'pe':
build_pe_modules(ui)
if ui == 'cocoa':
build_cocoa(edition, dev, help_destpath)
build_cocoa(edition, dev)
elif ui == 'qt':
build_qt(edition, dev)
def main():
options = parse_args()
conf = json.load(open('conf.json'))
edition = conf['edition']
ui = conf['ui']
dev = conf['dev']
if dev:
print("Building in Dev mode")
if options.clean:
if op.exists('build'):
shutil.rmtree('build')
if not op.exists('build'):
os.mkdir('build')
if options.only_help:
build_help(edition)
else:
build_normal(edition, ui, dev)
if __name__ == '__main__':
main()

View File

@@ -7,25 +7,49 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import <Cocoa/Cocoa.h>
#import "RecentDirectories.h"
#import "PyDupeGuru.h"
#import "ResultWindow.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h"
#import "HSAboutBox.h"
#import "HSRecentFiles.h"
@interface AppDelegateBase : NSObject
{
IBOutlet PyDupeGuruBase *py;
IBOutlet RecentDirectories *recentDirectories;
IBOutlet ResultWindowBase *result;
IBOutlet NSMenu *recentResultsMenu;
IBOutlet NSMenu *actionsMenu;
IBOutlet NSMenu *columnsMenu;
ResultWindowBase *_resultWindow;
DirectoryPanel *_directoryPanel;
DetailsPanel *_detailsPanel;
BOOL _savedResults;
NSWindowController *_preferencesPanel;
HSAboutBox *_aboutBox;
HSRecentFiles *_recentResults;
}
/* Virtual */
- (PyDupeGuruBase *)py;
- (RecentDirectories *)recentDirectories;
- (ResultWindowBase *)createResultWindow;
- (DirectoryPanel *)createDirectoryPanel;
- (DetailsPanel *)createDetailsPanel;
- (NSString *)homepageURL;
/* Public */
- (ResultWindowBase *)resultWindow;
- (DirectoryPanel *)directoryPanel;
- (DetailsPanel *)detailsPanel;
- (void)saveResults;
- (HSRecentFiles *)recentResults;
- (NSMenu *)columnsMenu;
/* Actions */
- (IBAction)loadResults:(id)sender;
- (IBAction)openWebsite:(id)sender;
- (IBAction)openHelp:(id)sender;
- (IBAction)showAboutBox:(id)sender;
- (IBAction)showDirectoryWindow:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)showResultWindow:(id)sender;
- (IBAction)startScanning:(id)sender;
@end

View File

@@ -11,35 +11,140 @@ http://www.hardcoded.net/licenses/bsd_license
#import "HSFairwareReminder.h"
#import "Utils.h"
#import "Consts.h"
#import "Dialogs.h"
#import <Sparkle/SUUpdater.h>
@implementation AppDelegateBase
- (void)awakeFromNib
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
/* Because the pref pane is lazily loaded, we have to manually do the update check if the
preference is set.
*/
if ([ud boolForKey:@"SUEnableAutomaticChecks"]) {
[[SUUpdater sharedUpdater] checkForUpdatesInBackground];
}
_recentResults = [[HSRecentFiles alloc] initWithName:@"recentResults" menu:recentResultsMenu];
[_recentResults setDelegate:self];
_resultWindow = [self createResultWindow];
_directoryPanel = [self createDirectoryPanel];
_detailsPanel = nil; // Lazily loaded
_aboutBox = nil; // Lazily loaded
_preferencesPanel = nil; // Lazily loaded
[[[self directoryPanel] window] makeKeyAndOrderFront:self];
}
/* Virtual */
- (PyDupeGuruBase *)py { return py; }
- (RecentDirectories *)recentDirectories { return recentDirectories; }
- (ResultWindowBase *)createResultWindow
{
return nil; // must be overriden by all editions
}
- (DirectoryPanel *)createDirectoryPanel
{
return [[DirectoryPanel alloc] initWithParentApp:self];
}
- (DetailsPanel *)createDetailsPanel
{
return [[DetailsPanel alloc] initWithPy:py];
}
- (NSString *)homepageURL
{
return @""; // must be overriden by all editions
}
/* Public */
- (ResultWindowBase *)resultWindow
{
return _resultWindow;
}
- (DirectoryPanel *)directoryPanel
{
if (!_directoryPanel)
_directoryPanel = [[DirectoryPanel alloc] initWithParentApp:self];
return _directoryPanel;
}
- (DetailsPanel *)detailsPanel
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
_detailsPanel = [self createDetailsPanel];
return _detailsPanel;
}
- (void)saveResults
- (HSRecentFiles *)recentResults
{
if (_savedResults) {
return;
}
[py saveIgnoreList];
[py saveResults];
_savedResults = YES;
return _recentResults;
}
- (NSMenu *)columnsMenu { return columnsMenu; }
/* Actions */
- (IBAction)loadResults:(id)sender
{
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:YES];
[op setCanChooseDirectories:NO];
[op setCanCreateDirectories:NO];
[op setAllowsMultipleSelection:NO];
[op setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
[op setTitle:TR(@"SelectResultToLoadMsg")];
if ([op runModal] == NSOKButton) {
NSString *filename = [[op filenames] objectAtIndex:0];
[py loadResultsFrom:filename];
[[self recentResults] addFile:filename];
}
}
- (IBAction)openWebsite:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[self homepageURL]]];
}
- (IBAction)openHelp:(id)sender
{
NSBundle *b = [NSBundle mainBundle];
NSString *p = [b pathForResource:@"index" ofType:@"html" inDirectory:@"help"];
NSURL *u = [NSURL fileURLWithPath:p];
[[NSWorkspace sharedWorkspace] openURL:u];
}
- (IBAction)showAboutBox:(id)sender
{
if (_aboutBox == nil) {
_aboutBox = [[HSAboutBox alloc] initWithApp:py];
}
[[_aboutBox window] makeKeyAndOrderFront:sender];
}
- (IBAction)showDirectoryWindow:(id)sender
{
[[[self directoryPanel] window] makeKeyAndOrderFront:nil];
}
- (IBAction)showPreferencesPanel:(id)sender
{
if (_preferencesPanel == nil) {
_preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
}
[_preferencesPanel showWindow:sender];
}
- (IBAction)showResultWindow:(id)sender
{
[[[self resultWindow] window] makeKeyAndOrderFront:nil];
}
- (IBAction)startScanning:(id)sender
{
[[self resultWindow] startDuplicateScan:sender];
}
/* Delegate */
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
@@ -49,54 +154,53 @@ http://www.hardcoded.net/licenses/bsd_license
NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"];
NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"];
if ([columnsOrder count])
[result restoreColumnsPosition:columnsOrder widths:columnsWidth];
[[self resultWindow] restoreColumnsPosition:columnsOrder widths:columnsWidth];
else
[result resetColumnsToDefault:nil];
[[self resultWindow] resetColumnsToDefault:nil];
[HSFairwareReminder showNagWithApp:[self py]];
//Restore results
[py loadIgnoreList];
[py loadResults];
_savedResults = NO;
[py loadSession];
}
- (void)applicationWillBecomeActive:(NSNotification *)aNotification
{
if (![[result window] isVisible])
[result showWindow:NSApp];
if (![[[self directoryPanel] window] isVisible]) {
[[self directoryPanel] showWindow:NSApp];
}
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
if ([py resultsAreModified]) {
NSString *msg = TR(@"ReallyWantToQuitMsg");
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) { // NO
return NSTerminateCancel;
}
}
return NSTerminateNow;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject: [result getColumnsOrder] forKey:@"columnsOrder"];
[ud setObject: [result getColumnsWidth] forKey:@"columnsWidth"];
[self saveResults];
[ud setObject: [[self resultWindow] getColumnsOrder] forKey:@"columnsOrder"];
[ud setObject: [[self resultWindow] getColumnsWidth] forKey:@"columnsWidth"];
NSInteger sc = [ud integerForKey:@"sessionCountSinceLastIgnorePurge"];
if (sc >= 10)
{
if (sc >= 10) {
sc = -1;
[py purgeIgnoreList];
}
sc++;
[py saveSession];
[ud setInteger:sc forKey:@"sessionCountSinceLastIgnorePurge"];
// NSApplication does not release nib instances objects, we must do it manually
// Well, it isn't needed because the memory is freed anyway (we are quitting the application
// But I need to release RecentDirectories so it saves the user defaults
[recentDirectories release];
// But I need to release HSRecentFiles so it saves the user defaults
[_directoryPanel release];
[_recentResults release];
}
- (void)recentDirecoryClicked:(NSString *)directory
- (void)recentFileClicked:(NSString *)path
{
[[self directoryPanel] addDirectory:directory];
}
/* SUUpdater delegate */
- (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation;
{
/* If results aren't saved now, we might get a weird utf-8 lookup error when saving later.
**/
[self saveResults];
return NO;
[py loadResultsFrom:path];
}
@end

View File

@@ -16,3 +16,5 @@ http://www.hardcoded.net/licenses/bsd_license
#define jobCopy @"job_copy"
#define jobMove @"job_move"
#define jobDelete @"job_delete"
#define TR(s) NSLocalizedString(s, @"")

View File

@@ -18,6 +18,7 @@ http://www.hardcoded.net/licenses/bsd_license
- (id)initWithPy:(PyApp *)aPy;
- (PyDetailsPanel *)py;
- (BOOL)isVisible;
- (void)toggleVisibility;
/* Python --> Cocoa */

View File

@@ -34,9 +34,14 @@ http://www.hardcoded.net/licenses/bsd_license
[detailsTable reloadData];
}
- (BOOL)isVisible
{
return [[self window] isVisible];
}
- (void)toggleVisibility
{
if ([[self window] isVisible]) {
if ([self isVisible]) {
[[self window] close];
}
else {

View File

@@ -10,6 +10,8 @@ http://www.hardcoded.net/licenses/bsd_license
#import "HSOutline.h"
#import "PyDirectoryOutline.h"
#define DGAddedFoldersNotification @"DGAddedFoldersNotification"
@interface DirectoryOutline : HSOutline {}
- (id)initWithPyParent:(id)aPyParent view:(HSOutlineView *)aOutlineView;
- (PyDirectoryOutline *)py;

View File

@@ -49,12 +49,15 @@ http://www.hardcoded.net/licenses/bsd_license
sourceDragMask = [info draggingSourceOperationMask];
pboard = [info draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType];
NSArray *foldernames = [pboard propertyListForType:NSFilenamesPboardType];
if (!(sourceDragMask & NSDragOperationLink))
return NO;
for (NSString *filename in filenames) {
[[self py] addDirectory:filename];
for (NSString *foldername in foldernames) {
[[self py] addDirectory:foldername];
}
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:foldernames forKey:@"foldernames"];
[[NSNotificationCenter defaultCenter] postNotificationName:DGAddedFoldersNotification
object:self userInfo:userInfo];
}
return YES;
}

View File

@@ -7,27 +7,34 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import <Cocoa/Cocoa.h>
#import "RecentDirectories.h"
#import "HSOutlineView.h"
#import "HSRecentFiles.h"
#import "DirectoryOutline.h"
#import "PyDupeGuru.h"
@class AppDelegateBase;
@interface DirectoryPanel : NSWindowController
{
IBOutlet NSPopUpButton *addButtonPopUp;
IBOutlet NSPopUpButton *loadRecentButtonPopUp;
IBOutlet HSOutlineView *outlineView;
IBOutlet NSButton *removeButton;
AppDelegateBase *_app;
PyDupeGuruBase *_py;
RecentDirectories *_recentDirectories;
HSRecentFiles *_recentDirectories;
DirectoryOutline *outline;
BOOL _alwaysShowPopUp;
}
- (id)initWithParentApp:(id)aParentApp;
- (id)initWithParentApp:(AppDelegateBase *)aParentApp;
- (void)fillPopUpMenu; // Virtual
- (IBAction)askForDirectory:(id)sender;
- (IBAction)popupAddDirectoryMenu:(id)sender;
- (IBAction)popupLoadRecentMenu:(id)sender;
- (IBAction)removeSelectedDirectory:(id)sender;
- (IBAction)toggleVisible:(id)sender;
- (void)addDirectory:(NSString *)directory;
- (void)refreshRemoveButtonText;

View File

@@ -10,28 +10,45 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Dialogs.h"
#import "Utils.h"
#import "AppDelegate.h"
#import "Consts.h"
@implementation DirectoryPanel
- (id)initWithParentApp:(id)aParentApp
- (id)initWithParentApp:(AppDelegateBase *)aParentApp
{
self = [super initWithWindowNibName:@"DirectoryPanel"];
[self window];
AppDelegateBase *app = aParentApp;
_py = [app py];
_recentDirectories = [app recentDirectories];
_app = aParentApp;
_py = [_app py];
_alwaysShowPopUp = NO;
[self fillPopUpMenu];
_recentDirectories = [[HSRecentFiles alloc] initWithName:@"recentDirectories" menu:[addButtonPopUp menu]];
[_recentDirectories setDelegate:self];
outline = [[DirectoryOutline alloc] initWithPyParent:_py view:outlineView];
[self refreshRemoveButtonText];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(directorySelectionChanged:)
name:NSOutlineViewSelectionDidChangeNotification object:outlineView];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outlineAddedFolders:)
name:DGAddedFoldersNotification object:outline];
return self;
}
- (void)dealloc
{
[outline release];
[_recentDirectories release];
[super dealloc];
}
/* Virtual */
- (void)fillPopUpMenu
{
NSMenu *m = [addButtonPopUp menu];
NSMenuItem *mi = [m addItemWithTitle:TR(@"Add New Folder...") action:@selector(askForDirectory:) keyEquivalent:@""];
[mi setTarget:self];
[m addItem:[NSMenuItem separatorItem]];
}
/* Actions */
- (IBAction)askForDirectory:(id)sender
@@ -40,7 +57,7 @@ http://www.hardcoded.net/licenses/bsd_license
[op setCanChooseFiles:YES];
[op setCanChooseDirectories:YES];
[op setAllowsMultipleSelection:YES];
[op setTitle:@"Select a directory to add to the scanning list"];
[op setTitle:TR(@"SelectFolderToAddMsg")];
[op setDelegate:self];
if ([op runModal] == NSOKButton) {
for (NSString *directory in [op filenames]) {
@@ -51,20 +68,32 @@ http://www.hardcoded.net/licenses/bsd_license
- (IBAction)popupAddDirectoryMenu:(id)sender
{
if ([[_recentDirectories directories] count] == 0)
{
if ((!_alwaysShowPopUp) && ([[_recentDirectories filepaths] count] == 0)) {
[self askForDirectory:sender];
return;
}
NSMenu *m = [addButtonPopUp menu];
while ([m numberOfItems] > 0)
[m removeItemAtIndex:0];
NSMenuItem *mi = [m addItemWithTitle:@"Add New Directory..." action:@selector(askForDirectory:) keyEquivalent:@""];
[mi setTarget:self];
[m addItem:[NSMenuItem separatorItem]];
[_recentDirectories fillMenu:m];
else {
[addButtonPopUp selectItem:nil];
[[addButtonPopUp cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
}
- (IBAction)popupLoadRecentMenu:(id)sender
{
if ([[[_app recentResults] filepaths] count] > 0) {
NSMenu *m = [loadRecentButtonPopUp menu];
while ([m numberOfItems] > 0) {
[m removeItemAtIndex:0];
}
NSMenuItem *mi = [m addItemWithTitle:TR(@"Load from file...") action:@selector(loadResults:) keyEquivalent:@""];
[mi setTarget:_app];
[m addItem:[NSMenuItem separatorItem]];
[[_app recentResults] fillMenu:m];
[loadRecentButtonPopUp selectItem:nil];
[[loadRecentButtonPopUp cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
else {
[_app loadResults:nil];
}
}
- (IBAction)removeSelectedDirectory:(id)sender
@@ -85,11 +114,6 @@ http://www.hardcoded.net/licenses/bsd_license
[self refreshRemoveButtonText];
}
- (IBAction)toggleVisible:(id)sender
{
[[self window] makeKeyAndOrderFront:nil];
}
/* Public */
- (void)addDirectory:(NSString *)directory
{
@@ -97,14 +121,14 @@ http://www.hardcoded.net/licenses/bsd_license
if (r) {
NSString *m = @"";
if (r == 1) {
m = @"'%@' already is in the list.";
m = TR(@"FolderAlreadyInListMsg");
}
else if (r == 2) {
m = @"'%@' does not exist.";
m = TR(@"FolderDoesNotExistMsg");
}
[Dialogs showMessage:[NSString stringWithFormat:m,directory]];
}
[_recentDirectories addDirectory:directory];
[_recentDirectories addFile:directory];
[[self window] makeKeyAndOrderFront:nil];
}
@@ -116,8 +140,8 @@ http://www.hardcoded.net/licenses/bsd_license
}
[removeButton setEnabled:YES];
NSInteger state = [outline intProperty:@"state" valueAtPath:[outline selectedIndexPath]];
NSString *buttonText = state == 2 ? @"Put Back" : @"Remove";
[removeButton setTitle:buttonText];
NSString *imgName = state == 2 ? @"NSGoLeftTemplate" : @"NSRemoveTemplate";
[removeButton setImage:[NSImage imageNamed:imgName]];
}
/* Delegate */
@@ -128,6 +152,11 @@ http://www.hardcoded.net/licenses/bsd_license
return isdir;
}
- (void)recentFileClicked:(NSString *)path
{
[self addDirectory:path];
}
/* Notifications */
- (void)directorySelectionChanged:(NSNotification *)aNotification
@@ -135,4 +164,12 @@ http://www.hardcoded.net/licenses/bsd_license
[self refreshRemoveButtonText];
}
- (void)outlineAddedFolders:(NSNotification *)aNotification
{
NSArray *foldernames = [[aNotification userInfo] objectForKey:@"foldernames"];
for (NSString *foldername in foldernames) {
[_recentDirectories addFile:foldername];
}
}
@end

View File

@@ -13,12 +13,10 @@ http://www.hardcoded.net/licenses/bsd_license
//Actions
- (NSNumber *)addDirectory:(NSString *)name;
- (void)removeDirectory:(NSNumber *)index;
- (void)loadResults;
- (void)loadResultsFrom:(NSString *)filename;
- (void)saveResults;
- (void)saveResultsAs:(NSString *)filename;
- (void)loadIgnoreList;
- (void)saveIgnoreList;
- (void)loadSession;
- (void)saveSession;
- (void)clearIgnoreList;
- (void)purgeIgnoreList;
- (NSString *)exportToXHTMLwithColumns:(NSArray *)aColIds;
@@ -46,6 +44,8 @@ http://www.hardcoded.net/licenses/bsd_license
- (NSNumber *)getIgnoreListCount;
- (NSNumber *)getMarkCount;
- (BOOL)scanWasProblematic;
- (BOOL)resultsAreModified;
- (NSArray *)deltaColumns;
//Scanning options
- (void)setMinMatchPercentage:(NSNumber *)percentage;

View File

@@ -68,7 +68,8 @@ http://www.hardcoded.net/licenses/bsd_license
NSInteger selectedDupeCount = [self selectedDupeCount];
if (!selectedDupeCount)
return;
NSString *msg = [NSString stringWithFormat:@"You are about to remove %d files from results. Continue?",selectedDupeCount];
NSString *msgFmt = TR(@"FileRemovalConfirmMsg");
NSString *msg = [NSString stringWithFormat:msgFmt,selectedDupeCount];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[[self py] removeSelected];
@@ -97,7 +98,7 @@ http://www.hardcoded.net/licenses/bsd_license
if (![newName isEqual:oldName]) {
BOOL renamed = [[self py] renameSelected:newName];
if (!renamed) {
[Dialogs showMessage:[NSString stringWithFormat:@"The name '%@' already exists.", newName]];
[Dialogs showMessage:[NSString stringWithFormat:TR(@"FilenameAlreadyExistsMsg"), newName]];
}
else {
[tableView setNeedsDisplay:YES];

View File

@@ -13,37 +13,43 @@ http://www.hardcoded.net/licenses/bsd_license
#import "HSTableView.h"
#import "PyDupeGuru.h"
@class AppDelegateBase;
@interface ResultWindowBase : NSWindowController
{
@protected
IBOutlet PyDupeGuruBase *py;
IBOutlet id app;
IBOutlet NSSegmentedControl *deltaSwitch;
IBOutlet NSSegmentedControl *optionsSwitch;
IBOutlet HSTableView *matches;
IBOutlet NSSegmentedControl *pmSwitch;
IBOutlet NSTextField *stats;
IBOutlet NSMenu *columnsMenu;
IBOutlet NSSearchField *filterField;
AppDelegateBase *app;
PyDupeGuruBase *py;
NSMenu *columnsMenu;
NSMutableArray *_resultColumns;
NSWindowController *preferencesPanel;
ResultTable *table;
StatsLabel *statsLabel;
ProblemDialog *problemDialog;
}
- (id)initWithParentApp:(AppDelegateBase *)app;
/* Virtual */
- (void)initResultColumns;
- (void)setScanOptions;
- (NSString *)getScanErrorMessageForCode:(NSInteger)errorCode;
/* Helpers */
- (void)fillColumnsMenu;
- (NSTableColumn *)getColumnForIdentifier:(NSInteger)aIdentifier title:(NSString *)aTitle width:(NSInteger)aWidth refCol:(NSTableColumn *)aColumn;
- (NSArray *)getColumnsOrder;
- (NSDictionary *)getColumnsWidth;
- (void)initResultColumns;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
- (void)sendMarkedToTrash:(BOOL)hardlinkDeleted;
- (void)updateOptionSegments;
/* Actions */
- (IBAction)clearIgnoreList:(id)sender;
- (IBAction)changeDelta:(id)sender;
- (IBAction)changePowerMarker:(id)sender;
- (IBAction)changeOptions:(id)sender;
- (IBAction)copyMarked:(id)sender;
- (IBAction)deleteMarked:(id)sender;
- (IBAction)hardlinkMarked:(id)sender;
@@ -51,7 +57,6 @@ http://www.hardcoded.net/licenses/bsd_license
- (IBAction)filter:(id)sender;
- (IBAction)ignoreSelected:(id)sender;
- (IBAction)invokeCustomCommand:(id)sender;
- (IBAction)loadResults:(id)sender;
- (IBAction)markAll:(id)sender;
- (IBAction)markInvert:(id)sender;
- (IBAction)markNone:(id)sender;
@@ -65,7 +70,6 @@ http://www.hardcoded.net/licenses/bsd_license
- (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)revealSelected:(id)sender;
- (IBAction)saveResults:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)startDuplicateScan:(id)sender;
- (IBAction)switchSelected:(id)sender;
- (IBAction)toggleColumn:(id)sender;

View File

@@ -14,36 +14,57 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Consts.h"
@implementation ResultWindowBase
- (void)awakeFromNib
- (id)initWithParentApp:(AppDelegateBase *)aApp;
{
[self window];
self = [super initWithWindowNibName:@"ResultWindow"];
app = aApp;
py = [app py];
columnsMenu = [app columnsMenu];
/* Put a cute iTunes-like bottom bar */
[[self window] setContentBorderThickness:28 forEdge:NSMinYEdge];
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
table = [[ResultTable alloc] initWithPyParent:py view:matches];
statsLabel = [[StatsLabel alloc] initWithPyParent:py labelView:stats];
problemDialog = [[ProblemDialog alloc] initWithPy:py];
[self initResultColumns];
[self fillColumnsMenu];
[deltaSwitch setSelectedSegment:0];
[pmSwitch setSelectedSegment:0];
[matches setTarget:self];
[matches setDoubleAction:@selector(openClicked:)];
[table setDeltaColumns:[Utils array2IndexSet:[py deltaColumns]]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobInProgress:) name:JobInProgress object:nil];
return self;
}
- (void)dealloc
{
[table release];
[preferencesPanel release];
[statsLabel release];
[problemDialog release];
[super dealloc];
}
/* Virtual */
- (void)initResultColumns
{
}
- (void)setScanOptions
{
}
- (NSString *)getScanErrorMessageForCode:(NSInteger)errorCode
{
if (errorCode == 0) {
return nil;
}
if (errorCode == 3) {
return TR(@"NoScannableFileMsg");
}
return TR(@"UnknownErrorMsg");
}
/* Helpers */
- (void)fillColumnsMenu
{
@@ -57,7 +78,8 @@ http://www.hardcoded.net/licenses/bsd_license
[mi setState:NSOnState];
}
[columnsMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem *mi = [columnsMenu addItemWithTitle:@"Reset to Default" action:@selector(resetColumnsToDefault:) keyEquivalent:@""];
NSMenuItem *mi = [columnsMenu addItemWithTitle:TR(@"Reset to Default")
action:@selector(resetColumnsToDefault:) keyEquivalent:@""];
[mi setTarget:self];
}
@@ -96,11 +118,6 @@ http://www.hardcoded.net/licenses/bsd_license
return result;
}
- (void)initResultColumns
{
// Virtual
}
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth
{
for (NSMenuItem *mi in [columnsMenu itemArray]) {
@@ -130,9 +147,9 @@ http://www.hardcoded.net/licenses/bsd_license
if (!mark_count) {
return;
}
NSString *msg = @"You are about to send %d files to Trash. Continue?";
NSString *msg = TR(@"SendToTrashConfirmMsg");
if (hardlinkDeleted) {
msg = @"You are about to send %d files to Trash (and hardlink them afterwards). Continue?";
msg = TR(@"HardlinkConfirmMsg");
}
if ([Dialogs askYesNo:[NSString stringWithFormat:msg,mark_count]] == NSAlertSecondButtonReturn) { // NO
return;
@@ -147,25 +164,37 @@ http://www.hardcoded.net/licenses/bsd_license
}
}
- (void)updateOptionSegments
{
[optionsSwitch setSelected:[[app detailsPanel] isVisible] forSegment:0];
[optionsSwitch setSelected:[table powerMarkerMode] forSegment:1];
[optionsSwitch setSelected:[table deltaValuesMode] forSegment:2];
}
/* Actions */
- (IBAction)clearIgnoreList:(id)sender
{
NSInteger i = n2i([py getIgnoreListCount]);
if (!i)
return;
if ([Dialogs askYesNo:[NSString stringWithFormat:@"Do you really want to remove all %d items from the ignore list?",i]] == NSAlertSecondButtonReturn) // NO
NSString *msg = [NSString stringWithFormat:TR(@"ClearIgnoreListConfirmMsg"),i];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[py clearIgnoreList];
}
- (IBAction)changeDelta:(id)sender
- (IBAction)changeOptions:(id)sender
{
[table setDeltaValuesMode:[deltaSwitch selectedSegment] == 1];
}
- (IBAction)changePowerMarker:(id)sender
{
[table setPowerMarkerMode:[pmSwitch selectedSegment] == 1];
NSInteger seg = [optionsSwitch selectedSegment];
if (seg == 0) {
[self toggleDetailsPanel:sender];
}
else if (seg == 1) {
[self togglePowerMarker:sender];
}
else if (seg == 2) {
[self toggleDelta:sender];
}
}
- (IBAction)copyMarked:(id)sender
@@ -178,9 +207,8 @@ http://www.hardcoded.net/licenses/bsd_license
[op setCanChooseDirectories:YES];
[op setCanCreateDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setTitle:@"Select a directory to copy marked files to"];
if ([op runModalForTypes:nil] == NSOKButton)
{
[op setTitle:TR(@"SelectCopyDestinationMsg")];
if ([op runModal] == NSOKButton) {
NSString *directory = [[op filenames] objectAtIndex:0];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py copyOrMove:b2n(YES) markedTo:directory recreatePath:[ud objectForKey:@"recreatePathType"]];
@@ -215,7 +243,7 @@ http://www.hardcoded.net/licenses/bsd_license
NSInteger selectedDupeCount = [table selectedDupeCount];
if (!selectedDupeCount)
return;
NSString *msg = [NSString stringWithFormat:@"All selected %d matches are going to be ignored in all subsequent scans. Continue?",selectedDupeCount];
NSString *msg = [NSString stringWithFormat:TR(@"IgnoreConfirmMsg"),selectedDupeCount];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[py addSelectedToIgnoreList];
@@ -229,22 +257,7 @@ http://www.hardcoded.net/licenses/bsd_license
[py invokeCommand:cmd];
}
else {
[Dialogs showMessage:@"You have no custom command set up. Set it up in your preferences."];
}
}
- (IBAction)loadResults:(id)sender
{
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:YES];
[op setCanChooseDirectories:NO];
[op setCanCreateDirectories:NO];
[op setAllowsMultipleSelection:NO];
[op setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
[op setTitle:@"Select a results file to load"];
if ([op runModal] == NSOKButton) {
NSString *filename = [[op filenames] objectAtIndex:0];
[py loadResultsFrom:filename];
[Dialogs showMessage:TR(@"NoCustomCommandMsg")];
}
}
@@ -278,9 +291,8 @@ http://www.hardcoded.net/licenses/bsd_license
[op setCanChooseDirectories:YES];
[op setCanCreateDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setTitle:@"Select a directory to move marked files to"];
if ([op runModalForTypes:nil] == NSOKButton)
{
[op setTitle:TR(@"SelectMoveDestinationMsg")];
if ([op runModal] == NSOKButton) {
NSString *directory = [[op filenames] objectAtIndex:0];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setRemoveEmptyFolders:n2b([ud objectForKey:@"removeEmptyFolders"])];
@@ -307,7 +319,8 @@ http://www.hardcoded.net/licenses/bsd_license
int mark_count = [[py getMarkCount] intValue];
if (!mark_count)
return;
if ([Dialogs askYesNo:[NSString stringWithFormat:@"You are about to remove %d files from results. Continue?",mark_count]] == NSAlertSecondButtonReturn) // NO
NSString *msg = [NSString stringWithFormat:@"You are about to remove %d files from results. Continue?",mark_count];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[py removeMarked];
}
@@ -334,25 +347,31 @@ http://www.hardcoded.net/licenses/bsd_license
[py revealSelected];
}
- (IBAction)showPreferencesPanel:(id)sender
{
[preferencesPanel showWindow:sender];
}
- (IBAction)saveResults:(id)sender
{
NSSavePanel *sp = [NSSavePanel savePanel];
[sp setCanCreateDirectories:YES];
[sp setAllowedFileTypes:[NSArray arrayWithObject:@"dupeguru"]];
[sp setTitle:@"Select a file to save your results to"];
[sp setTitle:TR(@"SelectResultToSaveMsg")];
if ([sp runModal] == NSOKButton) {
[py saveResultsAs:[sp filename]];
[[app recentResults] addFile:[sp filename]];
}
}
- (IBAction)startDuplicateScan:(id)sender
{
// Virtual
if ([py resultsAreModified]) {
if ([Dialogs askYesNo:TR(@"ReallyWantToContinueMsg")] == NSAlertSecondButtonReturn) // NO
return;
}
[self setScanOptions];
NSInteger r = n2i([py doScan]);
NSString *errorMsg = [self getScanErrorMessageForCode:r];
if (errorMsg != nil) {
[[ProgressController mainProgressController] hide];
[Dialogs showMessage:errorMsg];
}
}
- (IBAction)switchSelected:(id)sender
@@ -365,50 +384,38 @@ http://www.hardcoded.net/licenses/bsd_license
NSMenuItem *mi = sender;
NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]];
NSTableColumn *col = [matches tableColumnWithIdentifier:colId];
if (col == nil)
{
if (col == nil) {
//Add Column
col = [_resultColumns objectAtIndex:[mi tag]];
[matches addTableColumn:col];
[mi setState:NSOnState];
}
else
{
else {
//Remove column
[matches removeTableColumn:col];
[mi setState:NSOffState];
}
}
- (IBAction)toggleDelta:(id)sender
{
if ([deltaSwitch selectedSegment] == 1)
[deltaSwitch setSelectedSegment:0];
else
[deltaSwitch setSelectedSegment:1];
[self changeDelta:sender];
}
- (IBAction)toggleDetailsPanel:(id)sender
{
[[(AppDelegateBase *)app detailsPanel] toggleVisibility];
[[app detailsPanel] toggleVisibility];
[self updateOptionSegments];
}
- (IBAction)toggleDelta:(id)sender
{
[table setDeltaValuesMode:![table deltaValuesMode]];
[self updateOptionSegments];
}
- (IBAction)togglePowerMarker:(id)sender
{
if ([pmSwitch selectedSegment] == 1)
[pmSwitch setSelectedSegment:0];
else
[pmSwitch setSelectedSegment:1];
[self changePowerMarker:sender];
[table setPowerMarkerMode:![table powerMarkerMode]];
[self updateOptionSegments];
}
/* Notifications */
- (void)windowWillClose:(NSNotification *)aNotification
{
[NSApp hide:NSApp];
}
- (void)jobCompleted:(NSNotification *)aNotification
{
id lastAction = [[ProgressController mainProgressController] jobId];
@@ -417,7 +424,7 @@ http://www.hardcoded.net/licenses/bsd_license
[problemDialog showWindow:self];
}
else {
[Dialogs showMessage:@"All marked files were copied sucessfully."];
[Dialogs showMessage:TR(@"CopySuccessMsg")];
}
}
else if ([lastAction isEqualTo:jobMove]) {
@@ -425,7 +432,7 @@ http://www.hardcoded.net/licenses/bsd_license
[problemDialog showWindow:self];
}
else {
[Dialogs showMessage:@"All marked files were moved sucessfully."];
[Dialogs showMessage:TR(@"MoveSuccessMsg")];
}
}
else if ([lastAction isEqualTo:jobDelete]) {
@@ -433,27 +440,25 @@ http://www.hardcoded.net/licenses/bsd_license
[problemDialog showWindow:self];
}
else {
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
[Dialogs showMessage:TR(@"SendToTrashSuccessMsg")];
}
}
else if ([lastAction isEqualTo:jobScan]) {
NSInteger rowCount = [[table py] numberOfRows];
if (rowCount == 0)
[Dialogs showMessage:@"No duplicates found."];
if (rowCount == 0) {
[Dialogs showMessage:TR(@"NoDuplicateFoundMsg")];
}
}
// Re-activate toolbar items right after the progress bar stops showing instead of waiting until
// a mouse-over is performed
[[[self window] toolbar] validateVisibleItems];
}
- (void)jobInProgress:(NSNotification *)aNotification
{
[Dialogs showMessage:@"A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."];
[Dialogs showMessage:TR(@"TaskHangingMsg")];
}
- (void)jobStarted:(NSNotification *)aNotification
{
[[self window] makeKeyAndOrderFront:nil];
NSDictionary *ui = [aNotification userInfo];
NSString *desc = [ui valueForKey:@"desc"];
[[ProgressController mainProgressController] setJobDesc:desc];

View File

@@ -0,0 +1,12 @@
/* Class = "NSPanel"; title = "Details of Selected File"; ObjectID = "5"; */
"5.title" = "Details of Selected File";
/* Class = "NSTableColumn"; headerCell.title = "Selected"; ObjectID = "9"; */
"9.headerCell.title" = "Selected";
/* Class = "NSTableColumn"; headerCell.title = "Reference"; ObjectID = "10"; */
"10.headerCell.title" = "Reference";
/* Class = "NSTableColumn"; headerCell.title = "Attribute"; ObjectID = "11"; */
"11.headerCell.title" = "Attribute";

View File

@@ -0,0 +1,23 @@
/* Class = "NSTableColumn"; headerCell.title = "State"; ObjectID = "13"; */
"13.headerCell.title" = "State";
/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "15"; */
"15.headerCell.title" = "Name";
/* Class = "NSButtonCell"; title = "Scan"; ObjectID = "48"; */
"48.title" = "Scan";
/* Class = "NSMenuItem"; title = "Normal"; ObjectID = "55"; */
"55.title" = "Normal";
/* Class = "NSMenuItem"; title = "Reference"; ObjectID = "56"; */
"56.title" = "Reference";
/* Class = "NSMenuItem"; title = "Excluded"; ObjectID = "57"; */
"57.title" = "Excluded";
/* Class = "NSTextFieldCell"; title = "Select folders to scan and press \"Scan\"."; ObjectID = "71"; */
"71.title" = "Select folders to scan and press \"Scan\".";
/* Class = "NSButtonCell"; title = "Load Results"; ObjectID = "73"; */
"73.title" = "Load Results";

View File

@@ -0,0 +1,63 @@
"Add New Folder..." = "Add New Folder...";
"Load from file..." = "Load from file...";
"Reset to Default" = "Reset to Default";
"Add iTunes Directory" = "Add iTunes Directory";
"Remove Dead Tracks in iTunes" = "Remove Dead Tracks in iTunes";
"Add iPhoto Library" = "Add iPhoto Library";
"Clear Picture Cache" = "Clear Picture Cache";
/* Columns */
"Folder" = "Folder";
"Size (KB)" = "Size (KB)";
"Size (MB)" = "Size (MB)";
"Kind" = "Kind";
"Modification" = "Modification";
"Match %" = "Match %";
"Words Used" = "Words Used";
"Dupe Count" = "Dupe Count";
"Time" = "Time";
"Bitrate" = "Bitrate";
"Sample Rate" = "Sample Rate";
"Title" = "Title";
"Artist" = "Artist";
"Album" = "Album";
"Genre" = "Genre";
"Year" = "Year";
"Track Number" = "Track Number";
"Comment" = "Comment";
"Dimensions" = "Dimensions";
/* Messages */
"SelectResultToLoadMsg" = "Select a results file to load";
"SelectCopyDestinationMsg" = "Select a directory to copy marked files to";
"SelectMoveDestinationMsg" = "Select a directory to move marked files to";
"SelectResultToSaveMsg" = "Select a file to save your results to";
"SelectFolderToAddMsg" = "Select a folder to add to the scanning list";
"ReallyWantToQuitMsg" = "You have unsaved results, do you really want to quit?";
"ReallyWantToContinueMsg" = "You have unsaved results, do you really want to continue?";
"FolderAlreadyInListMsg" = "'%@' already is in the list.";
"FolderDoesNotExistMsg" = "'%@' does not exist.";
"FileRemovalConfirmMsg" = "You are about to remove %d files from results. Continue?";
"FilenameAlreadyExistsMsg" = "The name '%@' already exists.";
"NoScannableFileMsg" = "The selected directories contain no scannable file.";
"UnknownErrorMsg" = "Unknown Error.";
"SendToTrashConfirmMsg" = "You are about to send %d files to Trash. Continue?";
"HardlinkConfirmMsg" = "You are about to send %d files to Trash (and hardlink them afterwards). Continue?";
"ClearIgnoreListConfirmMsg" = "Do you really want to remove all %d items from the ignore list?";
"IgnoreConfirmMsg" = "All selected %d matches are going to be ignored in all subsequent scans. Continue?";
"NoCustomCommandMsg" = "You have no custom command set up. Set it up in your preferences.";
"CopySuccessMsg" = "All marked files were copied sucessfully.";
"MoveSuccessMsg" = "All marked files were moved sucessfully.";
"SendToTrashSuccessMsg" = "All marked files were sucessfully sent to Trash.";
"NoDuplicateFoundMsg" = "No duplicates found.";
"TaskHangingMsg" = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again.";
"RemoveDeadTracksConfirmMsg" = "Your iTunes Library contains %d dead tracks ready to be removed. Continue?";
"NoDeadTrackMsg" = "You have no dead tracks in your iTunes Library";
"IPhotoAppNotFoundMsg" = "The iPhoto application couldn't be found.";
"ClearPictureCacheConfirmMsg" = "Do you really want to remove all your cached picture analysis?";

View File

@@ -0,0 +1,174 @@
/* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "5"; */
"5.title" = "Bring All to Front";
/* Class = "NSMenuItem"; title = "Window"; ObjectID = "19"; */
"19.title" = "Window";
/* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "23"; */
"23.title" = "Minimize";
/* Class = "NSMenu"; title = "Window"; ObjectID = "24"; */
"24.title" = "Window";
/* Class = "NSMenuItem"; title = "About dupeGuru"; ObjectID = "58"; */
"58.title" = "About dupeGuru";
/* Class = "NSMenuItem"; title = "Help"; ObjectID = "103"; */
"103.title" = "Help";
/* Class = "NSMenu"; title = "Help"; ObjectID = "106"; */
"106.title" = "Help";
/* Class = "NSMenuItem"; title = "dupeGuru Help"; ObjectID = "111"; */
"111.title" = "dupeGuru Help";
/* Class = "NSMenuItem"; title = "Hide dupeGuru"; ObjectID = "134"; */
"134.title" = "Hide dupeGuru";
/* Class = "NSMenuItem"; title = "Quit dupeGuru"; ObjectID = "136"; */
"136.title" = "Quit dupeGuru";
/* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "145"; */
"145.title" = "Hide Others";
/* Class = "NSMenuItem"; title = "Show All"; ObjectID = "150"; */
"150.title" = "Show All";
/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "197"; */
"197.title" = "Zoom";
/* Class = "NSMenuItem"; title = "Details Panel"; ObjectID = "398"; */
"398.title" = "Details Panel";
/* Class = "NSMenuItem"; title = "Preferences..."; ObjectID = "541"; */
"541.title" = "Preferences...";
/* Class = "NSMenuItem"; title = "Folder Selection Window"; ObjectID = "579"; */
"579.title" = "Folder Selection Window";
/* Class = "NSMenuItem"; title = "Actions"; ObjectID = "597"; */
"597.title" = "Actions";
/* Class = "NSMenu"; title = "Actions"; ObjectID = "598"; */
"598.title" = "Actions";
/* Class = "NSMenuItem"; title = "Send Marked to Trash"; ObjectID = "599"; */
"599.title" = "Send Marked to Trash";
/* Class = "NSMenuItem"; title = "Move Marked to..."; ObjectID = "600"; */
"600.title" = "Move Marked to...";
/* Class = "NSMenuItem"; title = "Copy Marked to..."; ObjectID = "601"; */
"601.title" = "Copy Marked to...";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "602"; */
"602.title" = "Make Selected Reference";
/* Class = "NSMenuItem"; title = "Remove Marked from Results"; ObjectID = "603"; */
"603.title" = "Remove Marked from Results";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "605"; */
"605.title" = "Remove Selected from Results";
/* Class = "NSMenuItem"; title = "Columns"; ObjectID = "618"; */
"618.title" = "Columns";
/* Class = "NSMenu"; title = "Columns"; ObjectID = "619"; */
"619.title" = "Columns";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "708"; */
"708.title" = "Open Selected with Default Application";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "710"; */
"710.title" = "Reveal Selected in Finder";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "922"; */
"922.title" = "Add Selected to Ignore List";
/* Class = "NSMenuItem"; title = "Close Window"; ObjectID = "924"; */
"924.title" = "Close Window";
/* Class = "NSMenuItem"; title = "Start Duplicate Scan"; ObjectID = "926"; */
"926.title" = "Start Duplicate Scan";
/* Class = "NSMenuItem"; title = "Clear Ignore List"; ObjectID = "927"; */
"927.title" = "Clear Ignore List";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "933"; */
"933.title" = "Rename Selected";
/* Class = "NSMenuItem"; title = "Export Results to XHTML"; ObjectID = "947"; */
"947.title" = "Export Results to XHTML";
/* Class = "NSMenuItem"; title = "Check for update..."; ObjectID = "950"; */
"950.title" = "Check for update...";
/* Class = "NSMenuItem"; title = "Mode"; ObjectID = "959"; */
"959.title" = "Mode";
/* Class = "NSMenu"; title = "Mode"; ObjectID = "960"; */
"960.title" = "Mode";
/* Class = "NSMenuItem"; title = "Show Dupes Only"; ObjectID = "961"; */
"961.title" = "Show Dupes Only";
/* Class = "NSMenuItem"; title = "Show Delta Values"; ObjectID = "962"; */
"962.title" = "Show Delta Values";
/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "965"; */
"965.title" = "Edit";
/* Class = "NSMenu"; title = "Edit"; ObjectID = "966"; */
"966.title" = "Edit";
/* Class = "NSMenuItem"; title = "Cut"; ObjectID = "985"; */
"985.title" = "Cut";
/* Class = "NSMenuItem"; title = "Copy"; ObjectID = "986"; */
"986.title" = "Copy";
/* Class = "NSMenuItem"; title = "Paste"; ObjectID = "991"; */
"991.title" = "Paste";
/* Class = "NSMenuItem"; title = "Mark All"; ObjectID = "1011"; */
"1011.title" = "Mark All";
/* Class = "NSMenuItem"; title = "Mark None"; ObjectID = "1012"; */
"1012.title" = "Mark None";
/* Class = "NSMenuItem"; title = "Invert Marking"; ObjectID = "1013"; */
"1013.title" = "Invert Marking";
/* Class = "NSMenuItem"; title = "Mark Selected"; ObjectID = "1014"; */
"1014.title" = "Mark Selected";
/* Class = "NSMenuItem"; title = "dupeGuru Website"; ObjectID = "1023"; */
"1023.title" = "dupeGuru Website";
/* Class = "NSMenuItem"; title = "Invoke Custom Command"; ObjectID = "1177"; */
"1177.title" = "Invoke Custom Command";
/* Class = "NSMenuItem"; title = "File"; ObjectID = "1203"; */
"1203.title" = "File";
/* Class = "NSMenu"; title = "File"; ObjectID = "1204"; */
"1204.title" = "File";
/* Class = "NSMenuItem"; title = "Load Results..."; ObjectID = "1205"; */
"1205.title" = "Load Results...";
/* Class = "NSMenuItem"; title = "Save Results..."; ObjectID = "1206"; */
"1206.title" = "Save Results...";
/* Class = "NSMenuItem"; title = "Delete Marked and Replace with Hardlinks"; ObjectID = "1227"; */
"1227.title" = "Delete Marked and Replace with Hardlinks";
/* Class = "NSMenuItem"; title = "Load Recent Results"; ObjectID = "1239"; */
"1239.title" = "Load Recent Results";
/* Class = "NSMenu"; title = "Load Recent Results"; ObjectID = "1240"; */
"1240.title" = "Load Recent Results";
/* Class = "NSMenuItem"; title = "Results Window"; ObjectID = "1272"; */
"1272.title" = "Results Window";

View File

@@ -0,0 +1,18 @@
/* Class = "NSWindow"; title = "Problems!"; ObjectID = "1"; */
"1.title" = "Problems!";
/* Class = "NSTextFieldCell"; title = "There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results."; ObjectID = "4"; */
"4.title" = "There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results.";
/* Class = "NSTableColumn"; headerCell.title = "File Path"; ObjectID = "10"; */
"10.headerCell.title" = "File Path";
/* Class = "NSTableColumn"; headerCell.title = "Error Message"; ObjectID = "11"; */
"11.headerCell.title" = "Error Message";
/* Class = "NSButtonCell"; title = "Close"; ObjectID = "19"; */
"19.title" = "Close";
/* Class = "NSButtonCell"; title = "Reveal Selected"; ObjectID = "21"; */
"21.title" = "Reveal Selected";

View File

@@ -0,0 +1,99 @@
/* Class = "NSWindow"; title = "dupeGuru Results"; ObjectID = "1"; */
"1.title" = "dupeGuru Results";
/* Class = "NSTextFieldCell"; title = "Marked: 0 files, 0 B. Total: 0 files, 0 B."; ObjectID = "6"; */
"6.title" = "Marked: 0 files, 0 B. Total: 0 files, 0 B.";
/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "11"; */
"11.headerCell.title" = "Name";
/* Class = "NSToolbarItem"; label = "Options"; ObjectID = "15"; */
"15.label" = "Options";
/* Class = "NSToolbarItem"; paletteLabel = "Options"; ObjectID = "15"; */
"15.paletteLabel" = "Options";
/* Class = "NSToolbarItem"; label = "Filter"; ObjectID = "16"; */
"16.label" = "Filter";
/* Class = "NSToolbarItem"; paletteLabel = "Filter"; ObjectID = "16"; */
"16.paletteLabel" = "Filter";
/* Class = "NSToolbarItem"; label = "Action"; ObjectID = "17"; */
"17.label" = "Action";
/* Class = "NSToolbarItem"; paletteLabel = "Action"; ObjectID = "17"; */
"17.paletteLabel" = "Action";
/* Class = "NSToolbarItem"; label = "Directories"; ObjectID = "19"; */
"19.label" = "Directories";
/* Class = "NSToolbarItem"; paletteLabel = "Directories"; ObjectID = "19"; */
"19.paletteLabel" = "Directories";
/* Class = "NSMenuItem"; title = "Delete Marked and Replace with Hardlinks"; ObjectID = "27"; */
"27.title" = "Delete Marked and Replace with Hardlinks";
/* Class = "NSMenuItem"; title = "Send Marked to Trash"; ObjectID = "29"; */
"29.title" = "Send Marked to Trash";
/* Class = "NSMenuItem"; title = "Move Marked to..."; ObjectID = "30"; */
"30.title" = "Move Marked to...";
/* Class = "NSMenuItem"; title = "Copy Marked to..."; ObjectID = "31"; */
"31.title" = "Copy Marked to...";
/* Class = "NSMenuItem"; title = "Remove Marked from Results"; ObjectID = "32"; */
"32.title" = "Remove Marked from Results";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "34"; */
"34.title" = "Remove Selected from Results";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "35"; */
"35.title" = "Add Selected to Ignore List";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "36"; */
"36.title" = "Make Selected Reference";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "38"; */
"38.title" = "Open Selected with Default Application";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "39"; */
"39.title" = "Reveal Selected in Finder";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "40"; */
"40.title" = "Rename Selected";
/* Class = "NSSearchFieldCell"; placeholderString = "Filter"; ObjectID = "42"; */
"42.placeholderString" = "Filter";
/* Class = "NSSegmentedCell"; 44.labels[0] = "Details"; ObjectID = "44"; */
"44.labels[0]" = "Details";
/* Class = "NSSegmentedCell"; 44.labels[1] = "Dupes Only"; ObjectID = "44"; */
"44.labels[1]" = "Dupes Only";
/* Class = "NSSegmentedCell"; 44.labels[2] = "Delta"; ObjectID = "44"; */
"44.labels[2]" = "Delta";
/* Class = "NSMenu"; title = "Menu"; ObjectID = "67"; */
"67.title" = "Menu";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "68"; */
"68.title" = "Add Selected to Ignore List";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "70"; */
"70.title" = "Rename Selected";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "71"; */
"71.title" = "Remove Selected from Results";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "72"; */
"72.title" = "Make Selected Reference";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "73"; */
"73.title" = "Reveal Selected in Finder";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "74"; */
"74.title" = "Open Selected with Default Application";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
"Collecting files to scan" = "Collecting files to scan";
"%s (%d discarded)" = "%s (%d discarded)";
"Scanning for duplicates" = "Scanning for duplicates";
"Loading" = "Loading";
"Moving" = "Moving";
"Copying" = "Copying";
"Sending to Trash" = "Sending to Trash";
"0 matches found" = "0 matches found";
"%d matches found" = "%d matches found";
"Read size of %d/%d files" = "Read size of %d/%d files";
"Grouped %d/%d matches" = "Grouped %d/%d matches";
"%d / %d (%s / %s) duplicates marked." = "%d / %d (%s / %s) duplicates marked.";
" filter: %s" = " filter: %s";
"Read size of %d/%d files" = "Read size of %d/%d files";
"Read metadata of %d/%d files" = "Read metadata of %d/%d files";
"Removing false matches" = "Removing false matches";
"Processed %d/%d matches against the ignore list" = "Processed %d/%d matches against the ignore list";
"Doing group prioritization" = "Doing group prioritization";
"Analyzed %d/%d pictures" = "Analyzed %d/%d pictures";
"Preparing for matching" = "Preparing for matching";
"Matched %d/%d pictures" = "Matched %d/%d pictures";
"Verified %d/%d matches" = "Verified %d/%d matches";
"Removing dead tracks from your iTunes Library" = "Removing dead tracks from your iTunes Library";
"Scanning the iTunes Library" = "Scanning the iTunes Library";
"Probing iPhoto. Don't touch it during the operation!" = "Probing iPhoto. Don't touch it during the operation!";
"Sending dupes to the Trash" = "Sending dupes to the Trash";

View File

@@ -0,0 +1,12 @@
/* Class = "NSPanel"; title = "Details of Selected File"; ObjectID = "5"; */
"5.title" = "Détails du fichier sélectionné";
/* Class = "NSTableColumn"; headerCell.title = "Selected"; ObjectID = "9"; */
"9.headerCell.title" = "Sélectionné";
/* Class = "NSTableColumn"; headerCell.title = "Reference"; ObjectID = "10"; */
"10.headerCell.title" = "Référence";
/* Class = "NSTableColumn"; headerCell.title = "Attribute"; ObjectID = "11"; */
"11.headerCell.title" = "Attribut";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
/* Class = "NSTableColumn"; headerCell.title = "State"; ObjectID = "13"; */
"13.headerCell.title" = "Type";
/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "15"; */
"15.headerCell.title" = "Nom";
/* Class = "NSButtonCell"; title = "Scan"; ObjectID = "48"; */
"48.title" = "Scan";
/* Class = "NSMenuItem"; title = "Normal"; ObjectID = "55"; */
"55.title" = "Normal";
/* Class = "NSMenuItem"; title = "Reference"; ObjectID = "56"; */
"56.title" = "Référence";
/* Class = "NSMenuItem"; title = "Excluded"; ObjectID = "57"; */
"57.title" = "Exclus";
/* Class = "NSTextFieldCell"; title = "Select folders to scan and press \"Scan\"."; ObjectID = "71"; */
"71.title" = "Sélectionnez les dossiers à scanner et cliquez sur Scan.";
/* Class = "NSButtonCell"; title = "Load Results"; ObjectID = "73"; */
"73.title" = "Charger";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
"Add New Folder..." = "Ajouter dossier...";
"Load from file..." = "Charger un fichier...";
"Reset to Default" = "Colonnes par défault";
"Add iTunes Directory" = "Ajouter librairie iTunes";
"Remove Dead Tracks in iTunes" = "Retirer les tracks mortes dans iTunes";
"Add iPhoto Library" = "Ajouter librairie iPhoto";
"Clear Picture Cache" = "Vider la cache d'images";
/* Columns */
"Folder" = "Dossier";
"Size (KB)" = "Taille (KB)";
"Size (MB)" = "Taille (MB)";
"Kind" = "Type";
"Modification" = "Modification";
"Match %" = "Match %";
"Words Used" = "Mots";
"Dupe Count" = "# Doublons";
"Time" = "Temps";
"Bitrate" = "Bitrate";
"Sample Rate" = "Sample Rate";
"Title" = "Titre";
"Artist" = "Artiste";
"Album" = "Album";
"Genre" = "Genre";
"Year" = "Année";
"Track Number" = "Track";
"Comment" = "Commentaire";
"Dimensions" = "Dimensions";
/* Messages */
"SelectResultToLoadMsg" = "Sélectionnez un fichier résultats à charger";
"SelectCopyDestinationMsg" = "Sélectionnez un dossier vers lequel copier les fichiers";
"SelectMoveDestinationMsg" = "Sélectionnez un dossier vers lequel déplacer les fichiers";
"SelectResultToSaveMsg" = "Sélectionnez un fichier résultats dans lequel sauvegarder";
"SelectFolderToAddMsg" = "Sélectionnez un dossier à ajouter à la liste";
"ReallyWantToQuitMsg" = "Vos résultats ne sont pas sauvegardés. Voulez-vous vraiment quitter?";
"ReallyWantToContinueMsg" = "Vos résultats ne sont pas sauvegardés. Voulez-vous vraiment continuer?";
"FolderAlreadyInListMsg" = "'%@' est déjà dans la liste.";
"FolderDoesNotExistMsg" = "'%@' n'existe pas.";
"FileRemovalConfirmMsg" = "%d fichiers seront retirés des résultats. Continuer?";
"FilenameAlreadyExistsMsg" = "Le nom '%@' existe déjà.";
"NoScannableFileMsg" = "Les dossiers sélectionnés ne continnent pas de fichiers valides.";
"UnknownErrorMsg" = "Erreur inconnue.";
"SendToTrashConfirmMsg" = "%d fichiers seront envoyés à la corbeille. Continuer?";
"HardlinkConfirmMsg" = "%d fichiers seront envoyés à la corbeille (puis 'hardlinkés'). Continuer?";
"ClearIgnoreListConfirmMsg" = "Voulez-vous vider la liste de fichiers ignorés des %d items qu'elle contient?";
"IgnoreConfirmMsg" = "%d fichiers seront ignorés des prochains scans. Continuer?";
"NoCustomCommandMsg" = "Vous n'avez pas de commande personnalisée. Ajoutez-la dans vos préférences.";
"CopySuccessMsg" = "Tous les fichiers marqués ont été copiés correctement.";
"MoveSuccessMsg" = "Tous les fichiers déplacés ont été copiés correctement.";
"SendToTrashSuccessMsg" = "Tous les fichiers marqués ont été correctement envoyés à la corbeille.";
"NoDuplicateFoundMsg" = "Aucun doublon trouvé.";
"TaskHangingMsg" = "Une action précédente est encore en cours. Attendez quelques secondes avant d'en repartir une nouvelle.";
"RemoveDeadTracksConfirmMsg" = "Votre librairie iTunes contient %d tracks mortes qui seront retirées. Continuer?";
"NoDeadTrackMsg" = "Votre librairie iTunes ne contient aucune track morte.";
"IPhotoAppNotFoundMsg" = "iPhoto n'a pas pu être trouvée dans vos applications.";
"ClearPictureCacheConfirmMsg" = "Voulez-vous vraiment vider la cache de vos analyses précédentes?";

View File

@@ -0,0 +1,174 @@
/* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "5"; */
"5.title" = "Tout ramener au premier plan";
/* Class = "NSMenuItem"; title = "Window"; ObjectID = "19"; */
"19.title" = "Fenêtre";
/* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "23"; */
"23.title" = "Placer dans le Dock";
/* Class = "NSMenu"; title = "Window"; ObjectID = "24"; */
"24.title" = "Fenêtre";
/* Class = "NSMenuItem"; title = "About dupeGuru"; ObjectID = "58"; */
"58.title" = "À propos de dupeGuru";
/* Class = "NSMenuItem"; title = "Help"; ObjectID = "103"; */
"103.title" = "Aide";
/* Class = "NSMenu"; title = "Help"; ObjectID = "106"; */
"106.title" = "Aide";
/* Class = "NSMenuItem"; title = "dupeGuru Help"; ObjectID = "111"; */
"111.title" = "Aide dupeGuru";
/* Class = "NSMenuItem"; title = "Hide dupeGuru"; ObjectID = "134"; */
"134.title" = "Masquer dupeGuru";
/* Class = "NSMenuItem"; title = "Quit dupeGuru"; ObjectID = "136"; */
"136.title" = "Quitter dupeGuru";
/* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "145"; */
"145.title" = "Masquer les autres";
/* Class = "NSMenuItem"; title = "Show All"; ObjectID = "150"; */
"150.title" = "Tout afficher";
/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "197"; */
"197.title" = "Réduire/agrandir";
/* Class = "NSMenuItem"; title = "Details Panel"; ObjectID = "398"; */
"398.title" = "Fenêtre de détails";
/* Class = "NSMenuItem"; title = "Preferences..."; ObjectID = "541"; */
"541.title" = "Préférences...";
/* Class = "NSMenuItem"; title = "Folder Selection Window"; ObjectID = "579"; */
"579.title" = "Fenêtre de sélection de dossiers";
/* Class = "NSMenuItem"; title = "Actions"; ObjectID = "597"; */
"597.title" = "Actions";
/* Class = "NSMenu"; title = "Actions"; ObjectID = "598"; */
"598.title" = "Actions";
/* Class = "NSMenuItem"; title = "Send Marked to Trash"; ObjectID = "599"; */
"599.title" = "Envoyer marqués à la corbeille";
/* Class = "NSMenuItem"; title = "Move Marked to..."; ObjectID = "600"; */
"600.title" = "Déplacer marqués vers...";
/* Class = "NSMenuItem"; title = "Copy Marked to..."; ObjectID = "601"; */
"601.title" = "Copier marqués vers...";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "602"; */
"602.title" = "Transformer sélectionnés en références";
/* Class = "NSMenuItem"; title = "Remove Marked from Results"; ObjectID = "603"; */
"603.title" = "Retirer marqués des résultats";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "605"; */
"605.title" = "Retirer sélectionnés des résultats";
/* Class = "NSMenuItem"; title = "Columns"; ObjectID = "618"; */
"618.title" = "Colonnes";
/* Class = "NSMenu"; title = "Columns"; ObjectID = "619"; */
"619.title" = "Colonnes";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "708"; */
"708.title" = "Ouvrir sélectionné avec l'application par défaut";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "710"; */
"710.title" = "Révéler sélectionné dans Finder";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "922"; */
"922.title" = "Ajouter sélectionnés à la liste de fichiers ignorés";
/* Class = "NSMenuItem"; title = "Close Window"; ObjectID = "924"; */
"924.title" = "Fermer";
/* Class = "NSMenuItem"; title = "Start Duplicate Scan"; ObjectID = "926"; */
"926.title" = "Commencer à scanner";
/* Class = "NSMenuItem"; title = "Clear Ignore List"; ObjectID = "927"; */
"927.title" = "Vider la liste de fichiers ignorés";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "933"; */
"933.title" = "Renommer sélectionné";
/* Class = "NSMenuItem"; title = "Export Results to XHTML"; ObjectID = "947"; */
"947.title" = "Exporter les résultats vers HTML";
/* Class = "NSMenuItem"; title = "Check for update..."; ObjectID = "950"; */
"950.title" = "Mise à jour...";
/* Class = "NSMenuItem"; title = "Mode"; ObjectID = "959"; */
"959.title" = "Mode";
/* Class = "NSMenu"; title = "Mode"; ObjectID = "960"; */
"960.title" = "Mode";
/* Class = "NSMenuItem"; title = "Show Dupes Only"; ObjectID = "961"; */
"961.title" = "Ne pas montrer les références";
/* Class = "NSMenuItem"; title = "Show Delta Values"; ObjectID = "962"; */
"962.title" = "Montrer les valeurs en tant que delta";
/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "965"; */
"965.title" = "Édition";
/* Class = "NSMenu"; title = "Edit"; ObjectID = "966"; */
"966.title" = "Édition";
/* Class = "NSMenuItem"; title = "Cut"; ObjectID = "985"; */
"985.title" = "Couper";
/* Class = "NSMenuItem"; title = "Copy"; ObjectID = "986"; */
"986.title" = "Copier";
/* Class = "NSMenuItem"; title = "Paste"; ObjectID = "991"; */
"991.title" = "Coller";
/* Class = "NSMenuItem"; title = "Mark All"; ObjectID = "1011"; */
"1011.title" = "Tout marquer";
/* Class = "NSMenuItem"; title = "Mark None"; ObjectID = "1012"; */
"1012.title" = "Tout démarquer";
/* Class = "NSMenuItem"; title = "Invert Marking"; ObjectID = "1013"; */
"1013.title" = "Inverser le marquage";
/* Class = "NSMenuItem"; title = "Mark Selected"; ObjectID = "1014"; */
"1014.title" = "Marquer sélectionnés";
/* Class = "NSMenuItem"; title = "dupeGuru Website"; ObjectID = "1023"; */
"1023.title" = "Site web de dupeGuru";
/* Class = "NSMenuItem"; title = "Invoke Custom Command"; ObjectID = "1177"; */
"1177.title" = "Invoquer commande personnalisée";
/* Class = "NSMenuItem"; title = "File"; ObjectID = "1203"; */
"1203.title" = "Fichier";
/* Class = "NSMenu"; title = "File"; ObjectID = "1204"; */
"1204.title" = "Fichier";
/* Class = "NSMenuItem"; title = "Load Results..."; ObjectID = "1205"; */
"1205.title" = "Charger résultats...";
/* Class = "NSMenuItem"; title = "Save Results..."; ObjectID = "1206"; */
"1206.title" = "Sauvegarder résultats...";
/* Class = "NSMenuItem"; title = "Delete Marked and Replace with Hardlinks"; ObjectID = "1227"; */
"1227.title" = "Remplacer marqués par des hardlinks";
/* Class = "NSMenuItem"; title = "Load Recent Results"; ObjectID = "1239"; */
"1239.title" = "Charger résultats récents";
/* Class = "NSMenu"; title = "Load Recent Results"; ObjectID = "1240"; */
"1240.title" = "Charger résultats récents";
/* Class = "NSMenuItem"; title = "Results Window"; ObjectID = "1272"; */
"1272.title" = "Fenêtre de résultats";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
/* Class = "NSWindow"; title = "Problems!"; ObjectID = "1"; */
"1.title" = "Problèmes!";
/* Class = "NSTextFieldCell"; title = "There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results."; ObjectID = "4"; */
"4.title" = "There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results.";
"4.title" = "Il y a eu des problèmes lors du traitement de certain (ou tous) fichiers. La cause de ces problèmes est décrite ci-dessous. Ces fichiers n'ont pas été enlevés des résultats.";
/* Class = "NSTableColumn"; headerCell.title = "File Path"; ObjectID = "10"; */
"10.headerCell.title" = "Chemin du fichier";
/* Class = "NSTableColumn"; headerCell.title = "Error Message"; ObjectID = "11"; */
"11.headerCell.title" = "Message d'erreur";
/* Class = "NSButtonCell"; title = "Close"; ObjectID = "19"; */
"19.title" = "Fermer";
/* Class = "NSButtonCell"; title = "Reveal Selected"; ObjectID = "21"; */
"21.title" = "Révéler Fichier";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
/* Class = "NSWindow"; title = "dupeGuru Results"; ObjectID = "1"; */
"1.title" = "dupeGuru (Résultats)";
/* Class = "NSTextFieldCell"; title = "Marked: 0 files, 0 B. Total: 0 files, 0 B."; ObjectID = "6"; */
"6.title" = "Marqués: 0 fichiers, 0 B. Total: 0 fichiers, 0 B.";
/* Class = "NSTableColumn"; headerCell.title = "Name"; ObjectID = "11"; */
"11.headerCell.title" = "Nom";
/* Class = "NSToolbarItem"; label = "Options"; ObjectID = "15"; */
"15.label" = "Options";
/* Class = "NSToolbarItem"; paletteLabel = "Options"; ObjectID = "15"; */
"15.paletteLabel" = "Options";
/* Class = "NSToolbarItem"; label = "Filter"; ObjectID = "16"; */
"16.label" = "Filtre";
/* Class = "NSToolbarItem"; paletteLabel = "Filter"; ObjectID = "16"; */
"16.paletteLabel" = "Filtre";
/* Class = "NSToolbarItem"; label = "Action"; ObjectID = "17"; */
"17.label" = "Action";
/* Class = "NSToolbarItem"; paletteLabel = "Action"; ObjectID = "17"; */
"17.paletteLabel" = "Action";
/* Class = "NSToolbarItem"; label = "Directories"; ObjectID = "19"; */
"19.label" = "Dossiers";
/* Class = "NSToolbarItem"; paletteLabel = "Directories"; ObjectID = "19"; */
"19.paletteLabel" = "Dossiers";
/* Class = "NSMenuItem"; title = "Delete Marked and Replace with Hardlinks"; ObjectID = "27"; */
"27.title" = "Remplacer marqués par des hardlinks";
/* Class = "NSMenuItem"; title = "Send Marked to Trash"; ObjectID = "29"; */
"29.title" = "Envoyer marqués à la corbeille";
/* Class = "NSMenuItem"; title = "Move Marked to..."; ObjectID = "30"; */
"30.title" = "Déplacer marqués vers...";
/* Class = "NSMenuItem"; title = "Copy Marked to..."; ObjectID = "31"; */
"31.title" = "Copier marqués vers...";
/* Class = "NSMenuItem"; title = "Remove Marked from Results"; ObjectID = "32"; */
"32.title" = "Retirer marqués des résultats";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "34"; */
"34.title" = "Retirer sélectionnés des résultats";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "35"; */
"35.title" = "Ajouter sélectionnés à la liste de fichiers ignorés";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "36"; */
"36.title" = "Transformer sélectionnés en références";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "38"; */
"38.title" = "Ouvrir sélectionné avec l'application par défaut";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "39"; */
"39.title" = "Révéler sélectionné dans Finder";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "40"; */
"40.title" = "Renommer sélectionné";
/* Class = "NSSearchFieldCell"; placeholderString = "Filter"; ObjectID = "42"; */
"42.placeholderString" = "Filtre";
/* Class = "NSSegmentedCell"; 44.labels[0] = "Details"; ObjectID = "44"; */
"44.labels[0]" = "Détails";
/* Class = "NSSegmentedCell"; 44.labels[1] = "Dupes Only"; ObjectID = "44"; */
"44.labels[1]" = "Sans réf.";
/* Class = "NSSegmentedCell"; 44.labels[2] = "Delta"; ObjectID = "44"; */
"44.labels[2]" = "Delta";
/* Class = "NSMenuItem"; title = "Add Selected to Ignore List"; ObjectID = "68"; */
"68.title" = "Ajouter sélectionnés à la liste de fichiers ignorés";
/* Class = "NSMenuItem"; title = "Rename Selected"; ObjectID = "70"; */
"70.title" = "Renommer sélectionné";
/* Class = "NSMenuItem"; title = "Remove Selected from Results"; ObjectID = "71"; */
"71.title" = "Retirer sélectionnés des résultats";
/* Class = "NSMenuItem"; title = "Make Selected Reference"; ObjectID = "72"; */
"72.title" = "Transformer sélectionnés en références";
/* Class = "NSMenuItem"; title = "Reveal Selected in Finder"; ObjectID = "73"; */
"73.title" = "Révéler sélectionné dans Finder";
/* Class = "NSMenuItem"; title = "Open Selected with Default Application"; ObjectID = "74"; */
"74.title" = "Ouvrir sélectionné avec l'application par défaut";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
"Collecting files to scan" = "Collecte des fichiers à scanner";
"%s (%d discarded)" = "%s (%d hors-groupe)";
"Scanning for duplicates" = "Scan de doublons en cours";
"Loading" = "Chargement en cours";
"Moving" = "Déplacement en cours";
"Copying" = "Copie en cours";
"Sending to Trash" = "Envoi vers corbeille";
"0 matches found" = "0 paires trouvées";
"%d matches found" = "%d paires trouvées";
"Read size of %d/%d files" = "Lu la taille de %d/%d fichiers";
"Grouped %d/%d matches" = "%d/%d paires groupées";
"%d / %d (%s / %s) duplicates marked." = "%d / %d (%s / %s) doublons marqués.";
" filter: %s" = " filtre: %s";
"Read metadata of %d/%d files" = "Lu les métadonnées de %d/%d fichiers";
"Removing false matches" = "Retrait des paires invalides";
"Processed %d/%d matches against the ignore list" = "Vérification de %d/%d paires dans la ignore list";
"Doing group prioritization" = "Prioritization des groupes";
"Analyzed %d/%d pictures" = "Analyzé %d/%d images";
"Preparing for matching" = "Préparation pour la comparaison";
"Matched %d/%d pictures" = "Comparé %d/%d images";
"Verified %d/%d matches" = "Vérifié %d/%d paires";
"Removing dead tracks from your iTunes Library" = "Retrait des tracks mortes de votre librairie iTunes";
"Scanning the iTunes Library" = "Scan de la librairie iTunes en cours";
"Probing iPhoto. Don't touch it during the operation!" = "Communication avec iPhoto en cours. N'y touchez pas!";
"Sending dupes to the Trash" = "Envoi de doublons à la corbeille en cours";

View File

@@ -12,8 +12,5 @@ http://www.hardcoded.net/licenses/bsd_license
#import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase {}
- (IBAction)openWebsite:(id)sender;
- (IBAction)toggleDirectories:(id)sender;
- (PyDupeGuru *)py;
@end

View File

@@ -7,12 +7,13 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import "AppDelegate.h"
#import "../../cocoalib/ProgressController.h"
#import "../../cocoalib/Utils.h"
#import "../../cocoalib/ValueTransformers.h"
#import "../../cocoalib/Dialogs.h"
#import "ProgressController.h"
#import "Utils.h"
#import "ValueTransformers.h"
#import "Dialogs.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h"
#import "ResultWindow.h"
#import "Consts.h"
@implementation AppDelegate
@@ -56,32 +57,30 @@ http://www.hardcoded.net/licenses/bsd_license
return self;
}
- (IBAction)openWebsite:(id)sender
- (NSString *)homepageURL
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_me"]];
return @"http://www.hardcoded.net/dupeguru_me/";
}
- (IBAction)toggleDirectories:(id)sender
- (ResultWindowBase *)createResultWindow
{
[[self directoryPanel] toggleVisible:sender];
return [[ResultWindow alloc] initWithParentApp:self];
}
- (DirectoryPanel *)directoryPanel
- (DirectoryPanel *)createDirectoryPanel
{
if (!_directoryPanel)
_directoryPanel = [[DirectoryPanelME alloc] initWithParentApp:self];
return _directoryPanel;
return [[DirectoryPanelME alloc] initWithParentApp:self];
}
- (PyDupeGuru *)py { return (PyDupeGuru *)py; }
//Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSMenu *actionsMenu = [[[NSApp mainMenu] itemWithTitle:@"Actions"] submenu];
// index 3 is just after "Export Results to XHTML"
NSMenuItem *mi = [actionsMenu insertItemWithTitle:@"Remove Dead Tracks in iTunes"
NSMenuItem *mi = [actionsMenu insertItemWithTitle:TR(@"Remove Dead Tracks in iTunes")
action:@selector(removeDeadTracks:) keyEquivalent:@"" atIndex:3];
[mi setTarget:result];
[mi setTarget:[self resultWindow]];
[super applicationDidFinishLaunching:aNotification];
}
@end

View File

@@ -7,25 +7,28 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import "DirectoryPanel.h"
#import "Consts.h"
@implementation DirectoryPanelME
- (id)initWithParentApp:(id)aParentApp
{
self = [super initWithParentApp:aParentApp];
[[self window] setTitle:@"dupeGuru Music Edition"];
_alwaysShowPopUp = YES;
return self;
}
- (void)fillPopUpMenu
{
[super fillPopUpMenu];
NSMenu *m = [addButtonPopUp menu];
NSMenuItem *mi = [m insertItemWithTitle:TR(@"Add iTunes Directory") action:@selector(addiTunes:)
keyEquivalent:@"" atIndex:1];
[mi setTarget:self];
}
- (IBAction)addiTunes:(id)sender
{
[self addDirectory:[@"~/Music/iTunes/iTunes Music" stringByExpandingTildeInPath]];
}
- (IBAction)popupAddDirectoryMenu:(id)sender
{
NSMenu *m = [addButtonPopUp menu];
while ([m numberOfItems] > 0)
[m removeItemAtIndex:0];
NSMenuItem *mi = [m addItemWithTitle:@"Add New Directory..." action:@selector(askForDirectory:) keyEquivalent:@""];
[mi setTarget:self];
mi = [m addItemWithTitle:@"Add iTunes Directory" action:@selector(addiTunes:) keyEquivalent:@""];
[mi setTarget:self];
[m addItem:[NSMenuItem separatorItem]];
[_recentDirectories fillMenu:m];
[addButtonPopUp selectItem: nil];
[[addButtonPopUp cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
@end

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key>
<string>hsft</string>
<key>CFBundleVersion</key>
<string>5.10.3</string>
<string>{version}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>

View File

@@ -8,7 +8,6 @@ http://www.hardcoded.net/licenses/bsd_license
#import <Cocoa/Cocoa.h>
#import "../base/ResultWindow.h"
#import "DirectoryPanel.h"
@interface ResultWindow : ResultWindowBase {}
- (IBAction)removeDeadTracks:(id)sender;

View File

@@ -7,21 +7,59 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import "ResultWindow.h"
#import "../../cocoalib/Dialogs.h"
#import "../../cocoalib/ProgressController.h"
#import "../../cocoalib/Utils.h"
#import "AppDelegate.h"
#import "Dialogs.h"
#import "Utils.h"
#import "PyDupeGuru.h"
#import "Consts.h"
@implementation ResultWindow
/* Override */
- (void)awakeFromNib
- (void)setScanOptions
{
[super awakeFromNib];
[[self window] setTitle:@"dupeGuru Music Edition"];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,6)];
[deltaColumns removeIndex:6];
[table setDeltaColumns:deltaColumns];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setScanType:[ud objectForKey:@"scanType"]];
[_py enable:[ud objectForKey:@"scanTagTrack"] scanForTag:@"track"];
[_py enable:[ud objectForKey:@"scanTagArtist"] scanForTag:@"artist"];
[_py enable:[ud objectForKey:@"scanTagAlbum"] scanForTag:@"album"];
[_py enable:[ud objectForKey:@"scanTagTitle"] scanForTag:@"title"];
[_py enable:[ud objectForKey:@"scanTagGenre"] scanForTag:@"genre"];
[_py enable:[ud objectForKey:@"scanTagYear"] scanForTag:@"year"];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
}
- (void)initResultColumns
{
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:TR(@"Folder") width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TR(@"Size (MB)") width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
NSTableColumn *timeCol = [self getColumnForIdentifier:3 title:TR(@"Time") width:50 refCol:refCol];
[[timeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:timeCol];
NSTableColumn *brCol = [self getColumnForIdentifier:4 title:TR(@"Bitrate") width:50 refCol:refCol];
[[brCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:brCol];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:TR(@"Sample Rate") width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:TR(@"Kind") width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:TR(@"Modification") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:8 title:TR(@"Title") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:9 title:TR(@"Artist") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:10 title:TR(@"Album") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:11 title:TR(@"Genre") width:80 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:12 title:TR(@"Year") width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:13 title:TR(@"Track Number") width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:14 title:TR(@"Comment") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:15 title:TR(@"Match %") width:57 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:16 title:TR(@"Words Used") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:17 title:TR(@"Dupe Count") width:80 refCol:refCol]];
}
/* Actions */
@@ -49,83 +87,20 @@ http://www.hardcoded.net/licenses/bsd_license
[self restoreColumnsPosition:columnsOrder widths:columnsWidth];
}
- (IBAction)startDuplicateScan:(id)sender
{
if ([matches numberOfRows] > 0)
{
if ([Dialogs askYesNo:@"Are you sure you want to start a new duplicate scan?"] == NSAlertSecondButtonReturn) // NO
return;
}
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setScanType:[ud objectForKey:@"scanType"]];
[_py enable:[ud objectForKey:@"scanTagTrack"] scanForTag:@"track"];
[_py enable:[ud objectForKey:@"scanTagArtist"] scanForTag:@"artist"];
[_py enable:[ud objectForKey:@"scanTagAlbum"] scanForTag:@"album"];
[_py enable:[ud objectForKey:@"scanTagTitle"] scanForTag:@"title"];
[_py enable:[ud objectForKey:@"scanTagGenre"] scanForTag:@"genre"];
[_py enable:[ud objectForKey:@"scanTagYear"] scanForTag:@"year"];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
NSInteger r = n2i([py doScan]);
if (r == 3)
{
[Dialogs showMessage:@"The selected directories contain no scannable file."];
[app toggleDirectories:nil];
}
}
/* Public */
- (void)initResultColumns
{
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (MB)" width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
NSTableColumn *timeCol = [self getColumnForIdentifier:3 title:@"Time" width:50 refCol:refCol];
[[timeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:timeCol];
NSTableColumn *brCol = [self getColumnForIdentifier:4 title:@"Bitrate" width:50 refCol:refCol];
[[brCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:brCol];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Sample Rate" width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Modification" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:8 title:@"Title" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:9 title:@"Artist" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:10 title:@"Album" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:11 title:@"Genre" width:80 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:12 title:@"Year" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:13 title:@"Track Number" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:14 title:@"Comment" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:15 title:@"Match %" width:57 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:16 title:@"Words Used" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:17 title:@"Dupe Count" width:80 refCol:refCol]];
}
/* Notifications */
- (void)jobCompleted:(NSNotification *)aNotification
{
[super jobCompleted:aNotification];
id lastAction = [[ProgressController mainProgressController] jobId];
if ([lastAction isEqualTo:jobScanDeadTracks])
{
if ([lastAction isEqualTo:jobScanDeadTracks]) {
NSInteger deadTrackCount = [(PyDupeGuru *)py deadTrackCount];
if (deadTrackCount > 0)
{
NSString *msg = @"Your iTunes Library contains %d dead tracks ready to be removed. Continue?";
if (deadTrackCount > 0) {
NSString *msg = TR(@"RemoveDeadTracksConfirmMsg");
if ([Dialogs askYesNo:[NSString stringWithFormat:msg,deadTrackCount]] == NSAlertFirstButtonReturn)
[(PyDupeGuru *)py removeDeadTracks];
}
else
{
[Dialogs showMessage:@"You have no dead tracks in your iTunes Library"];
else {
[Dialogs showMessage:TR(@"NoDeadTrackMsg")];
}
}
}

View File

@@ -4,24 +4,16 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
from hscommon.cocoa import signature
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_me.app_cocoa import DupeGuruME
from core_me import __appname__
from core.scanner import ScanType
# Fix py2app imports which chokes on relative imports and other stuff
import core_me.app_cocoa, core_me.data, core_me.fs, core_me.scanner
import hsaudiotag.aiff, hsaudiotag.flac, hsaudiotag.genres, hsaudiotag.id3v1,\
hsaudiotag.id3v2, hsaudiotag.mp4, hsaudiotag.mpeg, hsaudiotag.ogg, hsaudiotag.wma
from hsaudiotag import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
import hsutil.conflict
import core.engine, core.fs, core.app
import xml.etree.ElementPath
import gzip
import aem.kae
import appscript.defaultterminology
class PyDupeGuru(PyDupeGuruBase):
def init(self):
self = super(PyDupeGuru,self).init()
@@ -70,5 +62,5 @@ class PyDupeGuru(PyDupeGuruBase):
#---Registration
def appName(self):
return "dupeGuru Music Edition"
return __appname__

View File

@@ -29,24 +29,31 @@
CE003CCB11242D00004B0AA7 /* NSIndexPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CC311242D00004B0AA7 /* NSIndexPathAdditions.m */; };
CE003CCC11242D00004B0AA7 /* NSTableViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CC511242D00004B0AA7 /* NSTableViewAdditions.m */; };
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CCE11242D2C004B0AA7 /* DirectoryOutline.m */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_me_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */; };
CE05331712E5D3ED0029EF25 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05330D12E5D3ED0029EF25 /* DetailsPanel.xib */; };
CE05331812E5D3ED0029EF25 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05330F12E5D3ED0029EF25 /* DirectoryPanel.xib */; };
CE05331912E5D3ED0029EF25 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05331112E5D3ED0029EF25 /* MainMenu.xib */; };
CE05331A12E5D3ED0029EF25 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05331312E5D3ED0029EF25 /* ProblemDialog.xib */; };
CE05331B12E5D3ED0029EF25 /* ResultWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05331512E5D3ED0029EF25 /* ResultWindow.xib */; };
CE05332312E5D4100029EF25 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05332112E5D4100029EF25 /* Preferences.xib */; };
CE05332F12E5D6100029EF25 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE05332D12E5D6100029EF25 /* Localizable.strings */; };
CE073F6309CAE1A3005C1D2F /* help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* help */; };
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */; };
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */; };
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */; };
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
CE14259F0AFB719300BD5167 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
CE1EAA0A12DF3E81009BA949 /* HSRecentFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = CE1EAA0912DF3E81009BA949 /* HSRecentFiles.m */; };
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE3FBDD31094637800B72D77 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3FBDD11094637800B72D77 /* DetailsPanel.xib */; };
CE3FBDD41094637800B72D77 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */; };
CE45274F12E5F62D00005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE45274D12E5F62D00005A15 /* core.strings */; };
CE49DEF60FDFEB810098617B /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */; };
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE4B59C51119919700C06C9E /* ErrorReportWindow.xib */; };
CE4B59C91119919700C06C9E /* progress.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE4B59C61119919700C06C9E /* progress.xib */; };
CE4F934612CCA9470067A3AE /* about.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE4F934512CCA9470067A3AE /* about.xib */; };
CE4F934912CCA96C0067A3AE /* HSAboutBox.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4F934812CCA96C0067A3AE /* HSAboutBox.m */; };
CE515DF30FC6C12E00EC695D /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DE10FC6C12E00EC695D /* Dialogs.m */; };
CE515DF40FC6C12E00EC695D /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DE30FC6C12E00EC695D /* HSErrorReportWindow.m */; };
CE515DF60FC6C12E00EC695D /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DE70FC6C12E00EC695D /* ProgressController.m */; };
CE515DF70FC6C12E00EC695D /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DEA0FC6C12E00EC695D /* RecentDirectories.m */; };
CE515DFA0FC6C12E00EC695D /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DF00FC6C12E00EC695D /* Utils.m */; };
CE515DFB0FC6C12E00EC695D /* ValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DF20FC6C12E00EC695D /* ValueTransformers.m */; };
CE515E1D0FC6C19300EC695D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515E160FC6C19300EC695D /* AppDelegate.m */; };
@@ -59,14 +66,10 @@
CE74A12412537F06008A8DF0 /* HSFairwareReminder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE74A12212537F06008A8DF0 /* HSFairwareReminder.m */; };
CE74A12712537F2E008A8DF0 /* FairwareReminder.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE74A12512537F2E008A8DF0 /* FairwareReminder.xib */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CE900AD2109B238600754048 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD1109B238600754048 /* Preferences.xib */; };
CE900AD7109B2A9B00754048 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD6109B2A9B00754048 /* MainMenu.xib */; };
CEB14D29124DFC2800FA7481 /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CEB14D28124DFC2800FA7481 /* ResultTable.m */; };
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDF07A2112493B200EE5BC0 /* StatsLabel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -86,7 +89,7 @@
/* Begin PBXFileReference section */
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
@@ -110,26 +113,45 @@
CE003CCD11242D2C004B0AA7 /* DirectoryOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DirectoryOutline.h; path = ../base/DirectoryOutline.h; sourceTree = SOURCE_ROOT; };
CE003CCE11242D2C004B0AA7 /* DirectoryOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DirectoryOutline.m; path = ../base/DirectoryOutline.m; sourceTree = SOURCE_ROOT; };
CE003CCF11242D2C004B0AA7 /* PyDirectoryOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDirectoryOutline.h; path = ../base/PyDirectoryOutline.h; sourceTree = SOURCE_ROOT; };
CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_me_help; path = ../../help_me/dupeguru_me_help; sourceTree = "<group>"; };
CE05330E12E5D3ED0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/DetailsPanel.xib; sourceTree = SOURCE_ROOT; };
CE05331012E5D3ED0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE05331212E5D3ED0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE05331412E5D3ED0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE05331612E5D3ED0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE05331C12E5D4010029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/DetailsPanel.xib; sourceTree = SOURCE_ROOT; };
CE05331D12E5D4010029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE05331E12E5D4010029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE05331F12E5D4010029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE05332012E5D4010029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE05332212E5D4100029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Preferences.xib; sourceTree = "<group>"; };
CE05332912E5D4460029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/Preferences.xib; sourceTree = "<group>"; };
CE05332E12E5D6100029EF25 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE05333312E5D6370029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE05347712E5DC420029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../../cocoalib/fr.lproj/FairwareReminder.xib; sourceTree = SOURCE_ROOT; };
CE073F5409CAE1A3005C1D2F /* help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = help; path = ../../build/help; sourceTree = "<group>"; };
CE0A0BFE1175A1C000DCA3C6 /* HSTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSTable.h; sourceTree = "<group>"; };
CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE0A0C011175A1DE00DCA3C6 /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE0A0C131175A28100DCA3C6 /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE1425880AFB718500BD5167 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE1EAA0812DF3E81009BA949 /* HSRecentFiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSRecentFiles.h; path = ../../cocoalib/HSRecentFiles.h; sourceTree = SOURCE_ROOT; };
CE1EAA0912DF3E81009BA949 /* HSRecentFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSRecentFiles.m; path = ../../cocoalib/HSRecentFiles.m; sourceTree = SOURCE_ROOT; };
CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
CE381C9509914ACE003581CE /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DetailsPanel.xib; path = ../../base/xib/DetailsPanel.xib; sourceTree = "<group>"; };
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DirectoryPanel.xib; path = ../../base/xib/DirectoryPanel.xib; sourceTree = "<group>"; };
CE45274E12E5F62D00005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE45275012E5F63900005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE49DEF20FDFEB810098617B /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; };
CE4B59C51119919700C06C9E /* ErrorReportWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ErrorReportWindow.xib; sourceTree = "<group>"; };
CE4B59C61119919700C06C9E /* progress.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = progress.xib; sourceTree = "<group>"; };
CE4F934512CCA9470067A3AE /* about.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = about.xib; path = ../../cocoalib/xib/about.xib; sourceTree = SOURCE_ROOT; };
CE4F934712CCA96C0067A3AE /* HSAboutBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSAboutBox.h; path = ../../cocoalib/HSAboutBox.h; sourceTree = SOURCE_ROOT; };
CE4F934812CCA96C0067A3AE /* HSAboutBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSAboutBox.m; path = ../../cocoalib/HSAboutBox.m; sourceTree = SOURCE_ROOT; };
CE515DE00FC6C12E00EC695D /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = ../../cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
CE515DE10FC6C12E00EC695D /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CE515DE20FC6C12E00EC695D /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
@@ -137,8 +159,6 @@
CE515DE60FC6C12E00EC695D /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CE515DE70FC6C12E00EC695D /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CE515DE80FC6C12E00EC695D /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
CE515DE90FC6C12E00EC695D /* RecentDirectories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecentDirectories.h; path = ../../cocoalib/RecentDirectories.h; sourceTree = SOURCE_ROOT; };
CE515DEA0FC6C12E00EC695D /* RecentDirectories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RecentDirectories.m; path = ../../cocoalib/RecentDirectories.m; sourceTree = SOURCE_ROOT; };
CE515DEF0FC6C12E00EC695D /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = ../../cocoalib/Utils.h; sourceTree = SOURCE_ROOT; };
CE515DF00FC6C12E00EC695D /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = ../../cocoalib/Utils.m; sourceTree = SOURCE_ROOT; };
CE515DF10FC6C12E00EC695D /* ValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueTransformers.h; path = ../../cocoalib/ValueTransformers.h; sourceTree = SOURCE_ROOT; };
@@ -163,8 +183,6 @@
CE74A12312537F06008A8DF0 /* PyFairware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyFairware.h; path = ../../cocoalib/PyFairware.h; sourceTree = SOURCE_ROOT; };
CE74A12612537F2E008A8DF0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../../cocoalib/en.lproj/FairwareReminder.xib; sourceTree = SOURCE_ROOT; };
CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE900AD1109B238600754048 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
CE900AD6109B2A9B00754048 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CEB14D26124DFC2800FA7481 /* PyResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTable.h; path = ../base/PyResultTable.h; sourceTree = SOURCE_ROOT; };
CEB14D27124DFC2800FA7481 /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CEB14D28124DFC2800FA7481 /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; sourceTree = SOURCE_ROOT; };
@@ -174,8 +192,6 @@
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = ../../images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = ../../images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = ../../images/preferences32.png; sourceTree = SOURCE_ROOT; };
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = PyDupeGuru.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -195,6 +211,7 @@
080E96DDFE201D6D7F000001 /* DGME */ = {
isa = PBXGroup;
children = (
29B97316FDCFA39411CA2CEA /* main.m */,
CE381C9509914ACE003581CE /* AppDelegate.h */,
CE381C9409914ACE003581CE /* AppDelegate.m */,
CE848A1809DD85810004CB44 /* Consts.h */,
@@ -240,7 +257,6 @@
080E96DDFE201D6D7F000001 /* DGME */,
CE515E140FC6C17900EC695D /* dgbase */,
CE515DDD0FC6C09400EC695D /* cocoalib */,
29B97315FDCFA39411CA2CEA /* Other Sources */,
29B97317FDCFA39411CA2CEA /* Resources */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
@@ -248,22 +264,16 @@
name = dupeguru;
sourceTree = "<group>";
};
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
29B97316FDCFA39411CA2CEA /* main.m */,
);
name = "Other Sources";
sourceTree = "<group>";
};
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
CE3FBDD01094637800B72D77 /* xib */,
CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */,
CE073F5409CAE1A3005C1D2F /* help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */,
CE05330C12E5D3D70029EF25 /* xib */,
CEEB135109C837A2004D2330 /* dupeguru.icns */,
CE05332D12E5D6100029EF25 /* Localizable.strings */,
CE45274D12E5F62D00005A15 /* core.strings */,
8D1107310486CEB800E47090 /* Info.plist */,
CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */,
);
@@ -322,16 +332,17 @@
path = ../../cocoalib/views;
sourceTree = SOURCE_ROOT;
};
CE3FBDD01094637800B72D77 /* xib */ = {
CE05330C12E5D3D70029EF25 /* xib */ = {
isa = PBXGroup;
children = (
CE900AD6109B2A9B00754048 /* MainMenu.xib */,
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
CE900AD1109B238600754048 /* Preferences.xib */,
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */,
CE05330D12E5D3ED0029EF25 /* DetailsPanel.xib */,
CE05330F12E5D3ED0029EF25 /* DirectoryPanel.xib */,
CE05331112E5D3ED0029EF25 /* MainMenu.xib */,
CE05331312E5D3ED0029EF25 /* ProblemDialog.xib */,
CE05331512E5D3ED0029EF25 /* ResultWindow.xib */,
CE05332112E5D4100029EF25 /* Preferences.xib */,
);
path = xib;
name = xib;
sourceTree = "<group>";
};
CE49DEF10FDFEB810098617B /* brsinglelineformatter */ = {
@@ -347,6 +358,7 @@
CE4B59C41119919700C06C9E /* xib */ = {
isa = PBXGroup;
children = (
CE4F934512CCA9470067A3AE /* about.xib */,
CE74A12512537F2E008A8DF0 /* FairwareReminder.xib */,
CE4B59C51119919700C06C9E /* ErrorReportWindow.xib */,
CE4B59C61119919700C06C9E /* progress.xib */,
@@ -370,13 +382,15 @@
CE74A12112537F06008A8DF0 /* HSFairwareReminder.h */,
CE74A12212537F06008A8DF0 /* HSFairwareReminder.m */,
CE74A12312537F06008A8DF0 /* PyFairware.h */,
CE4F934712CCA96C0067A3AE /* HSAboutBox.h */,
CE4F934812CCA96C0067A3AE /* HSAboutBox.m */,
CE1EAA0812DF3E81009BA949 /* HSRecentFiles.h */,
CE1EAA0912DF3E81009BA949 /* HSRecentFiles.m */,
CE003CB911242D00004B0AA7 /* NSEventAdditions.h */,
CE003CBA11242D00004B0AA7 /* NSEventAdditions.m */,
CE515DE60FC6C12E00EC695D /* ProgressController.h */,
CE515DE70FC6C12E00EC695D /* ProgressController.m */,
CE515DE80FC6C12E00EC695D /* PyApp.h */,
CE515DE90FC6C12E00EC695D /* RecentDirectories.h */,
CE515DEA0FC6C12E00EC695D /* RecentDirectories.m */,
CE515DEF0FC6C12E00EC695D /* Utils.h */,
CE515DF00FC6C12E00EC695D /* Utils.m */,
CE515DF10FC6C12E00EC695D /* ValueTransformers.h */,
@@ -418,8 +432,6 @@
CEFC294309C89E0000D9F998 /* images */ = {
isa = PBXGroup;
children = (
CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */,
);
name = images;
@@ -455,6 +467,7 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */;
compatibilityVersion = "Xcode 3.0";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
@@ -462,6 +475,7 @@
French,
German,
en,
fr,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */;
projectDirPath = "";
@@ -478,20 +492,22 @@
buildActionMask = 2147483647;
files = (
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_me_help in Resources */,
CE073F6309CAE1A3005C1D2F /* help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CE6E0E9F1054EB97008D9390 /* dsa_pub.pem in Resources */,
CE3FBDD31094637800B72D77 /* DetailsPanel.xib in Resources */,
CE3FBDD41094637800B72D77 /* DirectoryPanel.xib in Resources */,
CE900AD2109B238600754048 /* Preferences.xib in Resources */,
CE900AD7109B2A9B00754048 /* MainMenu.xib in Resources */,
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */,
CE4B59C91119919700C06C9E /* progress.xib in Resources */,
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */,
CE74A12712537F2E008A8DF0 /* FairwareReminder.xib in Resources */,
CE4F934612CCA9470067A3AE /* about.xib in Resources */,
CE05331712E5D3ED0029EF25 /* DetailsPanel.xib in Resources */,
CE05331812E5D3ED0029EF25 /* DirectoryPanel.xib in Resources */,
CE05331912E5D3ED0029EF25 /* MainMenu.xib in Resources */,
CE05331A12E5D3ED0029EF25 /* ProblemDialog.xib in Resources */,
CE05331B12E5D3ED0029EF25 /* ResultWindow.xib in Resources */,
CE05332312E5D4100029EF25 /* Preferences.xib in Resources */,
CE05332F12E5D6100029EF25 /* Localizable.strings in Resources */,
CE45274F12E5F62D00005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -509,7 +525,6 @@
CE515DF30FC6C12E00EC695D /* Dialogs.m in Sources */,
CE515DF40FC6C12E00EC695D /* HSErrorReportWindow.m in Sources */,
CE515DF60FC6C12E00EC695D /* ProgressController.m in Sources */,
CE515DF70FC6C12E00EC695D /* RecentDirectories.m in Sources */,
CE515DFA0FC6C12E00EC695D /* Utils.m in Sources */,
CE515DFB0FC6C12E00EC695D /* ValueTransformers.m in Sources */,
CE515E1D0FC6C19300EC695D /* AppDelegate.m in Sources */,
@@ -531,16 +546,91 @@
CEB14D29124DFC2800FA7481 /* ResultTable.m in Sources */,
CE578303124DFC660004769C /* HSTableView.m in Sources */,
CE74A12412537F06008A8DF0 /* HSFairwareReminder.m in Sources */,
CE4F934912CCA96C0067A3AE /* HSAboutBox.m in Sources */,
CE1EAA0A12DF3E81009BA949 /* HSRecentFiles.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
CE05330D12E5D3ED0029EF25 /* DetailsPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE05330E12E5D3ED0029EF25 /* en */,
CE05331C12E5D4010029EF25 /* fr */,
);
name = DetailsPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE05330F12E5D3ED0029EF25 /* DirectoryPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE05331012E5D3ED0029EF25 /* en */,
CE05331D12E5D4010029EF25 /* fr */,
);
name = DirectoryPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE05331112E5D3ED0029EF25 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
CE05331212E5D3ED0029EF25 /* en */,
CE05331E12E5D4010029EF25 /* fr */,
);
name = MainMenu.xib;
sourceTree = SOURCE_ROOT;
};
CE05331312E5D3ED0029EF25 /* ProblemDialog.xib */ = {
isa = PBXVariantGroup;
children = (
CE05331412E5D3ED0029EF25 /* en */,
CE05331F12E5D4010029EF25 /* fr */,
);
name = ProblemDialog.xib;
sourceTree = SOURCE_ROOT;
};
CE05331512E5D3ED0029EF25 /* ResultWindow.xib */ = {
isa = PBXVariantGroup;
children = (
CE05331612E5D3ED0029EF25 /* en */,
CE05332012E5D4010029EF25 /* fr */,
);
name = ResultWindow.xib;
sourceTree = SOURCE_ROOT;
};
CE05332112E5D4100029EF25 /* Preferences.xib */ = {
isa = PBXVariantGroup;
children = (
CE05332212E5D4100029EF25 /* en */,
CE05332912E5D4460029EF25 /* fr */,
);
name = Preferences.xib;
sourceTree = SOURCE_ROOT;
};
CE05332D12E5D6100029EF25 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
CE05332E12E5D6100029EF25 /* en */,
CE05333312E5D6370029EF25 /* fr */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
CE45274D12E5F62D00005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE45274E12E5F62D00005A15 /* en */,
CE45275012E5F63900005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
CE74A12512537F2E008A8DF0 /* FairwareReminder.xib */ = {
isa = PBXVariantGroup;
children = (
CE74A12612537F2E008A8DF0 /* en */,
CE05347712E5DC420029EF25 /* fr */,
);
name = FairwareReminder.xib;
path = ../../cocoalib/xib;

Binary file not shown.

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<string key="IBDocument.SystemVersion">10J567</string>
<string key="IBDocument.InterfaceBuilderVersion">823</string>
<string key="IBDocument.AppKitVersion">1038.35</string>
<string key="IBDocument.HIToolboxVersion">462.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">788</string>
<string key="NS.object.0">823</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -19,13 +19,8 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -41,14 +36,14 @@
<object class="NSUserDefaultsController" id="579641073">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>ignoreHardlinkMatches</string>
<string>DebugMode</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
<object class="NSWindowTemplate" id="793317856">
<int key="NSWindowStyleMask">3</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{92, 276}, {406, 326}}</string>
<string key="NSWindowRect">{{92, 259}, {406, 343}}</string>
<int key="NSWTFlags">1886912512</int>
<string key="NSWindowTitle">dupeGuru ME Preferences</string>
<object class="NSMutableString" key="NSWindowClass">
@@ -94,7 +89,7 @@
<object class="NSTabView" id="1019752720">
<reference key="NSNextResponder" ref="986069316"/>
<int key="NSvFlags">12</int>
<string key="NSFrame">{{13, 40}, {380, 280}}</string>
<string key="NSFrame">{{13, 40}, {380, 297}}</string>
<reference key="NSSuperview" ref="986069316"/>
<object class="NSMutableArray" key="NSTabViewItems">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -108,7 +103,7 @@
<object class="NSSlider" id="810949831">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{117, 172}, {190, 21}}</string>
<string key="NSFrame">{{117, 189}, {190, 21}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSliderCell" key="NSCell" id="735486969">
@@ -136,7 +131,7 @@
<object class="NSTextField" id="595766735">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{119, 155}, {80, 13}}</string>
<string key="NSFrame">{{119, 172}, {80, 13}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="274051075">
@@ -172,7 +167,7 @@
<object class="NSTextField" id="735544762">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">289</int>
<string key="NSFrame">{{225, 155}, {80, 13}}</string>
<string key="NSFrame">{{225, 172}, {80, 13}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="602722407">
@@ -188,7 +183,7 @@
<object class="NSTextField" id="152034108">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 177}, {100, 14}}</string>
<string key="NSFrame">{{14, 194}, {100, 14}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="368410553">
@@ -208,7 +203,7 @@
<object class="NSTextField" id="531187173">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{17, 218}, {85, 13}}</string>
<string key="NSFrame">{{17, 235}, {85, 13}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="511697312">
@@ -224,7 +219,7 @@
<object class="NSPopUpButton" id="353791762">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{110, 207}, {231, 26}}</string>
<string key="NSFrame">{{110, 224}, {231, 26}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="1039743040">
@@ -334,7 +329,7 @@
<object class="NSButton" id="102571342">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 91}, {214, 18}}</string>
<string key="NSFrame">{{15, 90}, {330, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="455609515">
@@ -357,7 +352,7 @@
<object class="NSButton" id="527948380">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 51}, {214, 18}}</string>
<string key="NSFrame">{{15, 50}, {325, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="812282968">
@@ -378,7 +373,7 @@
<object class="NSTextField" id="746186689">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{313, 177}, {31, 14}}</string>
<string key="NSFrame">{{313, 194}, {31, 14}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="661671041">
@@ -405,9 +400,11 @@
<boolean value="YES"/>
<object class="NSAttributedString" id="145123224">
<string key="NSString">0</string>
<object class="NSDictionary" key="NSAttributes" id="589681839">
<object class="NSDictionary" key="NSAttributes" id="601001826">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
@@ -431,7 +428,7 @@
</object>
<object class="NSAttributedString" key="NS.nan">
<string key="NSString">NaN</string>
<reference key="NSAttributes" ref="589681839"/>
<reference key="NSAttributes" ref="601001826"/>
</object>
<object class="NSDecimalNumberPlaceholder" key="NS.min" id="417544583">
<int key="NS.exponent">0</int>
@@ -457,7 +454,7 @@
<object class="NSButton" id="996173927">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 71}, {214, 18}}</string>
<string key="NSFrame">{{15, 70}, {330, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="839484037">
@@ -478,7 +475,7 @@
<object class="NSButton" id="147113892">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 9}, {283, 18}}</string>
<string key="NSFrame">{{15, 10}, {330, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="58676792">
@@ -499,7 +496,7 @@
<object class="NSButton" id="367077416">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 31}, {262, 18}}</string>
<string key="NSFrame">{{15, 30}, {330, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="469745366">
@@ -520,7 +517,7 @@
<object class="NSTextField" id="742879627">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 133}, {100, 17}}</string>
<string key="NSFrame">{{14, 150}, {100, 17}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="714876031">
@@ -536,7 +533,7 @@
<object class="NSButton" id="24386232">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{24, 113}, {55, 18}}</string>
<string key="NSFrame">{{24, 130}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="771292699">
@@ -557,7 +554,7 @@
<object class="NSButton" id="28878355">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{77, 113}, {55, 18}}</string>
<string key="NSFrame">{{94, 130}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="324625140">
@@ -578,7 +575,7 @@
<object class="NSButton" id="964877114">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{129, 113}, {60, 18}}</string>
<string key="NSFrame">{{164, 130}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="564429548">
@@ -599,7 +596,7 @@
<object class="NSButton" id="144566514">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{187, 113}, {51, 18}}</string>
<string key="NSFrame">{{24, 110}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="243345318">
@@ -620,7 +617,7 @@
<object class="NSButton" id="180911463">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{235, 113}, {54, 18}}</string>
<string key="NSFrame">{{94, 110}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="222054797">
@@ -641,7 +638,7 @@
<object class="NSButton" id="422320464">
<reference key="NSNextResponder" ref="92401176"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{292, 113}, {54, 18}}</string>
<string key="NSFrame">{{164, 110}, {66, 18}}</string>
<reference key="NSSuperview" ref="92401176"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="464356494">
@@ -660,7 +657,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {360, 234}}</string>
<string key="NSFrame">{{10, 33}, {360, 251}}</string>
<reference key="NSSuperview" ref="1019752720"/>
</object>
<string key="NSLabel">Basic</string>
@@ -677,7 +674,7 @@
<object class="NSButton" id="836095588">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 215}, {262, 18}}</string>
<string key="NSFrame">{{15, 232}, {262, 18}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="287230715">
@@ -698,7 +695,7 @@
<object class="NSTextField" id="519483808">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 172}, {85, 13}}</string>
<string key="NSFrame">{{14, 126}, {332, 13}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="142188233">
@@ -714,7 +711,7 @@
<object class="NSTextField" id="839713145">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 144}, {324, 17}}</string>
<string key="NSFrame">{{14, 169}, {332, 17}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="380716547">
@@ -730,7 +727,7 @@
<object class="NSPopUpButton" id="1046542754">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{104, 165}, {234, 26}}</string>
<string key="NSFrame">{{14, 94}, {256, 26}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="923770094">
@@ -800,7 +797,7 @@
<object class="NSTextField" id="330569030">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 122}, {326, 22}}</string>
<string key="NSFrame">{{17, 147}, {326, 22}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="573680954">
@@ -830,7 +827,7 @@
<object class="NSButton" id="1065764374">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 195}, {265, 18}}</string>
<string key="NSFrame">{{15, 212}, {265, 18}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="621426332">
@@ -848,8 +845,29 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSButton" id="476462426">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 192}, {265, 18}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="29064087">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Debug mode (restart required)</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="476462426"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="150447483"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<string key="NSFrame">{{10, 33}, {360, 234}}</string>
</object>
</object>
<string key="NSFrame">{{10, 33}, {360, 251}}</string>
</object>
<string key="NSLabel">Advanced</string>
<reference key="NSColor" ref="221998487"/>
@@ -867,7 +885,7 @@
</object>
</object>
</object>
<string key="NSFrameSize">{406, 326}</string>
<string key="NSFrameSize">{406, 343}</string>
<reference key="NSSuperview"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
@@ -1498,6 +1516,22 @@
</object>
<int key="connectionID">128</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.DebugMode</string>
<reference key="source" ref="476462426"/>
<reference key="destination" ref="579641073"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="476462426"/>
<reference key="NSDestination" ref="579641073"/>
<string key="NSLabel">value: values.DebugMode</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.DebugMode</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">132</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -1547,8 +1581,8 @@
<reference key="object" ref="986069316"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="552254322"/>
<reference ref="1019752720"/>
<reference ref="552254322"/>
</object>
<reference key="parent" ref="793317856"/>
</object>
@@ -1601,6 +1635,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="836095588"/>
<reference ref="1065764374"/>
<reference ref="476462426"/>
<reference ref="519483808"/>
<reference ref="839713145"/>
<reference ref="1046542754"/>
@@ -1613,25 +1648,25 @@
<reference key="object" ref="92401176"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="422320464"/>
<reference ref="180911463"/>
<reference ref="144566514"/>
<reference ref="964877114"/>
<reference ref="28878355"/>
<reference ref="24386232"/>
<reference ref="742879627"/>
<reference ref="996173927"/>
<reference ref="746186689"/>
<reference ref="527948380"/>
<reference ref="102571342"/>
<reference ref="353791762"/>
<reference ref="531187173"/>
<reference ref="152034108"/>
<reference ref="735544762"/>
<reference ref="595766735"/>
<reference ref="810949831"/>
<reference ref="147113892"/>
<reference ref="144566514"/>
<reference ref="28878355"/>
<reference ref="180911463"/>
<reference ref="964877114"/>
<reference ref="422320464"/>
<reference ref="102571342"/>
<reference ref="527948380"/>
<reference ref="996173927"/>
<reference ref="367077416"/>
<reference ref="147113892"/>
</object>
<reference key="parent" ref="443899983"/>
</object>
@@ -2072,6 +2107,20 @@
<reference key="object" ref="621426332"/>
<reference key="parent" ref="1065764374"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">129</int>
<reference key="object" ref="476462426"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="29064087"/>
</object>
<reference key="parent" ref="76055040"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">130</int>
<reference key="object" ref="29064087"/>
<reference key="parent" ref="476462426"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -2084,6 +2133,7 @@
<string>10.IBPluginDependency</string>
<string>10.ImportedFromIB2</string>
<string>11.IBPluginDependency</string>
<string>11.IBViewBoundsToFrameTransform</string>
<string>11.ImportedFromIB2</string>
<string>115.IBPluginDependency</string>
<string>116.IBPluginDependency</string>
@@ -2093,22 +2143,34 @@
<string>12.IBPluginDependency</string>
<string>12.ImportedFromIB2</string>
<string>120.IBPluginDependency</string>
<string>120.IBViewBoundsToFrameTransform</string>
<string>120.ImportedFromIB2</string>
<string>121.IBPluginDependency</string>
<string>122.IBPluginDependency</string>
<string>122.IBViewBoundsToFrameTransform</string>
<string>123.IBPluginDependency</string>
<string>125.IBPluginDependency</string>
<string>125.IBViewBoundsToFrameTransform</string>
<string>125.ImportedFromIB2</string>
<string>126.IBPluginDependency</string>
<string>129.IBPluginDependency</string>
<string>129.IBViewBoundsToFrameTransform</string>
<string>129.ImportedFromIB2</string>
<string>13.IBPluginDependency</string>
<string>13.IBViewBoundsToFrameTransform</string>
<string>13.ImportedFromIB2</string>
<string>130.IBPluginDependency</string>
<string>14.IBPluginDependency</string>
<string>14.IBViewBoundsToFrameTransform</string>
<string>14.ImportedFromIB2</string>
<string>15.IBPluginDependency</string>
<string>15.IBViewBoundsToFrameTransform</string>
<string>15.ImportedFromIB2</string>
<string>17.IBPluginDependency</string>
<string>17.IBViewBoundsToFrameTransform</string>
<string>17.ImportedFromIB2</string>
<string>18.IBPluginDependency</string>
<string>18.IBViewBoundsToFrameTransform</string>
<string>18.ImportedFromIB2</string>
<string>19.IBPluginDependency</string>
<string>19.ImportedFromIB2</string>
@@ -2119,8 +2181,10 @@
<string>2.windowTemplate.hasMinSize</string>
<string>2.windowTemplate.minSize</string>
<string>20.IBPluginDependency</string>
<string>20.IBViewBoundsToFrameTransform</string>
<string>20.ImportedFromIB2</string>
<string>21.IBPluginDependency</string>
<string>21.IBViewBoundsToFrameTransform</string>
<string>21.ImportedFromIB2</string>
<string>22.IBPluginDependency</string>
<string>22.ImportedFromIB2</string>
@@ -2155,6 +2219,7 @@
<string>39.IBPluginDependency</string>
<string>39.ImportedFromIB2</string>
<string>4.IBPluginDependency</string>
<string>4.IBViewBoundsToFrameTransform</string>
<string>4.ImportedFromIB2</string>
<string>40.IBPluginDependency</string>
<string>40.ImportedFromIB2</string>
@@ -2166,6 +2231,7 @@
<string>45.IBPluginDependency</string>
<string>46.IBPluginDependency</string>
<string>5.IBPluginDependency</string>
<string>5.IBViewBoundsToFrameTransform</string>
<string>5.ImportedFromIB2</string>
<string>54.IBPluginDependency</string>
<string>55.IBPluginDependency</string>
@@ -2178,6 +2244,7 @@
<string>59.IBPluginDependency</string>
<string>59.ImportedFromIB2</string>
<string>6.IBPluginDependency</string>
<string>6.IBViewBoundsToFrameTransform</string>
<string>6.ImportedFromIB2</string>
<string>60.IBPluginDependency</string>
<string>61.IBPluginDependency</string>
@@ -2190,8 +2257,10 @@
<string>68.IBPluginDependency</string>
<string>69.IBPluginDependency</string>
<string>7.IBPluginDependency</string>
<string>7.IBViewBoundsToFrameTransform</string>
<string>7.ImportedFromIB2</string>
<string>8.IBPluginDependency</string>
<string>8.IBViewBoundsToFrameTransform</string>
<string>8.ImportedFromIB2</string>
<string>9.IBPluginDependency</string>
<string>9.ImportedFromIB2</string>
@@ -2204,6 +2273,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwlQAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2213,34 +2285,70 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwzQAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBiAAAwyMAAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAw2QAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBoAAAw18AAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwggAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwuQAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwwUAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwroAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDdAAAwigAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{555, 254}, {406, 343}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{555, 271}, {406, 326}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{555, 271}, {406, 326}}</string>
<string>{{555, 254}, {406, 343}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{213, 107}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwpIAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwuIAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -2275,6 +2383,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDJAAAwwgAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -2286,6 +2397,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABCtAAAwwgAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2298,6 +2412,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDOwAAwxwAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2310,8 +2427,14 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDJAAAwxwAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABCtAAAwxwAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -2333,7 +2456,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">128</int>
<int key="maxID">132</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -2345,6 +2468,13 @@
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSTableView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">

View File

@@ -0,0 +1,102 @@
/* Class = "NSWindow"; title = "dupeGuru ME Preferences"; ObjectID = "2"; */
"2.title" = "Préférences de dupeGuru ME";
/* Class = "NSTextFieldCell"; title = "More results"; ObjectID = "29"; */
"29.title" = "+ de doubles";
/* Class = "NSTextFieldCell"; title = "Fewer results"; ObjectID = "30"; */
"30.title" = "- de doubles";
/* Class = "NSTextFieldCell"; title = "Filter hardness:"; ObjectID = "31"; */
"31.title" = "Seuil du filtre:";
/* Class = "NSTextFieldCell"; title = "Scan type:"; ObjectID = "32"; */
"32.title" = "Type de scan:";
/* Class = "NSMenuItem"; title = "Content"; ObjectID = "35"; */
"35.title" = "Contenu";
/* Class = "NSMenuItem"; title = "Filename"; ObjectID = "36"; */
"36.title" = "Nom de fichier";
/* Class = "NSMenuItem"; title = "Filename - Fields"; ObjectID = "37"; */
"37.title" = "Nom de fichier (Champs)";
/* Class = "NSMenuItem"; title = "Tags"; ObjectID = "38"; */
"38.title" = "Tags";
/* Class = "NSMenuItem"; title = "Audio Content"; ObjectID = "39"; */
"39.title" = "Contenu Audio";
/* Class = "NSMenuItem"; title = "Filename - Fields (No Order)"; ObjectID = "40"; */
"40.title" = "Nom de fichier (Champs sans ordre)";
/* Class = "NSButtonCell"; title = "Word weighting"; ObjectID = "41"; */
"41.title" = "Proportionalité des mots";
/* Class = "NSButtonCell"; title = "Can mix file kind"; ObjectID = "42"; */
"42.title" = "Comparer les fichiers de différents types";
/* Class = "NSButtonCell"; title = "Reset to Defaults"; ObjectID = "45"; */
"45.title" = "Options par défaut";
/* Class = "NSButtonCell"; title = "Match similar words"; ObjectID = "46"; */
"46.title" = "Comparer les mots similaires";
/* Class = "NSTextFieldCell"; title = "Copy and Move:"; ObjectID = "54"; */
"54.title" = "Déplacements de fichiers:";
/* Class = "NSMenuItem"; title = "Recreate relative path"; ObjectID = "57"; */
"57.title" = "Re-créer chemins relatifs";
/* Class = "NSMenuItem"; title = "Recreate absolute path"; ObjectID = "58"; */
"58.title" = "Re-créer chemins absolus";
/* Class = "NSMenuItem"; title = "Right in destination"; ObjectID = "59"; */
"59.title" = "Directement à la destination";
/* Class = "NSButtonCell"; title = "Automatically check for updates"; ObjectID = "60"; */
"60.title" = "Vérifier automatiquement les mises à jour";
/* Class = "NSButtonCell"; title = "Use regular expressions when filtering"; ObjectID = "61"; */
"61.title" = "Utiliser les expressions régulières pour les filtres";
/* Class = "NSButtonCell"; title = "Remove empty folders after delete and move"; ObjectID = "62"; */
"62.title" = "Effacer les dossiers vides après un déplacement";
/* Class = "NSTextFieldCell"; title = "Tags to scan:"; ObjectID = "63"; */
"63.title" = "Tags à scanner:";
/* Class = "NSButtonCell"; title = "Track"; ObjectID = "64"; */
"64.title" = "Track";
/* Class = "NSButtonCell"; title = "Artist"; ObjectID = "65"; */
"65.title" = "Artiste";
/* Class = "NSButtonCell"; title = "Album"; ObjectID = "66"; */
"66.title" = "Album";
/* Class = "NSButtonCell"; title = "Title"; ObjectID = "67"; */
"67.title" = "Titre";
/* Class = "NSButtonCell"; title = "Genre"; ObjectID = "68"; */
"68.title" = "Genre";
/* Class = "NSButtonCell"; title = "Year"; ObjectID = "69"; */
"69.title" = "Année";
/* Class = "NSTabViewItem"; label = "Basic"; ObjectID = "116"; */
"116.label" = "Simple";
/* Class = "NSTabViewItem"; label = "Advanced"; ObjectID = "117"; */
"117.label" = "Avancé";
/* Class = "NSTextFieldCell"; title = "Custom Command (arguments: %d for dupe, %r for ref):"; ObjectID = "121"; */
"121.title" = "Commande perso. (arguments: %d pour doublon, %r pour réf):";
/* Class = "NSButtonCell"; title = "Ignore duplicates hardlinking to the same file"; ObjectID = "126"; */
"126.title" = "Ignorer doublons avec hardlink vers le même fichier";
/* Class = "NSButtonCell"; title = "Debug mode (restart required)"; ObjectID = "130"; */
"130.title" = "Mode de déboguage (redémarrage requis)";

File diff suppressed because it is too large Load Diff

View File

@@ -11,8 +11,5 @@ http://www.hardcoded.net/licenses/bsd_license
#import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase {}
- (IBAction)openWebsite:(id)sender;
- (IBAction)toggleDirectories:(id)sender;
- (PyDupeGuru *)py;
@end

View File

@@ -13,6 +13,7 @@ http://www.hardcoded.net/licenses/bsd_license
#import "Consts.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h"
#import "ResultWindow.h"
@implementation AppDelegate
+ (void)initialize
@@ -34,45 +35,35 @@ http://www.hardcoded.net/licenses/bsd_license
[ud registerDefaults:d];
}
- (id)init
- (NSString *)homepageURL
{
self = [super init];
_directoryPanel = nil;
return self;
return @"http://www.hardcoded.net/dupeguru_pe/";
}
- (DetailsPanel *)detailsPanel
- (ResultWindowBase *)createResultWindow
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanelPE alloc] initWithPy:py];
return _detailsPanel;
return [[ResultWindow alloc] initWithParentApp:self];
}
- (IBAction)openWebsite:(id)sender
- (DirectoryPanel *)createDirectoryPanel
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_pe"]];
return [[DirectoryPanelPE alloc] initWithParentApp:self];
}
- (IBAction)toggleDirectories:(id)sender
- (DetailsPanel *)createDetailsPanel
{
[[self directoryPanel] toggleVisible:sender];
return [[DetailsPanelPE alloc] initWithPy:py];
}
- (DirectoryPanel *)directoryPanel
{
if (!_directoryPanel)
_directoryPanel = [[DirectoryPanelPE alloc] initWithParentApp:self];
return _directoryPanel;
}
- (PyDupeGuru *)py { return (PyDupeGuru *)py; }
//Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSMenu *actionsMenu = [[[NSApp mainMenu] itemWithTitle:@"Actions"] submenu];
// index 2 is just after "Clear Ingore List"
NSMenuItem *mi = [actionsMenu insertItemWithTitle:@"Clear Picture Cache" action:@selector(clearPictureCache:) keyEquivalent:@"P" atIndex:2];
[mi setTarget:result];
NSMenuItem *mi = [actionsMenu insertItemWithTitle:TR(@"Clear Picture Cache")
action:@selector(clearPictureCache:) keyEquivalent:@"P" atIndex:2];
[mi setTarget:[self resultWindow]];
[mi setKeyEquivalentModifierMask:NSCommandKeyMask|NSShiftKeyMask];
[super applicationDidFinishLaunching:aNotification];
}

View File

@@ -7,45 +7,28 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import "DirectoryPanel.h"
#import "ProgressController.h"
static NSString* jobAddIPhoto = @"jobAddIPhoto";
#import "Consts.h"
@implementation DirectoryPanelPE
- (id)initWithParentApp:(id)aParentApp
{
self = [super initWithParentApp:aParentApp];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil];
[[self window] setTitle:@"dupeGuru Picture Edition"];
_alwaysShowPopUp = YES;
return self;
}
- (void)fillPopUpMenu
{
[super fillPopUpMenu];
NSMenu *m = [addButtonPopUp menu];
NSMenuItem *mi = [m insertItemWithTitle:TR(@"Add iPhoto Library") action:@selector(addiPhoto:)
keyEquivalent:@"" atIndex:1];
[mi setTarget:self];
}
- (IBAction)addiPhoto:(id)sender
{
[[ProgressController mainProgressController] setJobDesc:@"Adding iPhoto Library..."];
[[ProgressController mainProgressController] setJobId:jobAddIPhoto];
[[ProgressController mainProgressController] showSheetForParent:[self window]];
[self addDirectory:@"iPhoto Library"];
}
- (IBAction)popupAddDirectoryMenu:(id)sender
{
NSMenu *m = [addButtonPopUp menu];
while ([m numberOfItems] > 0)
[m removeItemAtIndex:0];
NSMenuItem *mi = [m addItemWithTitle:@"Add New Directory..." action:@selector(askForDirectory:) keyEquivalent:@""];
[mi setTarget:self];
mi = [m addItemWithTitle:@"Add iPhoto Directory" action:@selector(addiPhoto:) keyEquivalent:@""];
[mi setTarget:self];
[m addItem:[NSMenuItem separatorItem]];
[_recentDirectories fillMenu:m];
[addButtonPopUp selectItem:nil];
[[addButtonPopUp cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
- (void)jobCompleted:(NSNotification *)aNotification
{
if ([[ProgressController mainProgressController] jobId] == jobAddIPhoto) {
[outlineView reloadData];
}
}
@end

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key>
<string>hsft</string>
<key>CFBundleVersion</key>
<string>1.11.2</string>
<string>{version}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>

View File

@@ -11,6 +11,4 @@ http://www.hardcoded.net/licenses/bsd_license
@interface ResultWindow : ResultWindowBase {}
- (IBAction)clearPictureCache:(id)sender;
- (IBAction)startDuplicateScan:(id)sender;
- (IBAction)toggleDirectories:(id)sender;
@end

View File

@@ -8,26 +8,51 @@ http://www.hardcoded.net/licenses/bsd_license
#import "ResultWindow.h"
#import "Dialogs.h"
#import "ProgressController.h"
#import "Utils.h"
#import "AppDelegate.h"
#import "Consts.h"
#import "PyDupeGuru.h"
@implementation ResultWindow
/* Override */
- (void)awakeFromNib
- (void)initResultColumns
{
[super awakeFromNib];
[[self window] setTitle:@"dupeGuru Picture Edition"];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
[deltaColumns addIndex:5];
[table setDeltaColumns:deltaColumns];
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:TR(@"Folder") width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TR(@"Size (KB)") width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:TR(@"Kind") width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:TR(@"Dimensions") width:80 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:TR(@"Modification") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:TR(@"Match %") width:58 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:TR(@"Dupe Count") width:80 refCol:refCol]];
}
- (void)setScanOptions
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchScaled:[ud objectForKey:@"matchScaled"]];
}
- (NSString *)getScanErrorMessageForCode:(NSInteger)errorCode
{
if (errorCode == 4) {
return TR(@"IPhotoAppNotFoundMsg");
}
return [super getScanErrorMessageForCode:errorCode];
}
/* Actions */
- (IBAction)clearPictureCache:(id)sender
{
if ([Dialogs askYesNo:@"Do you really want to remove all your cached picture analysis?"] == NSAlertSecondButtonReturn) // NO
NSString *msg = TR(@"ClearPictureCacheConfirmMsg");
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[(PyDupeGuru *)py clearPictureCache];
}
@@ -48,49 +73,4 @@ http://www.hardcoded.net/licenses/bsd_license
[columnsWidth setObject:i2n(58) forKey:@"6"];
[self restoreColumnsPosition:columnsOrder widths:columnsWidth];
}
- (IBAction)startDuplicateScan:(id)sender
{
if ([matches numberOfRows] > 0)
{
if ([Dialogs askYesNo:@"Are you sure you want to start a new duplicate scan?"] == NSAlertSecondButtonReturn) // NO
return;
}
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchScaled:[ud objectForKey:@"matchScaled"]];
int r = n2i([py doScan]);
if (r != 0)
[[ProgressController mainProgressController] hide];
if (r == 3)
{
[Dialogs showMessage:@"The selected directories contain no scannable file."];
[app toggleDirectories:nil];
}
}
- (IBAction)toggleDirectories:(id)sender
{
[(AppDelegate *)app toggleDirectories:sender];
}
/* Public */
- (void)initResultColumns
{
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (KB)" width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Dimensions" width:80 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Modification" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Match %" width:58 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Dupe Count" width:80 refCol:refCol]];
}
@end

View File

@@ -4,17 +4,11 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_pe import app_cocoa as app_pe_cocoa
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
# Fix py2app imports which chokes on relative imports and other stuff
import hsutil.conflict
import core.engine, core.fs, core.app
import core_pe.block, core_pe.cache, core_pe.matchbase, core_pe.data, core_pe._block_osx
import xml.etree.ElementPath
import gzip
import aem.kae
import appscript.defaultterminology
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_pe import app_cocoa as app_pe_cocoa, __appname__
class PyDupeGuru(PyDupeGuruBase):
def init(self):
@@ -41,5 +35,5 @@ class PyDupeGuru(PyDupeGuruBase):
#---Registration
def appName(self):
return "dupeGuru Picture Edition"
return __appname__

View File

@@ -9,12 +9,16 @@
/* Begin PBXBuildFile section */
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
CE031751109B340A00517EE6 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031750109B340A00517EE6 /* Preferences.xib */; };
CE031754109B345200517EE6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031753109B345200517EE6 /* MainMenu.xib */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */; };
CE05339B12E5DA350029EF25 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05339312E5DA350029EF25 /* DirectoryPanel.xib */; };
CE05339C12E5DA350029EF25 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05339512E5DA350029EF25 /* MainMenu.xib */; };
CE05339D12E5DA350029EF25 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05339712E5DA350029EF25 /* ProblemDialog.xib */; };
CE05339E12E5DA350029EF25 /* ResultWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE05339912E5DA350029EF25 /* ResultWindow.xib */; };
CE0533A712E5DA4D0029EF25 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0533A312E5DA4D0029EF25 /* DetailsPanel.xib */; };
CE0533A812E5DA4D0029EF25 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0533A512E5DA4D0029EF25 /* Preferences.xib */; };
CE0533AB12E5DA6A0029EF25 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE0533A912E5DA6A0029EF25 /* Localizable.strings */; };
CE073F6309CAE1A3005C1D2F /* help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* help */; };
CE0C2AB61177011000BC749F /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C2AB51177011000BC749F /* HSTable.m */; };
CE0C2ABD1177014200BC749F /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C2ABB1177014200BC749F /* ProblemDialog.m */; };
CE0C2AC81177021600BC749F /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0C2AC71177021600BC749F /* ProblemDialog.xib */; };
CE15C8A80ADEB8B50061D4A5 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; };
CE15C8C00ADEB8D40061D4A5 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; };
CE1EB5FE12537F9D0034AABB /* HSFairwareReminder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE1EB5FC12537F9D0034AABB /* HSFairwareReminder.m */; };
@@ -22,17 +26,16 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE4527AC12E5F6E700005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE4527AA12E5F6E700005A15 /* core.strings */; };
CE60180812DF3EA900236FDC /* HSRecentFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = CE60180712DF3EA900236FDC /* HSRecentFiles.m */; };
CE6044EC0FE6796200B71262 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6044EB0FE6796200B71262 /* DetailsPanel.m */; };
CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; };
CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */; };
CE77C89E10946C6D0078B0DB /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */; };
CE77C8A810946CE20078B0DB /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE77C8A710946CE20078B0DB /* DetailsPanel.xib */; };
CE7AC9181119911200D02F6C /* ErrorReportWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE7AC9151119911200D02F6C /* ErrorReportWindow.xib */; };
CE7AC9191119911200D02F6C /* progress.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE7AC9161119911200D02F6C /* progress.xib */; };
CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1C0FC192D60086DCA6 /* Dialogs.m */; };
CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */; };
CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB220FC192D60086DCA6 /* ProgressController.m */; };
CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB250FC192D60086DCA6 /* RecentDirectories.m */; };
CE80DB350FC192D60086DCA6 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB2B0FC192D60086DCA6 /* Utils.m */; };
CE80DB360FC192D60086DCA6 /* ValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB2D0FC192D60086DCA6 /* ValueTransformers.m */; };
CE80DB470FC193650086DCA6 /* NSNotificationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB460FC193650086DCA6 /* NSNotificationAdditions.m */; };
@@ -51,15 +54,14 @@
CE9EA75C1122C96C008CD2BC /* NSTableViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7551122C96C008CD2BC /* NSTableViewAdditions.m */; };
CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7701122CA0B008CD2BC /* DirectoryOutline.m */; };
CEBAE4270FDA97E000B7887D /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */; };
CEC9DB4712CCAA6B003102F0 /* about.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEC9DB4612CCAA6B003102F0 /* about.xib */; };
CEC9DB4C12CCAA7D003102F0 /* HSAboutBox.m in Sources */ = {isa = PBXBuildFile; fileRef = CEC9DB4B12CCAA7D003102F0 /* HSAboutBox.m */; };
CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; };
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEF12A7E124DFD400087B51D /* HSTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF12A7D124DFD400087B51D /* HSTableView.m */; };
CEF12A84124DFD620087B51D /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF12A83124DFD620087B51D /* ResultTable.m */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
CEFCDE2D0AB0418600C33A93 /* dgpe_logo_32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFCDE2C0AB0418600C33A93 /* dgpe_logo_32.png */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -80,21 +82,33 @@
/* Begin PBXFileReference section */
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
8D1107320486CEB800E47090 /* dupeGuru PE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "dupeGuru PE.app"; sourceTree = BUILT_PRODUCTS_DIR; };
CE031750109B340A00517EE6 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
CE031753109B345200517EE6 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_pe_help; path = ../../help_pe/dupeguru_pe_help; sourceTree = SOURCE_ROOT; };
CE05339412E5DA350029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE05339612E5DA350029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE05339812E5DA350029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE05339A12E5DA350029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE05339F12E5DA420029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE0533A012E5DA420029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE0533A112E5DA420029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE0533A212E5DA420029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE0533A412E5DA4D0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailsPanel.xib; sourceTree = "<group>"; };
CE0533A612E5DA4D0029EF25 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Preferences.xib; sourceTree = "<group>"; };
CE0533AA12E5DA6A0029EF25 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE0533AC12E5DA790029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE0533AD12E5DAAD0029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/DetailsPanel.xib; sourceTree = "<group>"; };
CE0533AE12E5DAAD0029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/Preferences.xib; sourceTree = "<group>"; };
CE0533B712E5DC040029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../../cocoalib/fr.lproj/FairwareReminder.xib; sourceTree = SOURCE_ROOT; };
CE073F5409CAE1A3005C1D2F /* help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = help; path = ../../build/help; sourceTree = SOURCE_ROOT; };
CE0C2AAA117700E700BC749F /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE0C2AB41177011000BC749F /* HSTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSTable.h; sourceTree = "<group>"; };
CE0C2AB51177011000BC749F /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE0C2ABA1177014200BC749F /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0C2ABB1177014200BC749F /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE0C2ABC1177014200BC749F /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0C2AC71177021600BC749F /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE1EB5FB12537F9D0034AABB /* HSFairwareReminder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSFairwareReminder.h; path = ../../cocoalib/HSFairwareReminder.h; sourceTree = SOURCE_ROOT; };
@@ -106,13 +120,15 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE4527AB12E5F6E700005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE4527B012E5F72600005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE60180612DF3EA900236FDC /* HSRecentFiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSRecentFiles.h; path = ../../cocoalib/HSRecentFiles.h; sourceTree = SOURCE_ROOT; };
CE60180712DF3EA900236FDC /* HSRecentFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSRecentFiles.m; path = ../../cocoalib/HSRecentFiles.m; sourceTree = SOURCE_ROOT; };
CE6044EA0FE6796200B71262 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = ../base/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE6044EB0FE6796200B71262 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = ../base/DetailsPanel.m; sourceTree = SOURCE_ROOT; };
CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; };
CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; };
CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = ../base/dsa_pub.pem; sourceTree = "<group>"; };
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DirectoryPanel.xib; path = ../../base/xib/DirectoryPanel.xib; sourceTree = "<group>"; };
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DetailsPanel.xib; sourceTree = "<group>"; };
CE7AC9151119911200D02F6C /* ErrorReportWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ErrorReportWindow.xib; sourceTree = "<group>"; };
CE7AC9161119911200D02F6C /* progress.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = progress.xib; sourceTree = "<group>"; };
CE80DB1B0FC192D60086DCA6 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = ../../cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
@@ -122,8 +138,6 @@
CE80DB210FC192D60086DCA6 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CE80DB220FC192D60086DCA6 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CE80DB230FC192D60086DCA6 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
CE80DB240FC192D60086DCA6 /* RecentDirectories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecentDirectories.h; path = ../../cocoalib/RecentDirectories.h; sourceTree = SOURCE_ROOT; };
CE80DB250FC192D60086DCA6 /* RecentDirectories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RecentDirectories.m; path = ../../cocoalib/RecentDirectories.m; sourceTree = SOURCE_ROOT; };
CE80DB2A0FC192D60086DCA6 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = ../../cocoalib/Utils.h; sourceTree = SOURCE_ROOT; };
CE80DB2B0FC192D60086DCA6 /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = ../../cocoalib/Utils.m; sourceTree = SOURCE_ROOT; };
CE80DB2C0FC192D60086DCA6 /* ValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueTransformers.h; path = ../../cocoalib/ValueTransformers.h; sourceTree = SOURCE_ROOT; };
@@ -165,6 +179,9 @@
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDirectoryOutline.h; path = ../base/PyDirectoryOutline.h; sourceTree = SOURCE_ROOT; };
CEBAE4230FDA97E000B7887D /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; };
CEC9DB4612CCAA6B003102F0 /* about.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = about.xib; path = ../../cocoalib/xib/about.xib; sourceTree = SOURCE_ROOT; };
CEC9DB4A12CCAA7D003102F0 /* HSAboutBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSAboutBox.h; path = ../../cocoalib/HSAboutBox.h; sourceTree = SOURCE_ROOT; };
CEC9DB4B12CCAA7D003102F0 /* HSAboutBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSAboutBox.m; path = ../../cocoalib/HSAboutBox.m; sourceTree = SOURCE_ROOT; };
CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; sourceTree = "<group>"; };
CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = "<group>"; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
@@ -174,9 +191,6 @@
CEF12A82124DFD620087B51D /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CEF12A83124DFD620087B51D /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; sourceTree = SOURCE_ROOT; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = ../../images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = ../../images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = ../../images/preferences32.png; sourceTree = SOURCE_ROOT; };
CEFCDE2C0AB0418600C33A93 /* dgpe_logo_32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dgpe_logo_32.png; path = ../../images/dgpe_logo_32.png; sourceTree = SOURCE_ROOT; };
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = PyDupeGuru.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -196,6 +210,7 @@
080E96DDFE201D6D7F000001 /* DGPE */ = {
isa = PBXGroup;
children = (
29B97316FDCFA39411CA2CEA /* main.m */,
CE381C9509914ACE003581CE /* AppDelegate.h */,
CE381C9409914ACE003581CE /* AppDelegate.m */,
CE848A1809DD85810004CB44 /* Consts.h */,
@@ -243,7 +258,6 @@
080E96DDFE201D6D7F000001 /* DGPE */,
CE80DB1A0FC192AB0086DCA6 /* cocoalib */,
CE80DB810FC194BD0086DCA6 /* dgbase */,
29B97315FDCFA39411CA2CEA /* Other Sources */,
29B97317FDCFA39411CA2CEA /* Resources */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
@@ -251,23 +265,17 @@
name = dupeguru;
sourceTree = "<group>";
};
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
29B97316FDCFA39411CA2CEA /* main.m */,
);
name = "Other Sources";
sourceTree = "<group>";
};
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
CE77C89A10946C6D0078B0DB /* xib */,
CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */,
CE073F5409CAE1A3005C1D2F /* help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */,
CE05339212E5DA1D0029EF25 /* xib */,
CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */,
CE0533A912E5DA6A0029EF25 /* Localizable.strings */,
CE4527AA12E5F6E700005A15 /* core.strings */,
CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */,
);
name = Resources;
@@ -282,21 +290,23 @@
name = Frameworks;
sourceTree = "<group>";
};
CE77C89A10946C6D0078B0DB /* xib */ = {
CE05339212E5DA1D0029EF25 /* xib */ = {
isa = PBXGroup;
children = (
CE031753109B345200517EE6 /* MainMenu.xib */,
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */,
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */,
CE031750109B340A00517EE6 /* Preferences.xib */,
CE0C2AC71177021600BC749F /* ProblemDialog.xib */,
CE05339312E5DA350029EF25 /* DirectoryPanel.xib */,
CE05339512E5DA350029EF25 /* MainMenu.xib */,
CE05339712E5DA350029EF25 /* ProblemDialog.xib */,
CE05339912E5DA350029EF25 /* ResultWindow.xib */,
CE0533A312E5DA4D0029EF25 /* DetailsPanel.xib */,
CE0533A512E5DA4D0029EF25 /* Preferences.xib */,
);
path = xib;
name = xib;
sourceTree = "<group>";
};
CE7AC9141119911200D02F6C /* xib */ = {
isa = PBXGroup;
children = (
CEC9DB4612CCAA6B003102F0 /* about.xib */,
CE1EB5FF12537FB90034AABB /* FairwareReminder.xib */,
CE7AC9151119911200D02F6C /* ErrorReportWindow.xib */,
CE7AC9161119911200D02F6C /* progress.xib */,
@@ -326,11 +336,13 @@
CE1EB5FB12537F9D0034AABB /* HSFairwareReminder.h */,
CE1EB5FC12537F9D0034AABB /* HSFairwareReminder.m */,
CE1EB5FD12537F9D0034AABB /* PyFairware.h */,
CEC9DB4A12CCAA7D003102F0 /* HSAboutBox.h */,
CEC9DB4B12CCAA7D003102F0 /* HSAboutBox.m */,
CE60180612DF3EA900236FDC /* HSRecentFiles.h */,
CE60180712DF3EA900236FDC /* HSRecentFiles.m */,
CE80DB210FC192D60086DCA6 /* ProgressController.h */,
CE80DB220FC192D60086DCA6 /* ProgressController.m */,
CE80DB230FC192D60086DCA6 /* PyApp.h */,
CE80DB240FC192D60086DCA6 /* RecentDirectories.h */,
CE80DB250FC192D60086DCA6 /* RecentDirectories.m */,
CE80DB2A0FC192D60086DCA6 /* Utils.h */,
CE80DB2B0FC192D60086DCA6 /* Utils.m */,
CE80DB2C0FC192D60086DCA6 /* ValueTransformers.h */,
@@ -425,9 +437,6 @@
CEFC294309C89E0000D9F998 /* images */ = {
isa = PBXGroup;
children = (
CEFCDE2C0AB0418600C33A93 /* dgpe_logo_32.png */,
CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */,
);
name = images;
@@ -462,6 +471,7 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */;
compatibilityVersion = "Xcode 3.0";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
@@ -469,6 +479,7 @@
French,
German,
en,
fr,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */;
projectDirPath = "";
@@ -485,21 +496,22 @@
buildActionMask = 2147483647;
files = (
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */,
CE073F6309CAE1A3005C1D2F /* help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CEFCDE2D0AB0418600C33A93 /* dgpe_logo_32.png in Resources */,
CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */,
CE77C89E10946C6D0078B0DB /* DirectoryPanel.xib in Resources */,
CE77C8A810946CE20078B0DB /* DetailsPanel.xib in Resources */,
CE031751109B340A00517EE6 /* Preferences.xib in Resources */,
CE031754109B345200517EE6 /* MainMenu.xib in Resources */,
CE7AC9181119911200D02F6C /* ErrorReportWindow.xib in Resources */,
CE7AC9191119911200D02F6C /* progress.xib in Resources */,
CE0C2AC81177021600BC749F /* ProblemDialog.xib in Resources */,
CE1EB60112537FB90034AABB /* FairwareReminder.xib in Resources */,
CEC9DB4712CCAA6B003102F0 /* about.xib in Resources */,
CE05339B12E5DA350029EF25 /* DirectoryPanel.xib in Resources */,
CE05339C12E5DA350029EF25 /* MainMenu.xib in Resources */,
CE05339D12E5DA350029EF25 /* ProblemDialog.xib in Resources */,
CE05339E12E5DA350029EF25 /* ResultWindow.xib in Resources */,
CE0533A712E5DA4D0029EF25 /* DetailsPanel.xib in Resources */,
CE0533A812E5DA4D0029EF25 /* Preferences.xib in Resources */,
CE0533AB12E5DA6A0029EF25 /* Localizable.strings in Resources */,
CE4527AC12E5F6E700005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -518,7 +530,6 @@
CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */,
CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */,
CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */,
CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */,
CE80DB350FC192D60086DCA6 /* Utils.m in Sources */,
CE80DB360FC192D60086DCA6 /* ValueTransformers.m in Sources */,
CE80DB470FC193650086DCA6 /* NSNotificationAdditions.m in Sources */,
@@ -542,21 +553,96 @@
CEF12A7E124DFD400087B51D /* HSTableView.m in Sources */,
CEF12A84124DFD620087B51D /* ResultTable.m in Sources */,
CE1EB5FE12537F9D0034AABB /* HSFairwareReminder.m in Sources */,
CEC9DB4C12CCAA7D003102F0 /* HSAboutBox.m in Sources */,
CE60180812DF3EA900236FDC /* HSRecentFiles.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
CE05339312E5DA350029EF25 /* DirectoryPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE05339412E5DA350029EF25 /* en */,
CE05339F12E5DA420029EF25 /* fr */,
);
name = DirectoryPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE05339512E5DA350029EF25 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
CE05339612E5DA350029EF25 /* en */,
CE0533A012E5DA420029EF25 /* fr */,
);
name = MainMenu.xib;
sourceTree = SOURCE_ROOT;
};
CE05339712E5DA350029EF25 /* ProblemDialog.xib */ = {
isa = PBXVariantGroup;
children = (
CE05339812E5DA350029EF25 /* en */,
CE0533A112E5DA420029EF25 /* fr */,
);
name = ProblemDialog.xib;
sourceTree = SOURCE_ROOT;
};
CE05339912E5DA350029EF25 /* ResultWindow.xib */ = {
isa = PBXVariantGroup;
children = (
CE05339A12E5DA350029EF25 /* en */,
CE0533A212E5DA420029EF25 /* fr */,
);
name = ResultWindow.xib;
sourceTree = SOURCE_ROOT;
};
CE0533A312E5DA4D0029EF25 /* DetailsPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE0533A412E5DA4D0029EF25 /* en */,
CE0533AD12E5DAAD0029EF25 /* fr */,
);
name = DetailsPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE0533A512E5DA4D0029EF25 /* Preferences.xib */ = {
isa = PBXVariantGroup;
children = (
CE0533A612E5DA4D0029EF25 /* en */,
CE0533AE12E5DAAD0029EF25 /* fr */,
);
name = Preferences.xib;
sourceTree = SOURCE_ROOT;
};
CE0533A912E5DA6A0029EF25 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
CE0533AA12E5DA6A0029EF25 /* en */,
CE0533AC12E5DA790029EF25 /* fr */,
);
name = Localizable.strings;
sourceTree = SOURCE_ROOT;
};
CE1EB5FF12537FB90034AABB /* FairwareReminder.xib */ = {
isa = PBXVariantGroup;
children = (
CE1EB60012537FB90034AABB /* en */,
CE0533B712E5DC040029EF25 /* fr */,
);
name = FairwareReminder.xib;
path = ../../cocoalib/xib;
sourceTree = SOURCE_ROOT;
};
CE4527AA12E5F6E700005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE4527AB12E5F6E700005A15 /* en */,
CE4527B012E5F72600005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@@ -0,0 +1,18 @@
/* Class = "NSPanel"; title = "Details of Selected File"; ObjectID = "5"; */
"5.title" = "Details of Selected File";
/* Class = "NSTableColumn"; headerCell.title = "Selected"; ObjectID = "9"; */
"9.headerCell.title" = "Selected";
/* Class = "NSTableColumn"; headerCell.title = "Reference"; ObjectID = "10"; */
"10.headerCell.title" = "Reference";
/* Class = "NSTableColumn"; headerCell.title = "Attribute"; ObjectID = "11"; */
"11.headerCell.title" = "Attribute";
/* Class = "NSTextFieldCell"; title = "Selected"; ObjectID = "33"; */
"33.title" = "Selected";
/* Class = "NSTextFieldCell"; title = "Reference"; ObjectID = "35"; */
"35.title" = "Reference";

Binary file not shown.

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<string key="IBDocument.SystemVersion">10J567</string>
<string key="IBDocument.InterfaceBuilderVersion">823</string>
<string key="IBDocument.AppKitVersion">1038.35</string>
<string key="IBDocument.HIToolboxVersion">462.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">788</string>
<string key="NS.object.0">823</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -19,13 +19,8 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -41,14 +36,14 @@
<object class="NSUserDefaultsController" id="455472712">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>ignoreHardlinkMatches</string>
<string>DebugMode</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
<object class="NSWindowTemplate" id="809668081">
<int key="NSWindowStyleMask">3</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{92, 371}, {392, 231}}</string>
<string key="NSWindowRect">{{92, 348}, {392, 254}}</string>
<int key="NSWTFlags">1886912512</int>
<string key="NSWindowTitle">dupeGuru PE Preferences</string>
<object class="NSMutableString" key="NSWindowClass">
@@ -94,7 +89,7 @@
<object class="NSTabView" id="211771207">
<reference key="NSNextResponder" ref="905655072"/>
<int key="NSvFlags">12</int>
<string key="NSFrame">{{13, 40}, {366, 185}}</string>
<string key="NSFrame">{{13, 40}, {366, 208}}</string>
<reference key="NSSuperview" ref="905655072"/>
<object class="NSMutableArray" key="NSTabViewItems">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -108,7 +103,7 @@
<object class="NSSlider" id="266372855">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{117, 117}, {181, 21}}</string>
<string key="NSFrame">{{117, 140}, {181, 21}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSliderCell" key="NSCell" id="453640282">
@@ -136,7 +131,7 @@
<object class="NSTextField" id="869007847">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{119, 100}, {80, 13}}</string>
<string key="NSFrame">{{119, 123}, {80, 13}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="106025161">
@@ -172,7 +167,7 @@
<object class="NSTextField" id="171701149">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">289</int>
<string key="NSFrame">{{216, 100}, {80, 13}}</string>
<string key="NSFrame">{{216, 123}, {80, 13}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="397705219">
@@ -188,7 +183,7 @@
<object class="NSTextField" id="638371207">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 122}, {100, 14}}</string>
<string key="NSFrame">{{14, 145}, {100, 14}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="812365472">
@@ -208,7 +203,7 @@
<object class="NSButton" id="488256664">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 56}, {214, 18}}</string>
<string key="NSFrame">{{15, 79}, {316, 18}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="401283671">
@@ -231,7 +226,7 @@
<object class="NSButton" id="722670516">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 76}, {214, 18}}</string>
<string key="NSFrame">{{15, 99}, {316, 18}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="911281323">
@@ -252,7 +247,7 @@
<object class="NSButton" id="472028782">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 14}, {283, 18}}</string>
<string key="NSFrame">{{15, 39}, {316, 18}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="2297113">
@@ -273,7 +268,7 @@
<object class="NSButton" id="279087998">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 36}, {242, 18}}</string>
<string key="NSFrame">{{15, 59}, {316, 18}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="287383961">
@@ -294,7 +289,7 @@
<object class="NSTextField" id="403531548">
<reference key="NSNextResponder" ref="1073354031"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{301, 122}, {31, 14}}</string>
<string key="NSFrame">{{301, 145}, {31, 14}}</string>
<reference key="NSSuperview" ref="1073354031"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="983190380">
@@ -321,9 +316,11 @@
<boolean value="YES"/>
<object class="NSAttributedString" id="778485313">
<string key="NSString">0</string>
<object class="NSDictionary" key="NSAttributes" id="715018633">
<object class="NSDictionary" key="NSAttributes" id="808787112">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
@@ -347,7 +344,7 @@
</object>
<object class="NSAttributedString" key="NS.nan">
<string key="NSString">NaN</string>
<reference key="NSAttributes" ref="715018633"/>
<reference key="NSAttributes" ref="808787112"/>
</object>
<object class="NSDecimalNumberPlaceholder" key="NS.min" id="737238985">
<int key="NS.exponent">0</int>
@@ -371,7 +368,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {346, 139}}</string>
<string key="NSFrame">{{10, 33}, {346, 162}}</string>
<reference key="NSSuperview" ref="211771207"/>
</object>
<string key="NSLabel">Basic</string>
@@ -388,7 +385,7 @@
<object class="NSButton" id="1018598123">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 120}, {228, 18}}</string>
<string key="NSFrame">{{15, 143}, {316, 18}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="42276474">
@@ -409,7 +406,7 @@
<object class="NSButton" id="519470955">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 100}, {265, 18}}</string>
<string key="NSFrame">{{15, 123}, {316, 18}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="595497720">
@@ -427,10 +424,31 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSButton" id="606836304">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 103}, {316, 18}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="100803310">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Debug mode (restart required)</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="606836304"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="990345653"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSTextField" id="748076392">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 77}, {85, 13}}</string>
<string key="NSFrame">{{14, 37}, {318, 13}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="936873031">
@@ -446,7 +464,7 @@
<object class="NSTextField" id="526155835">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 49}, {306, 17}}</string>
<string key="NSFrame">{{14, 80}, {318, 17}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="765798142">
@@ -462,7 +480,7 @@
<object class="NSPopUpButton" id="724953200">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{104, 70}, {216, 26}}</string>
<string key="NSFrame">{{14, 5}, {216, 26}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="601288025">
@@ -538,7 +556,7 @@
<object class="NSTextField" id="590530357">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 27}, {312, 22}}</string>
<string key="NSFrame">{{17, 58}, {312, 22}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="922246764">
@@ -566,7 +584,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {346, 139}}</string>
<string key="NSFrame">{{10, 33}, {346, 162}}</string>
</object>
<string key="NSLabel">Advanced</string>
<reference key="NSColor" ref="71910056"/>
@@ -584,7 +602,7 @@
</object>
</object>
</object>
<string key="NSFrameSize">{392, 231}</string>
<string key="NSFrameSize">{392, 254}</string>
<reference key="NSSuperview"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
@@ -835,6 +853,30 @@
</object>
<int key="connectionID">73</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">nextKeyView</string>
<reference key="source" ref="606836304"/>
<reference key="destination" ref="279087998"/>
</object>
<int key="connectionID">77</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.DebugMode</string>
<reference key="source" ref="606836304"/>
<reference key="destination" ref="455472712"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="606836304"/>
<reference key="NSDestination" ref="455472712"/>
<string key="NSLabel">value: values.DebugMode</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.DebugMode</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">78</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -942,6 +984,7 @@
<reference ref="526155835"/>
<reference ref="724953200"/>
<reference ref="590530357"/>
<reference ref="606836304"/>
</object>
<reference key="parent" ref="1045400351"/>
</object>
@@ -956,9 +999,9 @@
<reference ref="171701149"/>
<reference ref="869007847"/>
<reference ref="266372855"/>
<reference ref="472028782"/>
<reference ref="279087998"/>
<reference ref="403531548"/>
<reference ref="472028782"/>
</object>
<reference key="parent" ref="700068878"/>
</object>
@@ -1211,6 +1254,20 @@
<reference key="object" ref="595497720"/>
<reference key="parent" ref="519470955"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">74</int>
<reference key="object" ref="606836304"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="100803310"/>
</object>
<reference key="parent" ref="581039403"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">75</int>
<reference key="object" ref="100803310"/>
<reference key="parent" ref="606836304"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -1221,6 +1278,7 @@
<string>1.IBPluginDependency</string>
<string>1.ImportedFromIB2</string>
<string>10.IBPluginDependency</string>
<string>10.IBViewBoundsToFrameTransform</string>
<string>10.ImportedFromIB2</string>
<string>11.IBPluginDependency</string>
<string>11.ImportedFromIB2</string>
@@ -1271,24 +1329,34 @@
<string>5.ImportedFromIB2</string>
<string>59.IBPluginDependency</string>
<string>6.IBPluginDependency</string>
<string>6.IBViewBoundsToFrameTransform</string>
<string>6.ImportedFromIB2</string>
<string>60.IBPluginDependency</string>
<string>61.IBPluginDependency</string>
<string>62.IBPluginDependency</string>
<string>63.IBPluginDependency</string>
<string>64.IBPluginDependency</string>
<string>64.IBViewBoundsToFrameTransform</string>
<string>64.ImportedFromIB2</string>
<string>65.IBPluginDependency</string>
<string>66.IBPluginDependency</string>
<string>66.IBViewBoundsToFrameTransform</string>
<string>67.IBPluginDependency</string>
<string>69.IBPluginDependency</string>
<string>69.IBViewBoundsToFrameTransform</string>
<string>69.ImportedFromIB2</string>
<string>7.IBPluginDependency</string>
<string>7.ImportedFromIB2</string>
<string>70.IBPluginDependency</string>
<string>74.IBPluginDependency</string>
<string>74.IBViewBoundsToFrameTransform</string>
<string>74.ImportedFromIB2</string>
<string>75.IBPluginDependency</string>
<string>8.IBPluginDependency</string>
<string>8.IBViewBoundsToFrameTransform</string>
<string>8.ImportedFromIB2</string>
<string>9.IBPluginDependency</string>
<string>9.IBViewBoundsToFrameTransform</string>
<string>9.ImportedFromIB2</string>
</object>
<object class="NSMutableArray" key="dict.values">
@@ -1297,6 +1365,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDZgAAwoIAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -1313,9 +1384,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{88, 614}, {392, 231}}</string>
<string>{{88, 591}, {392, 254}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{88, 614}, {392, 231}}</string>
<string>{{88, 591}, {392, 254}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{213, 107}</string>
@@ -1347,24 +1418,48 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwfAAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwrwAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBiAAAwpoAAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwwsAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwu4AAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAweAAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwjwAAA</bytes>
</object>
<boolean value="YES"/>
</object>
</object>
@@ -1384,7 +1479,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">73</int>
<int key="maxID">78</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">

View File

@@ -0,0 +1,18 @@
/* Class = "NSPanel"; title = "Details of Selected File"; ObjectID = "5"; */
"5.title" = "Détails du fichier sélectionné";
/* Class = "NSTableColumn"; headerCell.title = "Selected"; ObjectID = "9"; */
"9.headerCell.title" = "Sélectionné";
/* Class = "NSTableColumn"; headerCell.title = "Reference"; ObjectID = "10"; */
"10.headerCell.title" = "Référence";
/* Class = "NSTableColumn"; headerCell.title = "Attribute"; ObjectID = "11"; */
"11.headerCell.title" = "Attribut";
/* Class = "NSTextFieldCell"; title = "Selected"; ObjectID = "33"; */
"33.title" = "Sélectionné";
/* Class = "NSTextFieldCell"; title = "Reference"; ObjectID = "35"; */
"35.title" = "Référence";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
/* Class = "NSWindow"; title = "dupeGuru PE Preferences"; ObjectID = "2"; */
"2.title" = "Préférences de dupeGuru PE";
/* Class = "NSTextFieldCell"; title = "More results"; ObjectID = "18"; */
"18.title" = "+ de doubles";
/* Class = "NSTextFieldCell"; title = "Fewer results"; ObjectID = "19"; */
"19.title" = "- de doubles";
/* Class = "NSTextFieldCell"; title = "Filter hardness:"; ObjectID = "20"; */
"20.title" = "Seuil du filtre:";
/* Class = "NSButtonCell"; title = "Can mix file kind"; ObjectID = "21"; */
"21.title" = "Comparer les fichiers de différents types";
/* Class = "NSButtonCell"; title = "Reset to Defaults"; ObjectID = "24"; */
"24.title" = "Options par défaut";
/* Class = "NSTextFieldCell"; title = "Copy and Move:"; ObjectID = "25"; */
"25.title" = "Déplacements de fichiers:";
/* Class = "NSMenuItem"; title = "Recreate relative path"; ObjectID = "28"; */
"28.title" = "Re-créer chemins relatifs";
/* Class = "NSMenuItem"; title = "Recreate absolute path"; ObjectID = "29"; */
"29.title" = "Re-créer chemins absolus";
/* Class = "NSMenuItem"; title = "Right in destination"; ObjectID = "30"; */
"30.title" = "Directement à la destination";
/* Class = "NSButtonCell"; title = "Match scaled pictures together"; ObjectID = "31"; */
"31.title" = "Comparer les images de tailles différentes";
/* Class = "NSButtonCell"; title = "Automatically check for updates"; ObjectID = "32"; */
"32.title" = "Vérifier automatiquement les mises à jour";
/* Class = "NSButtonCell"; title = "Remove empty folders on delete or move"; ObjectID = "33"; */
"33.title" = "Effacer les dossiers vides après un déplacement";
/* Class = "NSButtonCell"; title = "Use regular expressions when filtering"; ObjectID = "34"; */
"34.title" = "Utiliser les expressions régulières pour les filtres";
/* Class = "NSTabViewItem"; label = "Basic"; ObjectID = "60"; */
"60.label" = "Simple";
/* Class = "NSTabViewItem"; label = "Advanced"; ObjectID = "61"; */
"61.label" = "Avancé";
/* Class = "NSTextFieldCell"; title = "Custom Command (arguments: %d for dupe, %r for ref):"; ObjectID = "65"; */
"65.title" = "Commande perso. (arguments: %d pour doublon, %r pour réf):";
/* Class = "NSButtonCell"; title = "Ignore duplicates hardlinking to the same file"; ObjectID = "70"; */
"70.title" = "Ignorer doublons avec hardlink vers le même fichier";
/* Class = "NSButtonCell"; title = "Debug mode (restart required)"; ObjectID = "75"; */
"75.title" = "Mode de déboguage (redémarrage requis)";

File diff suppressed because it is too large Load Diff

View File

@@ -11,8 +11,5 @@ http://www.hardcoded.net/licenses/bsd_license
#import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase {}
- (IBAction)openWebsite:(id)sender;
- (IBAction)toggleDirectories:(id)sender;
- (PyDupeGuru *)py;
@end

View File

@@ -12,6 +12,7 @@ http://www.hardcoded.net/licenses/bsd_license
#import "../../cocoalib/ValueTransformers.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h"
#import "ResultWindow.h"
#import "Consts.h"
@implementation AppDelegate
@@ -47,14 +48,14 @@ http://www.hardcoded.net/licenses/bsd_license
return self;
}
- (IBAction)openWebsite:(id)sender
- (NSString *)homepageURL
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru"]];
return @"http://www.hardcoded.net/dupeguru/";
}
- (IBAction)toggleDirectories:(id)sender
- (ResultWindowBase *)createResultWindow
{
[[self directoryPanel] toggleVisible:sender];
return [[ResultWindow alloc] initWithParentApp:self];
}
- (PyDupeGuru *)py { return (PyDupeGuru *)py; }

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key>
<string>hsft</string>
<key>CFBundleVersion</key>
<string>2.12.2</string>
<string>{version}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>

View File

@@ -8,12 +8,6 @@ http://www.hardcoded.net/licenses/bsd_license
#import <Cocoa/Cocoa.h>
#import "../base/ResultWindow.h"
#import "DirectoryPanel.h"
@interface ResultWindow : ResultWindowBase
{
NSString *_lastAction;
}
- (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)startDuplicateScan:(id)sender;
@interface ResultWindow : ResultWindowBase {}
@end

View File

@@ -7,20 +7,41 @@ http://www.hardcoded.net/licenses/bsd_license
*/
#import "ResultWindow.h"
#import "../../cocoalib/Dialogs.h"
#import "../../cocoalib/ProgressController.h"
#import "../../cocoalib/Utils.h"
#import "AppDelegate.h"
#import "Utils.h"
#import "Consts.h"
#import "PyDupeGuru.h"
@implementation ResultWindow
/* Override */
- (void)awakeFromNib
- (void)initResultColumns
{
[super awakeFromNib];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
[deltaColumns addIndex:4];
[table setDeltaColumns:deltaColumns];
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:TR(@"Folder") width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TR(@"Size (KB)") width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:TR(@"Kind") width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:TR(@"Modification") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:TR(@"Match %") width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:TR(@"Words Used") width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:TR(@"Dupe Count") width:80 refCol:refCol]];
}
- (void)setScanOptions
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setScanType:[ud objectForKey:@"scanType"]];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
int smallFileThreshold = [ud integerForKey:@"smallFileThreshold"]; // In KB
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
[_py setSizeThreshold:sizeThreshold];
}
/* Actions */
@@ -38,50 +59,4 @@ http://www.hardcoded.net/licenses/bsd_license
[columnsWidth setObject:i2n(60) forKey:@"5"];
[self restoreColumnsPosition:columnsOrder widths:columnsWidth];
}
- (IBAction)startDuplicateScan:(id)sender
{
if ([matches numberOfRows] > 0)
{
if ([Dialogs askYesNo:@"Are you sure you want to start a new duplicate scan?"] == NSAlertSecondButtonReturn) // NO
return;
}
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setScanType:[ud objectForKey:@"scanType"]];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
int smallFileThreshold = [ud integerForKey:@"smallFileThreshold"]; // In KB
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
[_py setSizeThreshold:sizeThreshold];
int r = n2i([py doScan]);
if (r != 0)
[[ProgressController mainProgressController] hide];
if (r == 3)
{
[Dialogs showMessage:@"The selected directories contain no scannable file."];
[app toggleDirectories:nil];
}
}
/* Public */
- (void)initResultColumns
{
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (KB)" width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Modification" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Match %" width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Words Used" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Dupe Count" width:80 refCol:refCol]];
}
@end

View File

@@ -4,18 +4,15 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
from hscommon.cocoa import signature
from core.scanner import ScanType
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_se.app_cocoa import DupeGuru
# Fix py2app imports with chokes on relative imports and other stuff
import hsutil.conflict
import core.engine, core.fs, core.app
import core_se.fs, core_se.data
import xml.etree.ElementPath
import gzip
from core_se import __appname__
class PyDupeGuru(PyDupeGuruBase):
def init(self):
@@ -48,5 +45,5 @@ class PyDupeGuru(PyDupeGuruBase):
#---Registration
def appName(self):
return "dupeGuru"
return __appname__

View File

@@ -9,17 +9,18 @@
/* Begin PBXBuildFile section */
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_help */; };
CE073F6309CAE1A3005C1D2F /* help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* help */; };
CE19BC6311199231007CCEB0 /* ErrorReportWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE19BC6011199231007CCEB0 /* ErrorReportWindow.xib */; };
CE19BC6411199231007CCEB0 /* progress.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE19BC6111199231007CCEB0 /* progress.xib */; };
CE27D3C112CCA42500859E67 /* about.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE27D3C012CCA42500859E67 /* about.xib */; };
CE27D3C412CCA43800859E67 /* HSAboutBox.m in Sources */ = {isa = PBXBuildFile; fileRef = CE27D3C312CCA43800859E67 /* HSAboutBox.m */; };
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3A46F9109B212E002ABFD5 /* MainMenu.xib */; };
CE4526F212E5F55F00005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE4526F012E5F55F00005A15 /* core.strings */; };
CE45579B0AE3BC2B005A9546 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE647E551173024A006D28BA /* ProblemDialog.m */; };
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE647E581173026F006D28BA /* ProblemDialog.xib */; };
CE6DD4E7124CA3070089A48D /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6DD4E6124CA3070089A48D /* ResultTable.m */; };
CE6DD547124CAF1F0089A48D /* HSTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6DD546124CAF1F0089A48D /* HSTableView.m */; };
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */; };
@@ -32,22 +33,24 @@
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
CE79638612536C94008D405B /* FairwareReminder.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE79638412536C94008D405B /* FairwareReminder.xib */; };
CE79638C12536F4E008D405B /* HSFairwareReminder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE79638B12536F4E008D405B /* HSFairwareReminder.m */; };
CE81134C12E5CE4D00A36C80 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81134212E5CE4D00A36C80 /* DetailsPanel.xib */; };
CE81134D12E5CE4D00A36C80 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81134412E5CE4D00A36C80 /* DirectoryPanel.xib */; };
CE81134E12E5CE4D00A36C80 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81134612E5CE4D00A36C80 /* MainMenu.xib */; };
CE81134F12E5CE4D00A36C80 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81134812E5CE4D00A36C80 /* ProblemDialog.xib */; };
CE81135012E5CE4D00A36C80 /* ResultWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81134A12E5CE4D00A36C80 /* ResultWindow.xib */; };
CE81135812E5CE6D00A36C80 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE81135612E5CE6D00A36C80 /* Preferences.xib */; };
CE8113EB12E5CE9A00A36C80 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE8113E912E5CE9A00A36C80 /* Localizable.strings */; };
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE8C53BB117324CE0011B41F /* HSTable.m */; };
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91F214113BC22D0010360B /* StatsLabel.m */; };
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; };
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */; };
CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; };
CEE7EA130FE675C80004E467 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE7EA120FE675C80004E467 /* DetailsPanel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEEFC0F810945D9F001F3A39 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */; };
CEEFC0FB10945E37001F3A39 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */; };
CEF0ACCE12DF3C2000B32F7E /* HSRecentFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF0ACCD12DF3C2000B32F7E /* HSRecentFiles.m */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8B0FC9517500CD5728 /* Dialogs.m */; };
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */; };
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F910FC9517500CD5728 /* ProgressController.m */; };
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F950FC9517500CD5728 /* RecentDirectories.m */; };
CEFC7FA50FC9517500CD5728 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F9B0FC9517500CD5728 /* Utils.m */; };
CEFC7FA60FC9517500CD5728 /* ValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F9D0FC9517500CD5728 /* ValueTransformers.m */; };
CEFC7FB90FC951A700CD5728 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7FB20FC951A700CD5728 /* AppDelegate.m */; };
@@ -76,20 +79,24 @@
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
8D1107320486CEB800E47090 /* dupeGuru.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dupeGuru.app; sourceTree = BUILT_PRODUCTS_DIR; };
CE073F5409CAE1A3005C1D2F /* dupeguru_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_help; path = ../../help_se/dupeguru_help; sourceTree = "<group>"; };
CE05341312E5DC260029EF25 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../../cocoalib/fr.lproj/FairwareReminder.xib; sourceTree = SOURCE_ROOT; };
CE073F5409CAE1A3005C1D2F /* help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = help; path = ../../build/help; sourceTree = "<group>"; };
CE19BC6011199231007CCEB0 /* ErrorReportWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ErrorReportWindow.xib; sourceTree = "<group>"; };
CE19BC6111199231007CCEB0 /* progress.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = progress.xib; sourceTree = "<group>"; };
CE27D3C012CCA42500859E67 /* about.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = about.xib; path = ../../cocoalib/xib/about.xib; sourceTree = SOURCE_ROOT; };
CE27D3C212CCA43800859E67 /* HSAboutBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSAboutBox.h; path = ../../cocoalib/HSAboutBox.h; sourceTree = SOURCE_ROOT; };
CE27D3C312CCA43800859E67 /* HSAboutBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSAboutBox.m; path = ../../cocoalib/HSAboutBox.m; sourceTree = SOURCE_ROOT; };
CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
CE381C9509914ACE003581CE /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CE4526F112E5F55F00005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE4526F312E5F57000005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE45579A0AE3BC2B005A9546 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE647E541173024A006D28BA /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E551173024A006D28BA /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE647E561173024A006D28BA /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E581173026F006D28BA /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE6DD4E4124CA3070089A48D /* PyResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTable.h; path = ../base/PyResultTable.h; sourceTree = SOURCE_ROOT; };
CE6DD4E5124CA3070089A48D /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CE6DD4E6124CA3070089A48D /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; sourceTree = SOURCE_ROOT; };
@@ -118,12 +125,25 @@
CE79638512536C94008D405B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../../cocoalib/en.lproj/FairwareReminder.xib; sourceTree = SOURCE_ROOT; };
CE79638A12536F4E008D405B /* HSFairwareReminder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSFairwareReminder.h; path = ../../cocoalib/HSFairwareReminder.h; sourceTree = SOURCE_ROOT; };
CE79638B12536F4E008D405B /* HSFairwareReminder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSFairwareReminder.m; path = ../../cocoalib/HSFairwareReminder.m; sourceTree = SOURCE_ROOT; };
CE81134312E5CE4D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/DetailsPanel.xib; sourceTree = SOURCE_ROOT; };
CE81134512E5CE4D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE81134712E5CE4D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE81134912E5CE4D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE81134B12E5CE4D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../base/en.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE81135112E5CE6100A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/DetailsPanel.xib; sourceTree = SOURCE_ROOT; };
CE81135212E5CE6100A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/DirectoryPanel.xib; sourceTree = SOURCE_ROOT; };
CE81135312E5CE6100A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
CE81135412E5CE6100A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE81135512E5CE6100A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = ../base/fr.lproj/ResultWindow.xib; sourceTree = SOURCE_ROOT; };
CE81135712E5CE6D00A36C80 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Preferences.xib; sourceTree = "<group>"; };
CE81135912E5CE7B00A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/Preferences.xib; sourceTree = "<group>"; };
CE8113EA12E5CE9A00A36C80 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE8113EC12E5CEA800A36C80 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
CE8C53B61173248F0011B41F /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE8C53BB117324CE0011B41F /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE91F210113BC22D0010360B /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F213113BC22D0010360B /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F214113BC22D0010360B /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSWindowController.h; sourceTree = "<group>"; };
CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSWindowController.m; sourceTree = "<group>"; };
CEDD92D60FDD01640031C7B7 /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
@@ -131,11 +151,9 @@
CEE7EA110FE675C80004E467 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = ../base/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
CEE7EA120FE675C80004E467 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = ../base/DetailsPanel.m; sourceTree = SOURCE_ROOT; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DirectoryPanel.xib; path = ../base/xib/DirectoryPanel.xib; sourceTree = "<group>"; };
CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DetailsPanel.xib; path = ../base/xib/DetailsPanel.xib; sourceTree = "<group>"; };
CEF0ACCC12DF3C2000B32F7E /* HSRecentFiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSRecentFiles.h; path = ../../cocoalib/HSRecentFiles.h; sourceTree = SOURCE_ROOT; };
CEF0ACCD12DF3C2000B32F7E /* HSRecentFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSRecentFiles.m; path = ../../cocoalib/HSRecentFiles.m; sourceTree = SOURCE_ROOT; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = ../../images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = ../../images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = ../../images/preferences32.png; sourceTree = SOURCE_ROOT; };
CEFC7F8A0FC9517500CD5728 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = ../../cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
@@ -143,8 +161,6 @@
CEFC7F900FC9517500CD5728 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CEFC7F910FC9517500CD5728 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CEFC7F920FC9517500CD5728 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
CEFC7F940FC9517500CD5728 /* RecentDirectories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecentDirectories.h; path = ../../cocoalib/RecentDirectories.h; sourceTree = SOURCE_ROOT; };
CEFC7F950FC9517500CD5728 /* RecentDirectories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RecentDirectories.m; path = ../../cocoalib/RecentDirectories.m; sourceTree = SOURCE_ROOT; };
CEFC7F9A0FC9517500CD5728 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = ../../cocoalib/Utils.h; sourceTree = SOURCE_ROOT; };
CEFC7F9B0FC9517500CD5728 /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = ../../cocoalib/Utils.m; sourceTree = SOURCE_ROOT; };
CEFC7F9C0FC9517500CD5728 /* ValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueTransformers.h; path = ../../cocoalib/ValueTransformers.h; sourceTree = SOURCE_ROOT; };
@@ -229,12 +245,14 @@
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
CE073F5409CAE1A3005C1D2F /* dupeguru_help */,
CE073F5409CAE1A3005C1D2F /* help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */,
CEEFC0CA10943849001F3A39 /* xib */,
CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */,
CE8113E912E5CE9A00A36C80 /* Localizable.strings */,
CE4526F012E5F55F00005A15 /* core.strings */,
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */,
);
name = Resources;
@@ -252,6 +270,7 @@
CE19BC5F11199231007CCEB0 /* xib */ = {
isa = PBXGroup;
children = (
CE27D3C012CCA42500859E67 /* about.xib */,
CE79638412536C94008D405B /* FairwareReminder.xib */,
CE19BC6011199231007CCEB0 /* ErrorReportWindow.xib */,
CE19BC6111199231007CCEB0 /* progress.xib */,
@@ -315,11 +334,12 @@
CEEFC0CA10943849001F3A39 /* xib */ = {
isa = PBXGroup;
children = (
CE647E581173026F006D28BA /* ProblemDialog.xib */,
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */,
CEAC6810109B0B7E00B43C85 /* Preferences.xib */,
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */,
CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */,
CE81134212E5CE4D00A36C80 /* DetailsPanel.xib */,
CE81134412E5CE4D00A36C80 /* DirectoryPanel.xib */,
CE81134612E5CE4D00A36C80 /* MainMenu.xib */,
CE81134812E5CE4D00A36C80 /* ProblemDialog.xib */,
CE81134A12E5CE4D00A36C80 /* ResultWindow.xib */,
CE81135612E5CE6D00A36C80 /* Preferences.xib */,
);
name = xib;
sourceTree = "<group>";
@@ -327,8 +347,6 @@
CEFC294309C89E0000D9F998 /* images */ = {
isa = PBXGroup;
children = (
CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */,
);
name = images;
@@ -351,11 +369,13 @@
CE79638A12536F4E008D405B /* HSFairwareReminder.h */,
CE79638B12536F4E008D405B /* HSFairwareReminder.m */,
CE79638212536C6E008D405B /* PyFairware.h */,
CE27D3C212CCA43800859E67 /* HSAboutBox.h */,
CE27D3C312CCA43800859E67 /* HSAboutBox.m */,
CEF0ACCC12DF3C2000B32F7E /* HSRecentFiles.h */,
CEF0ACCD12DF3C2000B32F7E /* HSRecentFiles.m */,
CEFC7F900FC9517500CD5728 /* ProgressController.h */,
CEFC7F910FC9517500CD5728 /* ProgressController.m */,
CEFC7F920FC9517500CD5728 /* PyApp.h */,
CEFC7F940FC9517500CD5728 /* RecentDirectories.h */,
CEFC7F950FC9517500CD5728 /* RecentDirectories.m */,
CEFC7F9A0FC9517500CD5728 /* Utils.h */,
CEFC7F9B0FC9517500CD5728 /* Utils.m */,
CEFC7F9C0FC9517500CD5728 /* ValueTransformers.h */,
@@ -426,6 +446,7 @@
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */;
compatibilityVersion = "Xcode 3.0";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
@@ -433,6 +454,7 @@
French,
German,
en,
fr,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */;
projectDirPath = "";
@@ -449,20 +471,22 @@
buildActionMask = 2147483647;
files = (
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */,
CE073F6309CAE1A3005C1D2F /* help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */,
CEEFC0F810945D9F001F3A39 /* DirectoryPanel.xib in Resources */,
CEEFC0FB10945E37001F3A39 /* DetailsPanel.xib in Resources */,
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */,
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */,
CE19BC6311199231007CCEB0 /* ErrorReportWindow.xib in Resources */,
CE19BC6411199231007CCEB0 /* progress.xib in Resources */,
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */,
CE79638612536C94008D405B /* FairwareReminder.xib in Resources */,
CE27D3C112CCA42500859E67 /* about.xib in Resources */,
CE81134C12E5CE4D00A36C80 /* DetailsPanel.xib in Resources */,
CE81134D12E5CE4D00A36C80 /* DirectoryPanel.xib in Resources */,
CE81134E12E5CE4D00A36C80 /* MainMenu.xib in Resources */,
CE81134F12E5CE4D00A36C80 /* ProblemDialog.xib in Resources */,
CE81135012E5CE4D00A36C80 /* ResultWindow.xib in Resources */,
CE81135812E5CE6D00A36C80 /* Preferences.xib in Resources */,
CE8113EB12E5CE9A00A36C80 /* Localizable.strings in Resources */,
CE4526F212E5F55F00005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -479,7 +503,6 @@
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */,
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */,
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */,
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */,
CEFC7FA50FC9517500CD5728 /* Utils.m in Sources */,
CEFC7FA60FC9517500CD5728 /* ValueTransformers.m in Sources */,
CEFC7FB90FC951A700CD5728 /* AppDelegate.m in Sources */,
@@ -501,21 +524,96 @@
CE6DD4E7124CA3070089A48D /* ResultTable.m in Sources */,
CE6DD547124CAF1F0089A48D /* HSTableView.m in Sources */,
CE79638C12536F4E008D405B /* HSFairwareReminder.m in Sources */,
CE27D3C412CCA43800859E67 /* HSAboutBox.m in Sources */,
CEF0ACCE12DF3C2000B32F7E /* HSRecentFiles.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
CE4526F012E5F55F00005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE4526F112E5F55F00005A15 /* en */,
CE4526F312E5F57000005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
CE79638412536C94008D405B /* FairwareReminder.xib */ = {
isa = PBXVariantGroup;
children = (
CE79638512536C94008D405B /* en */,
CE05341312E5DC260029EF25 /* fr */,
);
name = FairwareReminder.xib;
path = ../../cocoalib/xib;
sourceTree = SOURCE_ROOT;
};
CE81134212E5CE4D00A36C80 /* DetailsPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE81134312E5CE4D00A36C80 /* en */,
CE81135112E5CE6100A36C80 /* fr */,
);
name = DetailsPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE81134412E5CE4D00A36C80 /* DirectoryPanel.xib */ = {
isa = PBXVariantGroup;
children = (
CE81134512E5CE4D00A36C80 /* en */,
CE81135212E5CE6100A36C80 /* fr */,
);
name = DirectoryPanel.xib;
sourceTree = SOURCE_ROOT;
};
CE81134612E5CE4D00A36C80 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
CE81134712E5CE4D00A36C80 /* en */,
CE81135312E5CE6100A36C80 /* fr */,
);
name = MainMenu.xib;
sourceTree = SOURCE_ROOT;
};
CE81134812E5CE4D00A36C80 /* ProblemDialog.xib */ = {
isa = PBXVariantGroup;
children = (
CE81134912E5CE4D00A36C80 /* en */,
CE81135412E5CE6100A36C80 /* fr */,
);
name = ProblemDialog.xib;
sourceTree = SOURCE_ROOT;
};
CE81134A12E5CE4D00A36C80 /* ResultWindow.xib */ = {
isa = PBXVariantGroup;
children = (
CE81134B12E5CE4D00A36C80 /* en */,
CE81135512E5CE6100A36C80 /* fr */,
);
name = ResultWindow.xib;
sourceTree = SOURCE_ROOT;
};
CE81135612E5CE6D00A36C80 /* Preferences.xib */ = {
isa = PBXVariantGroup;
children = (
CE81135712E5CE6D00A36C80 /* en */,
CE81135912E5CE7B00A36C80 /* fr */,
);
name = Preferences.xib;
sourceTree = SOURCE_ROOT;
};
CE8113E912E5CE9A00A36C80 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
CE8113EA12E5CE9A00A36C80 /* en */,
CE8113EC12E5CEA800A36C80 /* fr */,
);
name = Localizable.strings;
sourceTree = SOURCE_ROOT;
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

Binary file not shown.

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<string key="IBDocument.SystemVersion">10J567</string>
<string key="IBDocument.InterfaceBuilderVersion">823</string>
<string key="IBDocument.AppKitVersion">1038.35</string>
<string key="IBDocument.HIToolboxVersion">462.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">788</string>
<string key="NS.object.0">823</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -19,13 +19,8 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -39,12 +34,16 @@
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSUserDefaultsController" id="75941798">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>DebugMode</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
<object class="NSWindowTemplate" id="489014306">
<int key="NSWindowStyleMask">3</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{92, 300}, {389, 302}}</string>
<string key="NSWindowRect">{{92, 277}, {389, 325}}</string>
<int key="NSWTFlags">1886912512</int>
<string key="NSWindowTitle">dupeGuru Preferences</string>
<object class="NSMutableString" key="NSWindowClass">
@@ -90,7 +89,7 @@
<object class="NSTabView" id="712448818">
<reference key="NSNextResponder" ref="642300710"/>
<int key="NSvFlags">12</int>
<string key="NSFrame">{{13, 40}, {363, 256}}</string>
<string key="NSFrame">{{13, 40}, {363, 279}}</string>
<reference key="NSSuperview" ref="642300710"/>
<object class="NSMutableArray" key="NSTabViewItems">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -104,7 +103,7 @@
<object class="NSSlider" id="111002126">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{117, 148}, {181, 21}}</string>
<string key="NSFrame">{{117, 171}, {181, 21}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSliderCell" key="NSCell" id="4139314">
@@ -132,7 +131,7 @@
<object class="NSTextField" id="950195532">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{119, 131}, {80, 13}}</string>
<string key="NSFrame">{{119, 154}, {80, 13}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="117548381">
@@ -168,7 +167,7 @@
<object class="NSTextField" id="1008577648">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">289</int>
<string key="NSFrame">{{216, 131}, {80, 13}}</string>
<string key="NSFrame">{{216, 154}, {80, 13}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="569479200">
@@ -184,7 +183,7 @@
<object class="NSTextField" id="1006361062">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 153}, {100, 14}}</string>
<string key="NSFrame">{{14, 176}, {100, 14}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="566839293">
@@ -204,7 +203,7 @@
<object class="NSTextField" id="511073890">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{17, 194}, {85, 13}}</string>
<string key="NSFrame">{{17, 217}, {85, 13}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="901283318">
@@ -220,7 +219,7 @@
<object class="NSPopUpButton" id="413464883">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{116, 183}, {216, 26}}</string>
<string key="NSFrame">{{116, 206}, {216, 26}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="63752222">
@@ -285,7 +284,7 @@
<object class="NSButton" id="637819333">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 107}, {214, 18}}</string>
<string key="NSFrame">{{15, 130}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="369089279">
@@ -308,7 +307,7 @@
<object class="NSButton" id="1067721243">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 67}, {214, 18}}</string>
<string key="NSFrame">{{15, 90}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="304300476">
@@ -329,7 +328,7 @@
<object class="NSButton" id="290008886">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 87}, {214, 18}}</string>
<string key="NSFrame">{{15, 110}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="949112651">
@@ -350,7 +349,7 @@
<object class="NSButton" id="551239185">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 5}, {283, 18}}</string>
<string key="NSFrame">{{15, 7}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="456303302">
@@ -371,7 +370,7 @@
<object class="NSButton" id="208488736">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 45}, {242, 18}}</string>
<string key="NSFrame">{{15, 70}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="275918454">
@@ -392,13 +391,13 @@
<object class="NSButton" id="427690895">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 25}, {152, 18}}</string>
<string key="NSFrame">{{15, 48}, {313, 18}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="527567105">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Ignore files smaller than</string>
<string key="NSContents">Ignore files smaller than:</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="427690895"/>
<int key="NSButtonFlags">1211912703</int>
@@ -413,7 +412,7 @@
<object class="NSTextField" id="880304924">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{173, 23}, {59, 22}}</string>
<string key="NSFrame">{{40, 26}, {59, 22}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="210024698">
@@ -457,9 +456,11 @@
<nil key="NS.nil"/>
<object class="NSAttributedString" key="NS.nan">
<string key="NSString">NaN</string>
<object class="NSDictionary" key="NSAttributes" id="781126459">
<object class="NSDictionary" key="NSAttributes" id="755311072">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
@@ -508,7 +509,7 @@
<object class="NSTextField" id="1051684239">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{240, 25}, {23, 17}}</string>
<string key="NSFrame">{{104, 25}, {23, 17}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="212167232">
@@ -524,7 +525,7 @@
<object class="NSTextField" id="262539816">
<reference key="NSNextResponder" ref="889257400"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{301, 153}, {31, 14}}</string>
<string key="NSFrame">{{301, 176}, {31, 14}}</string>
<reference key="NSSuperview" ref="889257400"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="186096546">
@@ -551,7 +552,7 @@
<boolean value="YES"/>
<object class="NSAttributedString" id="428931648">
<string key="NSString">0</string>
<reference key="NSAttributes" ref="781126459"/>
<reference key="NSAttributes" ref="755311072"/>
</object>
<string>.</string>
<integer value="1000"/>
@@ -571,7 +572,7 @@
</object>
<object class="NSAttributedString" key="NS.nan">
<string key="NSString">NaN</string>
<reference key="NSAttributes" ref="781126459"/>
<reference key="NSAttributes" ref="755311072"/>
</object>
<reference key="NS.min" ref="643632001"/>
<reference key="NS.max" ref="643632001"/>
@@ -588,7 +589,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {343, 210}}</string>
<string key="NSFrame">{{10, 33}, {343, 233}}</string>
<reference key="NSSuperview" ref="712448818"/>
</object>
<string key="NSLabel">Basic</string>
@@ -605,7 +606,7 @@
<object class="NSButton" id="724127338">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 191}, {228, 18}}</string>
<string key="NSFrame">{{15, 214}, {313, 18}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="360294640">
@@ -626,7 +627,7 @@
<object class="NSButton" id="647216699">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 171}, {265, 18}}</string>
<string key="NSFrame">{{15, 194}, {313, 18}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="118836063">
@@ -644,10 +645,31 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSButton" id="727223254">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 174}, {313, 18}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="236967908">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Debug mode (restart required)</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="727223254"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSTextField" id="962804407">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 148}, {315, 17}}</string>
<string key="NSFrame">{{14, 151}, {315, 17}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="111092399">
@@ -663,7 +685,7 @@
<object class="NSTextField" id="873032174">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 118}, {309, 22}}</string>
<string key="NSFrame">{{17, 121}, {309, 22}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="249250691">
@@ -680,7 +702,7 @@
<object class="NSTextField" id="511043844">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 97}, {85, 13}}</string>
<string key="NSFrame">{{14, 100}, {315, 13}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="669919489">
@@ -696,7 +718,7 @@
<object class="NSPopUpButton" id="857082145">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{101, 86}, {216, 26}}</string>
<string key="NSFrame">{{14, 68}, {234, 26}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="307074513">
@@ -764,7 +786,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {343, 210}}</string>
<string key="NSFrame">{{10, 33}, {343, 233}}</string>
</object>
<string key="NSLabel">Advanced</string>
<reference key="NSColor" ref="623994344"/>
@@ -782,7 +804,7 @@
</object>
</object>
</object>
<string key="NSFrameSize">{389, 302}</string>
<string key="NSFrameSize">{389, 325}</string>
<reference key="NSSuperview"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
@@ -1105,6 +1127,22 @@
</object>
<int key="connectionID">144</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.DebugMode</string>
<reference key="source" ref="727223254"/>
<reference key="destination" ref="75941798"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="727223254"/>
<reference key="NSDestination" ref="75941798"/>
<string key="NSLabel">value: values.DebugMode</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.DebugMode</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">148</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -1208,6 +1246,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="724127338"/>
<reference ref="647216699"/>
<reference ref="727223254"/>
<reference ref="962804407"/>
<reference ref="873032174"/>
<reference ref="511043844"/>
@@ -1229,12 +1268,12 @@
<reference ref="1008577648"/>
<reference ref="950195532"/>
<reference ref="111002126"/>
<reference ref="551239185"/>
<reference ref="208488736"/>
<reference ref="427690895"/>
<reference ref="262539816"/>
<reference ref="208488736"/>
<reference ref="880304924"/>
<reference ref="1051684239"/>
<reference ref="262539816"/>
<reference ref="551239185"/>
</object>
<reference key="parent" ref="562140942"/>
</object>
@@ -1604,6 +1643,20 @@
<reference key="object" ref="118836063"/>
<reference key="parent" ref="647216699"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">145</int>
<reference key="object" ref="727223254"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="236967908"/>
</object>
<reference key="parent" ref="448252432"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">146</int>
<reference key="object" ref="236967908"/>
<reference key="parent" ref="727223254"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -1621,13 +1674,20 @@
<string>128.ImportedFromIB2</string>
<string>129.IBPluginDependency</string>
<string>133.IBPluginDependency</string>
<string>133.IBViewBoundsToFrameTransform</string>
<string>133.ImportedFromIB2</string>
<string>134.IBPluginDependency</string>
<string>138.IBPluginDependency</string>
<string>138.IBViewBoundsToFrameTransform</string>
<string>139.IBPluginDependency</string>
<string>141.IBPluginDependency</string>
<string>141.IBViewBoundsToFrameTransform</string>
<string>141.ImportedFromIB2</string>
<string>142.IBPluginDependency</string>
<string>145.IBPluginDependency</string>
<string>145.IBViewBoundsToFrameTransform</string>
<string>145.ImportedFromIB2</string>
<string>146.IBPluginDependency</string>
<string>51.IBPluginDependency</string>
<string>51.ImportedFromIB2</string>
<string>52.IBEditorWindowLastContentRect</string>
@@ -1639,22 +1699,29 @@
<string>53.IBPluginDependency</string>
<string>53.ImportedFromIB2</string>
<string>54.IBPluginDependency</string>
<string>54.IBViewBoundsToFrameTransform</string>
<string>54.ImportedFromIB2</string>
<string>55.IBPluginDependency</string>
<string>55.IBViewBoundsToFrameTransform</string>
<string>55.ImportedFromIB2</string>
<string>56.IBPluginDependency</string>
<string>56.ImportedFromIB2</string>
<string>57.IBPluginDependency</string>
<string>57.IBViewBoundsToFrameTransform</string>
<string>57.ImportedFromIB2</string>
<string>59.IBPluginDependency</string>
<string>59.IBViewBoundsToFrameTransform</string>
<string>59.ImportedFromIB2</string>
<string>60.IBPluginDependency</string>
<string>60.IBViewBoundsToFrameTransform</string>
<string>60.ImportedFromIB2</string>
<string>61.IBPluginDependency</string>
<string>61.IBViewBoundsToFrameTransform</string>
<string>61.ImportedFromIB2</string>
<string>62.IBPluginDependency</string>
<string>62.ImportedFromIB2</string>
<string>63.IBPluginDependency</string>
<string>63.IBViewBoundsToFrameTransform</string>
<string>63.ImportedFromIB2</string>
<string>64.IBPluginDependency</string>
<string>64.ImportedFromIB2</string>
@@ -1695,6 +1762,7 @@
<string>87.IBPluginDependency</string>
<string>88.IBPluginDependency</string>
<string>89.IBPluginDependency</string>
<string>90.IBEditorWindowLastContentRect</string>
<string>90.IBPluginDependency</string>
<string>90.ImportedFromIB2</string>
<string>91.IBPluginDependency</string>
@@ -1724,40 +1792,76 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwyYAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBiAAAww0AAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAw1IAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBoAAAw00AAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{88, 543}, {389, 302}}</string>
<string>{{88, 520}, {389, 325}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{88, 543}, {389, 302}}</string>
<string>{{88, 520}, {389, 325}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{213, 107}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDcAAAwqIAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABCUAAAwoAAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwnQAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBcAAAwhAAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwrgAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwt4AAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDYwAAwigAAA</bytes>
</object>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -1798,6 +1902,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{114, 624}, {234, 63}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -1831,7 +1936,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">144</int>
<int key="maxID">148</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">

View File

@@ -0,0 +1,75 @@
/* Class = "NSWindow"; title = "dupeGuru Preferences"; ObjectID = "52"; */
"52.title" = "Préférences de dupeGuru";
/* Class = "NSTextFieldCell"; title = "More results"; ObjectID = "74"; */
"74.title" = "+ de doubles";
/* Class = "NSTextFieldCell"; title = "Fewer results"; ObjectID = "75"; */
"75.title" = "- de doubles";
/* Class = "NSTextFieldCell"; title = "Filter hardness:"; ObjectID = "76"; */
"76.title" = "Seuil du filtre:";
/* Class = "NSTextFieldCell"; title = "Scan type:"; ObjectID = "77"; */
"77.title" = "Type de scan:";
/* Class = "NSMenuItem"; title = "Content"; ObjectID = "80"; */
"80.title" = "Contenu";
/* Class = "NSMenuItem"; title = "Filename"; ObjectID = "81"; */
"81.title" = "Nom de fichier";
/* Class = "NSButtonCell"; title = "Word weighting"; ObjectID = "82"; */
"82.title" = "Proportionalité des mots";
/* Class = "NSButtonCell"; title = "Can mix file kind"; ObjectID = "83"; */
"83.title" = "Comparer les fichiers de différents types";
/* Class = "NSButtonCell"; title = "Reset to Defaults"; ObjectID = "86"; */
"86.title" = "Options par défaut";
/* Class = "NSButtonCell"; title = "Match similar words"; ObjectID = "87"; */
"87.title" = "Comparer les mots similaires";
/* Class = "NSTextFieldCell"; title = "Copy and Move:"; ObjectID = "88"; */
"88.title" = "Déplacements de fichiers:";
/* Class = "NSMenuItem"; title = "Recreate relative path"; ObjectID = "91"; */
"91.title" = "Re-créer chemins relatifs";
/* Class = "NSMenuItem"; title = "Recreate absolute path"; ObjectID = "92"; */
"92.title" = "Re-créer chemins absolus";
/* Class = "NSMenuItem"; title = "Right in destination"; ObjectID = "93"; */
"93.title" = "Directement à la destination";
/* Class = "NSButtonCell"; title = "Automatically check for updates"; ObjectID = "94"; */
"94.title" = "Vérifier automatiquement les mises à jour";
/* Class = "NSButtonCell"; title = "Remove empty folders on delete or move"; ObjectID = "96"; */
"96.title" = "Effacer les dossiers vides après un déplacement";
/* Class = "NSButtonCell"; title = "Ignore files smaller than"; ObjectID = "97"; */
"97.title" = "Ignorer les fichiers plus petits que:";
/* Class = "NSTextFieldCell"; title = "KB"; ObjectID = "100"; */
"100.title" = "KB";
/* Class = "NSTabViewItem"; label = "Basic"; ObjectID = "124"; */
"124.label" = "Simple";
/* Class = "NSTabViewItem"; label = "Advanced"; ObjectID = "125"; */
"125.label" = "Avancé";
/* Class = "NSButtonCell"; title = "Use regular expressions when filtering"; ObjectID = "129"; */
"129.title" = "Utiliser les expressions régulières pour les filtres";
/* Class = "NSTextFieldCell"; title = "Custom command (arguments: %d for dupe, %r for ref):"; ObjectID = "134"; */
"134.title" = "Commande perso. (arguments: %d pour doublon, %r pour réf):";
/* Class = "NSButtonCell"; title = "Ignore duplicates hardlinking to the same file"; ObjectID = "142"; */
"142.title" = "Ignorer doublons avec hardlink vers le même fichier";
/* Class = "NSButtonCell"; title = "Debug mode (restart required)"; ObjectID = "146"; */
"146.title" = "Mode de déboguage (redémarrage requis)";

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,7 @@
import sys
from optparse import OptionParser
import yaml
import json
def main(edition, ui, dev):
if edition not in ('se', 'me', 'pe'):
@@ -24,7 +23,7 @@ def main(edition, ui, dev):
'ui': ui,
'dev': dev,
}
yaml.dump(conf, open('conf.yaml', 'w'))
json.dump(conf, open('conf.json', 'w'))
if __name__ == '__main__':
usage = "usage: %prog [options]"

View File

@@ -13,12 +13,13 @@ import subprocess
import re
from send2trash import send2trash
from hscommon import io
from hscommon.reg import RegistrableApplication
from hscommon.notify import Broadcaster
from hsutil import io, files
from hsutil.path import Path
from hsutil.misc import flatten, first
from hsutil.str import escape
from hscommon.path import Path
from hscommon.conflict import smart_move, smart_copy
from hscommon.util import delete_if_empty, first, escape, nonone
from hscommon.trans import tr
from . import directories, results, scanner, export, fs
@@ -28,13 +29,22 @@ JOB_MOVE = 'job_move'
JOB_COPY = 'job_copy'
JOB_DELETE = 'job_delete'
HAD_FIRST_LAUNCH_PREFERENCE = 'HadFirstLaunch'
DEBUG_MODE_PREFERENCE = 'DebugMode'
class NoScannableFileError(Exception):
pass
class DupeGuru(RegistrableApplication, Broadcaster):
def __init__(self, data_module, appdata):
if self.get_default(DEBUG_MODE_PREFERENCE, False):
logging.getLogger().setLevel(logging.DEBUG)
logging.debug("Debug mode enabled")
RegistrableApplication.__init__(self, appid=1)
Broadcaster.__init__(self)
self.is_first_run = not self.get_default(HAD_FIRST_LAUNCH_PREFERENCE, False)
if self.is_first_run:
self.set_default(HAD_FIRST_LAUNCH_PREFERENCE, True)
self.appdata = appdata
if not op.exists(self.appdata):
os.makedirs(self.appdata)
@@ -49,6 +59,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
}
self.selected_dupes = []
#--- Private
def _do_delete(self, j, replace_with_hardlinks):
def op(dupe):
j.add_progress()
@@ -67,11 +78,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
os.link(str(ref.path), str(dupe.path))
self.clean_empty_dirs(dupe.path[:-1])
def _do_load(self, j):
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
self.notify('directories_changed')
self.results.load_from_xml(op.join(self.appdata, 'last_results.xml'), self._get_file, j)
def _get_display_info(self, dupe, group, delta=False):
if (dupe is None) or (group is None):
return ['---'] * len(self.data.COLUMNS)
@@ -113,7 +119,11 @@ class DupeGuru(RegistrableApplication, Broadcaster):
seen_inodes = set()
result = []
for file in files:
try:
inode = io.stat(file.path).st_ino
except OSError:
# The file was probably deleted or something
continue
if inode not in seen_inodes:
seen_inodes.add(inode)
result.append(file)
@@ -129,6 +139,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
# 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()
#--- Public
def add_directory(self, d):
try:
self.directories.add_path(Path(d))
@@ -151,14 +168,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def apply_filter(self, filter):
self.results.apply_filter(None)
if self.options['escape_filter_regexp']:
filter = escape(filter, '()[]\\.|+?^')
filter = escape(filter, set('()[]\\.|+?^'))
filter = escape(filter, '*', '.')
self.results.apply_filter(filter)
self.notify('results_changed')
def clean_empty_dirs(self, path):
if self.options['clean_empty_dirs']:
while files.delete_if_empty(path, ['.DS_Store']):
while delete_if_empty(path, ['.DS_Store']):
path = path[:-1]
def copy_or_move(self, dupe, copy, destination, dest_type):
@@ -180,9 +197,9 @@ class DupeGuru(RegistrableApplication, Broadcaster):
io.makedirs(dest_path)
# Raises an EnvironmentError if there's a problem
if copy:
files.copy(source_path, dest_path)
smart_copy(source_path, dest_path)
else:
files.move(source_path, dest_path)
smart_move(source_path, dest_path)
self.clean_empty_dirs(source_path[:-1])
def copy_or_move_marked(self, copy, destination, recreate_path):
@@ -204,7 +221,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
column_ids = [colid for colid in column_ids if colid.isdigit()]
column_ids = list(map(int, column_ids))
column_ids.sort()
colnames = [col['display'] for i, col in enumerate(self.data.COLUMNS) if i in column_ids]
colnames = [col.display for i, col in enumerate(self.data.COLUMNS) if i in column_ids]
rows = []
for group in self.results.groups:
for dupe in group:
@@ -240,18 +257,16 @@ class DupeGuru(RegistrableApplication, Broadcaster):
subprocess.Popen(cmd, shell=True)
def load(self):
self._start_job(JOB_LOAD, self._do_load)
self.load_ignore_list()
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
self.notify('directories_changed')
p = op.join(self.appdata, 'ignore_list.xml')
self.scanner.ignore_list.load_from_xml(p)
def load_from(self, filename):
def do(j):
self.results.load_from_xml(filename, self._get_file, j)
self._start_job(JOB_LOAD, do)
def load_ignore_list(self):
p = op.join(self.appdata, 'ignore_list.xml')
self.scanner.ignore_list.load_from_xml(p)
def make_selected_reference(self):
dupes = self.without_ref(self.selected_dupes)
changed_groups = set()
@@ -323,23 +338,15 @@ class DupeGuru(RegistrableApplication, Broadcaster):
if not op.exists(self.appdata):
os.makedirs(self.appdata)
self.directories.save_to_file(op.join(self.appdata, 'last_directories.xml'))
if self.results.is_modified:
self.results.save_to_xml(op.join(self.appdata, 'last_results.xml'))
def save_as(self, filename):
self.results.save_to_xml(filename)
# It's not because we saved it here that we don't want to save it in appdata when we quit
self.results.is_modified = True
def save_ignore_list(self):
if not op.exists(self.appdata):
os.makedirs(self.appdata)
p = op.join(self.appdata, 'ignore_list.xml')
self.scanner.ignore_list.save_to_xml(p)
def save_as(self, filename):
self.results.save_to_xml(filename)
def start_scanning(self):
def do(j):
j.set_progress(0, 'Collecting files to scan')
j.set_progress(0, tr("Collecting files to scan"))
files = list(self.directories.get_files())
if self.options['ignore_hardlink_matches']:
files = self._remove_hardlink_dupes(files)
@@ -349,6 +356,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
if not self.directories.has_any_file():
raise NoScannableFileError()
self.results.groups = []
self.notify('results_changed')
self._start_job(JOB_SCAN, do)
def toggle_selected_mark_state(self):
@@ -359,11 +367,24 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def without_ref(self, dupes):
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)
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:
result = type(fallback_value)(result)
except Exception:
result = fallback_value
return result
def set_default(self, key, value):
self._set_default(key, value)
#--- Properties
@property
def stat_line(self):
result = self.results.stat_line
if self.scanner.discarded_file_count:
result = '%s (%d discarded)' % (result, self.scanner.discarded_file_count)
result = tr("%s (%d discarded)") % (result, self.scanner.discarded_file_count)
return result

View File

@@ -11,26 +11,25 @@ import os.path as op
from jobprogress import job
from hscommon import cocoa
from hscommon.cocoa import install_exception_hook
from hscommon.cocoa import install_exception_hook, pythonify
from hscommon.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
NSWorkspace)
from hscommon.trans import tr
from . import app
JOBID2TITLE = {
app.JOB_SCAN: "Scanning for duplicates",
app.JOB_LOAD: "Loading",
app.JOB_MOVE: "Moving",
app.JOB_COPY: "Copying",
app.JOB_DELETE: "Sending to Trash",
app.JOB_SCAN: tr("Scanning for duplicates"),
app.JOB_LOAD: tr("Loading"),
app.JOB_MOVE: tr("Moving"),
app.JOB_COPY: tr("Copying"),
app.JOB_DELETE: tr("Sending to Trash"),
}
class DupeGuru(app.DupeGuru):
def __init__(self, data_module, appdata_subdir):
LOGGING_LEVEL = logging.DEBUG if NSUserDefaults.standardUserDefaults().boolForKey_('debug') else logging.WARNING
logging.basicConfig(level=LOGGING_LEVEL, format='%(levelname)s %(message)s')
logging.debug('started in debug mode')
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)
@@ -57,7 +56,15 @@ class DupeGuru(app.DupeGuru):
ud = {'desc': JOBID2TITLE[jobid], 'jobid':jobid}
NSNotificationCenter.defaultCenter().postNotificationName_object_userInfo_('JobStarted', self, ud)
#---Public
def _get_default(self, key_name):
raw = NSUserDefaults.standardUserDefaults().objectForKey_(key_name)
result = pythonify(raw)
return result
def _set_default(self, key_name, value):
NSUserDefaults.standardUserDefaults().setObject_forKey_(value, key_name)
#--- Public
def start_scanning(self):
self._select_dupes([])
try:

View File

@@ -18,10 +18,6 @@ from .gui.problem_table import ProblemTable
from .gui.result_table import ResultTable
from .gui.stats_label import StatsLabel
# Fix py2app's problems on relative imports
from core import app, app_cocoa, data, directories, engine, export, ignore, results, fs, scanner
from hsutil import conflict
class PyDupeGuruBase(PyFairware):
#---Directories
def addDirectory_(self, directory):
@@ -40,10 +36,7 @@ class PyDupeGuruBase(PyFairware):
def exportToXHTMLwithColumns_(self, column_ids):
return self.py.export_to_xhtml(column_ids)
def loadIgnoreList(self):
self.py.load_ignore_list()
def loadResults(self):
def loadSession(self):
self.py.load()
def loadResultsFrom_(self, filename):
@@ -64,10 +57,7 @@ class PyDupeGuruBase(PyFairware):
def toggleSelectedMark(self):
self.py.toggle_selected_mark_state()
def saveIgnoreList(self):
self.py.save_ignore_list()
def saveResults(self):
def saveSession(self):
self.py.save()
def saveResultsAs_(self, filename):
@@ -118,6 +108,13 @@ class PyDupeGuruBase(PyFairware):
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):

View File

@@ -6,16 +6,20 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hsutil.str import format_time, FT_DECIMAL, format_size
from collections import namedtuple
from hscommon.util import format_time_decimal, format_size
import time
Column = namedtuple('Column', 'attr display')
def format_path(p):
return str(p[:-1])
def format_timestamp(t, delta):
if delta:
return format_time(t, FT_DECIMAL)
return format_time_decimal(t)
else:
if t > 0:
return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(t))

View File

@@ -7,10 +7,11 @@
# http://www.hardcoded.net/licenses/bsd_license
from xml.etree import ElementTree as ET
import logging
from hsutil import io
from hsutil.files import FileOrPath
from hsutil.path import Path
from hscommon import io
from hscommon.path import Path
from hscommon.util import FileOrPath
from . import fs
@@ -24,7 +25,7 @@ class AlreadyThereError(Exception):
class InvalidPathError(Exception):
"""The path being added is invalid"""
class Directories(object):
class Directories:
#---Override
def __init__(self, fileclasses=[fs.File]):
self._dirs = []
@@ -63,7 +64,9 @@ class Directories(object):
try:
filepaths = set()
if state != STATE_EXCLUDED:
for file in fs.get_files(from_path, fileclasses=self.fileclasses):
found_files = fs.get_files(from_path, fileclasses=self.fileclasses)
logging.debug("Collected {} files in folder {}".format(len(found_files), str(from_path)))
for file in found_files:
file.is_ref = state == STATE_REFERENCE
filepaths.add(file.path)
yield file

View File

@@ -6,7 +6,6 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
import difflib
import itertools
import logging
@@ -14,8 +13,8 @@ import string
from collections import defaultdict, namedtuple
from unicodedata import normalize
from hsutil.misc import flatten
from hsutil.str import multi_replace
from hscommon.util import flatten, multi_replace
from hscommon.trans import tr
from jobprogress import job
(WEIGHT_WORDS,
@@ -25,7 +24,7 @@ NO_FIELD_ORDER) = range(3)
JOB_REFRESH_RATE = 100
def getwords(s):
if isinstance(s, str):
# We decompose the string so that ascii letters with accents can be part of the word.
s = normalize('NFD', s)
s = multi_replace(s, "-_&+():;\\[]{}.,<>/?~!@#$*", ' ').lower()
s = ''.join(c for c in s if c in string.ascii_letters + string.digits + string.whitespace)
@@ -176,7 +175,7 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
match_flags.append(MATCH_SIMILAR_WORDS)
if no_field_order:
match_flags.append(NO_FIELD_ORDER)
j.start_job(len(word_dict), '0 matches found')
j.start_job(len(word_dict), tr("0 matches found"))
compared = defaultdict(set)
result = []
try:
@@ -194,7 +193,7 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
result.append(m)
if len(result) >= LIMIT:
return result
j.add_progress(desc='%d matches found' % len(result))
j.add_progress(desc=tr("%d matches found") % len(result))
except MemoryError:
# This is the place where the memory usage is at its peak during the scan.
# Just continue the process with an incomplete list of matches.
@@ -206,14 +205,14 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
def getmatches_by_contents(files, sizeattr='size', partial=False, j=job.nulljob):
j = j.start_subjob([2, 8])
size2files = defaultdict(set)
for file in j.iter_with_progress(files, 'Read size of %d/%d files'):
for file in j.iter_with_progress(files, tr("Read size of %d/%d files")):
filesize = getattr(file, sizeattr)
if filesize:
size2files[filesize].add(file)
possible_matches = [files for files in size2files.values() if len(files) > 1]
del size2files
result = []
j.start_job(len(possible_matches), '0 matches found')
j.start_job(len(possible_matches), tr("0 matches found"))
for group in possible_matches:
for first, second in itertools.combinations(group, 2):
if first.is_ref and second.is_ref:
@@ -221,7 +220,7 @@ def getmatches_by_contents(files, sizeattr='size', partial=False, j=job.nulljob)
if first.md5partial == second.md5partial:
if partial or first.md5 == second.md5:
result.append(Match(first, second, 100))
j.add_progress(desc='%d matches found' % len(result))
j.add_progress(desc=tr("%d matches found") % len(result))
return result
class Group(object):
@@ -350,7 +349,7 @@ def get_groups(matches, j=job.nulljob):
dupe2group = {}
groups = []
try:
for match in j.iter_with_progress(matches, 'Grouped %d/%d matches', JOB_REFRESH_RATE):
for match in j.iter_with_progress(matches, tr("Grouped %d/%d matches"), JOB_REFRESH_RATE):
first, second, _ = match
first_group = dupe2group.get(first)
second_group = dupe2group.get(second)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2009-10-22
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
@@ -12,14 +11,11 @@
# resulting needless complexity and memory usage. It's been a while since I wanted to do that fork,
# and I'm doing it now.
import hashlib
import logging
from hsutil import io
from hsutil.misc import nonone, flatten
from hsutil.str import get_file_ext
from hscommon import io
from hscommon.util import nonone, flatten, get_file_ext
class FSError(Exception):
cls_message = "An error has occured on '{name}' in '{parent}'"
@@ -52,7 +48,7 @@ class OperationError(FSError):
operation shows that it didn't work."""
cls_message = "Operation on '{name}' failed."
class File(object):
class File:
INITIAL_INFO = {
'size': 0,
'mtime': 0,

View File

@@ -31,7 +31,7 @@ class DetailsPanel(GUIObject):
# we don't want the two sides of the table to display the stats for the same file
ref = group.ref if group is not None and group.ref is not dupe else None
l2 = self.app._get_display_info(ref, group, False)
names = [c['display'] for c in self.app.data.COLUMNS]
names = [c.display for c in self.app.data.COLUMNS]
self._table = list(zip(names, l1, l2))
#--- Public

View File

@@ -7,7 +7,7 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hsgui.tree import Tree, Node
from hscommon.gui.tree import Tree, Node
from ..directories import STATE_NORMAL, STATE_REFERENCE, STATE_EXCLUDED
from .base import GUIObject

View File

@@ -8,7 +8,7 @@
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.notify import Listener
from hsgui.table import GUITable, Row
from hscommon.gui.table import GUITable, Row
class ProblemTable(GUITable, Listener):
def __init__(self, view, problem_dialog):
@@ -31,7 +31,6 @@ class ProblemTable(GUITable, Listener):
#--- Event handlers
def problems_changed(self):
self.refresh()
self.view.refresh()
class ProblemRow(Row):

View File

@@ -9,7 +9,7 @@
from operator import attrgetter
from hsgui.table import GUITable, Row
from hscommon.gui.table import GUITable, Row
from .base import GUIObject
@@ -87,7 +87,6 @@ class ResultTable(GUIObject, GUITable):
def _refresh_with_view(self):
self.refresh()
self.view.refresh()
self.view.show_selected_row()
#--- Public
@@ -139,7 +138,6 @@ class ResultTable(GUIObject, GUITable):
return
self._delta_values = value
self.refresh()
self.view.refresh()
@property
def selected_dupe_count(self):
@@ -156,7 +154,7 @@ class ResultTable(GUIObject, GUITable):
# What we want to to here is that instead of restoring selected *dupes* after refresh, we
# restore selected *paths*.
indexes = self.selected_indexes
self.refresh()
self.refresh(refresh_view=False)
self.select(indexes)
self.view.refresh()

View File

@@ -8,9 +8,9 @@
from xml.etree import ElementTree as ET
from hsutil.files import FileOrPath
from hscommon.util import FileOrPath
class IgnoreList(object):
class IgnoreList:
"""An ignore list implementation that is iterable, filterable and exportable to XML.
Call Ignore to add an ignore list entry, and AreIgnore to check if 2 items are in the list.

View File

@@ -13,9 +13,8 @@ from xml.etree import ElementTree as ET
from . import engine
from jobprogress.job import nulljob
from hscommon.markable import Markable
from hsutil.misc import flatten, nonone
from hsutil.str import format_size
from hsutil.files import FileOrPath
from hscommon.util import flatten, nonone, FileOrPath, format_size
from hscommon.trans import tr
class Results(Markable):
#---Override
@@ -89,14 +88,14 @@ class Results(Markable):
total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe))
if self.mark_inverted:
marked_size = self.__total_size - marked_size
result = '%d / %d (%s / %s) duplicates marked.' % (
result = tr("%d / %d (%s / %s) duplicates marked.") % (
mark_count,
total_count,
format_size(marked_size, 2),
format_size(total_size, 2),
)
if self.__filters:
result += ' filter: %s' % ' --> '.join(self.__filters)
result += tr(" filter: %s") % ' --> '.join(self.__filters)
return result
def __recalculate_stats(self):
@@ -116,7 +115,7 @@ class Results(Markable):
self.__group_of_duplicate[dupe] = g
if not hasattr(dupe, 'is_ref'):
dupe.is_ref = False
self.is_modified = True
self.is_modified = bool(self.__groups)
old_filters = nonone(self.__filters, [])
self.apply_filter(None)
for filter_str in old_filters:
@@ -273,7 +272,7 @@ class Results(Markable):
for group in affected_groups:
group.discard_matches()
self.__dupes = None
self.is_modified = True
self.is_modified = bool(self.__groups)
def save_to_xml(self, outfile):
self.apply_filter(None)

View File

@@ -10,9 +10,9 @@ import logging
import re
from jobprogress import job
from hsutil import io
from hsutil.misc import dedupe
from hsutil.str import get_file_ext, rem_file_ext
from hscommon import io
from hscommon.util import dedupe, rem_file_ext, get_file_ext
from hscommon.trans import tr
from . import engine
from .ignore import IgnoreList
@@ -37,7 +37,7 @@ def is_same_with_digit(name, refname):
end = name[len(refname):].strip()
return RE_DIGIT_ENDING.match(end) is not None
class Scanner(object):
class Scanner:
def __init__(self):
self.ignore_list = IgnoreList()
self.discarded_file_count = 0
@@ -45,7 +45,7 @@ class Scanner(object):
def _getmatches(self, files, j):
if self.size_threshold:
j = j.start_subjob([2, 8])
for f in j.iter_with_progress(files, 'Read size of %d/%d files'):
for f in j.iter_with_progress(files, tr("Read size of %d/%d files")):
f.size # pre-read, makes a smoother progress if read here (especially for bundles)
files = [f for f in files if f.size >= self.size_threshold]
if self.scan_type in (ScanType.Contents, ScanType.ContentsAudio):
@@ -65,7 +65,8 @@ class Scanner(object):
ScanType.Fields: lambda f: engine.getfields(rem_file_ext(f.name)),
ScanType.Tag: lambda f: [engine.getwords(str(getattr(f, attrname))) for attrname in SCANNABLE_TAGS if attrname in self.scanned_tags],
}[self.scan_type]
for f in j.iter_with_progress(files, 'Read metadata of %d/%d files'):
for f in j.iter_with_progress(files, tr("Read metadata of %d/%d files")):
logging.debug("Reading metadata of {}".format(str(f.path)))
f.words = func(f)
return engine.getmatches(files, j=j, **kw)
@@ -94,13 +95,13 @@ class Scanner(object):
logging.info('Getting matches')
matches = self._getmatches(files, j)
logging.info('Found %d matches' % len(matches))
j.set_progress(100, 'Removing false matches')
j.set_progress(100, tr("Removing false matches"))
if not self.mix_file_kind:
matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
matches = [m for m in matches if io.exists(m.first.path) and io.exists(m.second.path)]
if self.ignore_list:
j = j.start_subjob(2)
iter_matches = j.iter_with_progress(matches, 'Processed %d/%d matches against the ignore list')
iter_matches = j.iter_with_progress(matches, tr("Processed %d/%d matches against the ignore list"))
matches = [m for m in iter_matches
if not self.ignore_list.AreIgnored(str(m.first.path), str(m.second.path))]
logging.info('Grouping matches')
@@ -109,7 +110,7 @@ class Scanner(object):
self.discarded_file_count = len(matched_files) - sum(len(g) for g in groups)
groups = [g for g in groups if any(not f.is_ref for f in g)]
logging.info('Created %d groups' % len(groups))
j.set_progress(100, 'Doing group prioritization')
j.set_progress(100, tr("Doing group prioritization"))
for g in groups:
g.prioritize(self._key_func, self._tie_breaker)
return groups

View File

@@ -7,15 +7,16 @@
# http://www.hardcoded.net/licenses/bsd_license
import os
import os.path as op
import logging
from hsutil.testutil import eq_
from hsutil.testcase import TestCase
from hsutil import io
from hsutil.path import Path
from hsutil.decorators import log_calls
import hsutil.files
from jobprogress.job import nulljob
from pytest import mark
from hscommon import io
from hscommon.path import Path
import hscommon.conflict
import hscommon.util
from hscommon.testutil import CallLogger, eq_, log_calls
from jobprogress.job import nulljob, Job, JobCancelled
from . import data
from .results_test import GetTestGroups
@@ -27,86 +28,85 @@ from ..gui.result_table import ResultTable
from ..scanner import ScanType
class DupeGuru(DupeGuruBase):
JOB = nulljob
def __init__(self):
DupeGuruBase.__init__(self, data, '/tmp')
def _start_job(self, jobid, func, *args):
func(nulljob, *args)
try:
func(self.JOB, *args)
except JobCancelled:
return
def _get_default(self, key_name):
return None
def _set_default(self, key_name, value):
pass
class CallLogger(object):
"""This is a dummy object that logs all calls made to it.
def add_fake_files_to_directories(directories, files):
directories.get_files = lambda: iter(files)
directories._dirs.append('this is just so Scan() doesnt return 3')
It is used to simulate the GUI layer.
"""
def __init__(self):
self.calls = []
class TestCaseDupeGuru:
def test_apply_filter_calls_results_apply_filter(self, monkeypatch):
dgapp = DupeGuru()
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
dgapp.apply_filter('foo')
eq_(2, len(dgapp.results.apply_filter.calls))
call = dgapp.results.apply_filter.calls[0]
assert call['filter_str'] is None
call = dgapp.results.apply_filter.calls[1]
eq_('foo', call['filter_str'])
def __getattr__(self, func_name):
def func(*args, **kw):
self.calls.append(func_name)
return func
def test_apply_filter_escapes_regexp(self, monkeypatch):
dgapp = DupeGuru()
monkeypatch.setattr(dgapp.results, 'apply_filter', log_calls(dgapp.results.apply_filter))
dgapp.apply_filter('()[]\\.|+?^abc')
call = dgapp.results.apply_filter.calls[1]
eq_('\\(\\)\\[\\]\\\\\\.\\|\\+\\?\\^abc', call['filter_str'])
dgapp.apply_filter('(*)') # In "simple mode", we want the * to behave as a wilcard
call = dgapp.results.apply_filter.calls[3]
eq_('\(.*\)', call['filter_str'])
dgapp.options['escape_filter_regexp'] = False
dgapp.apply_filter('(abc)')
call = dgapp.results.apply_filter.calls[5]
eq_('(abc)', call['filter_str'])
def clear_calls(self):
del self.calls[:]
class TCDupeGuru(TestCase):
cls_tested_module = app
def test_apply_filter_calls_results_apply_filter(self):
app = DupeGuru()
self.mock(app.results, 'apply_filter', log_calls(app.results.apply_filter))
app.apply_filter('foo')
self.assertEqual(2, len(app.results.apply_filter.calls))
call = app.results.apply_filter.calls[0]
self.assert_(call['filter_str'] is None)
call = app.results.apply_filter.calls[1]
self.assertEqual('foo', call['filter_str'])
def test_apply_filter_escapes_regexp(self):
app = DupeGuru()
self.mock(app.results, 'apply_filter', log_calls(app.results.apply_filter))
app.apply_filter('()[]\\.|+?^abc')
call = app.results.apply_filter.calls[1]
self.assertEqual('\\(\\)\\[\\]\\\\\\.\\|\\+\\?\\^abc', call['filter_str'])
app.apply_filter('(*)') # In "simple mode", we want the * to behave as a wilcard
call = app.results.apply_filter.calls[3]
self.assertEqual('\(.*\)', call['filter_str'])
app.options['escape_filter_regexp'] = False
app.apply_filter('(abc)')
call = app.results.apply_filter.calls[5]
self.assertEqual('(abc)', call['filter_str'])
def test_copy_or_move(self):
def test_copy_or_move(self, tmpdir, monkeypatch):
# The goal here is just to have a test for a previous blowup I had. I know my test coverage
# for this unit is pathetic. What's done is done. My approach now is to add tests for
# every change I want to make. The blowup was caused by a missing import.
p = self.tmppath()
p = Path(str(tmpdir))
io.open(p + 'foo', 'w').close()
self.mock(hsutil.files, 'copy', log_calls(lambda source_path, dest_path: None))
self.mock(os, 'makedirs', lambda path: None) # We don't want the test to create that fake directory
app = DupeGuru()
app.directories.add_path(p)
[f] = app.directories.get_files()
app.copy_or_move(f, True, 'some_destination', 0)
self.assertEqual(1, len(hsutil.files.copy.calls))
call = hsutil.files.copy.calls[0]
self.assertEqual('some_destination', call['dest_path'])
self.assertEqual(f.path, call['source_path'])
monkeypatch.setattr(hscommon.conflict, 'smart_copy', log_calls(lambda source_path, dest_path: None))
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
monkeypatch.setattr(app, 'smart_copy', hscommon.conflict.smart_copy)
monkeypatch.setattr(os, 'makedirs', lambda path: None) # We don't want the test to create that fake directory
dgapp = DupeGuru()
dgapp.directories.add_path(p)
[f] = dgapp.directories.get_files()
dgapp.copy_or_move(f, True, 'some_destination', 0)
eq_(1, len(hscommon.conflict.smart_copy.calls))
call = hscommon.conflict.smart_copy.calls[0]
eq_('some_destination', call['dest_path'])
eq_(f.path, call['source_path'])
def test_copy_or_move_clean_empty_dirs(self):
tmppath = Path(self.tmpdir())
def test_copy_or_move_clean_empty_dirs(self, tmpdir, monkeypatch):
tmppath = Path(str(tmpdir))
sourcepath = tmppath + 'source'
io.mkdir(sourcepath)
io.open(sourcepath + 'myfile', 'w')
app = DupeGuru()
app.directories.add_path(tmppath)
[myfile] = app.directories.get_files()
self.mock(app, 'clean_empty_dirs', log_calls(lambda path: None))
monkeypatch.setattr(app, 'clean_empty_dirs', log_calls(lambda path: None))
app.copy_or_move(myfile, False, tmppath + 'dest', 0)
calls = app.clean_empty_dirs.calls
self.assertEqual(1, len(calls))
self.assertEqual(sourcepath, calls[0]['path'])
eq_(1, len(calls))
eq_(sourcepath, calls[0]['path'])
def test_Scan_with_objects_evaluating_to_false(self):
class FakeFile(fs.File):
@@ -119,14 +119,14 @@ class TCDupeGuru(TestCase):
f1, f2 = [FakeFile('foo') for i in range(2)]
f1.is_ref, f2.is_ref = (False, False)
assert not (bool(f1) and bool(f2))
app.directories.get_files = lambda: iter([f1, f2])
app.directories._dirs.append('this is just so Scan() doesnt return 3')
add_fake_files_to_directories(app.directories, [f1, f2])
app.start_scanning() # no exception
def test_ignore_hardlink_matches(self):
@mark.skipif("not hasattr(os, 'link')")
def test_ignore_hardlink_matches(self, tmpdir):
# If the ignore_hardlink_matches option is set, don't match files hardlinking to the same
# inode.
tmppath = Path(self.tmpdir())
tmppath = Path(str(tmpdir))
io.open(tmppath + 'myfile', 'w').write('foo')
os.link(str(tmppath + 'myfile'), str(tmppath + 'hardlink'))
app = DupeGuru()
@@ -137,42 +137,46 @@ class TCDupeGuru(TestCase):
eq_(len(app.results.groups), 0)
class TCDupeGuru_clean_empty_dirs(TestCase):
cls_tested_module = app
def setUp(self):
self.mock(hsutil.files, 'delete_if_empty', log_calls(lambda path, files_to_delete=[]: None))
class TestCaseDupeGuru_clean_empty_dirs:
def pytest_funcarg__do_setup(self, request):
monkeypatch = request.getfuncargvalue('monkeypatch')
monkeypatch.setattr(hscommon.util, 'delete_if_empty', log_calls(lambda path, files_to_delete=[]: None))
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
monkeypatch.setattr(app, 'delete_if_empty', hscommon.util.delete_if_empty)
self.app = DupeGuru()
def test_option_off(self):
def test_option_off(self, do_setup):
self.app.clean_empty_dirs(Path('/foo/bar'))
self.assertEqual(0, len(hsutil.files.delete_if_empty.calls))
eq_(0, len(hscommon.util.delete_if_empty.calls))
def test_option_on(self):
def test_option_on(self, do_setup):
self.app.options['clean_empty_dirs'] = True
self.app.clean_empty_dirs(Path('/foo/bar'))
calls = hsutil.files.delete_if_empty.calls
self.assertEqual(1, len(calls))
self.assertEqual(Path('/foo/bar'), calls[0]['path'])
self.assertEqual(['.DS_Store'], calls[0]['files_to_delete'])
calls = hscommon.util.delete_if_empty.calls
eq_(1, len(calls))
eq_(Path('/foo/bar'), calls[0]['path'])
eq_(['.DS_Store'], calls[0]['files_to_delete'])
def test_recurse_up(self):
def test_recurse_up(self, do_setup, monkeypatch):
# delete_if_empty must be recursively called up in the path until it returns False
@log_calls
def mock_delete_if_empty(path, files_to_delete=[]):
return len(path) > 1
self.mock(hsutil.files, 'delete_if_empty', mock_delete_if_empty)
monkeypatch.setattr(hscommon.util, 'delete_if_empty', mock_delete_if_empty)
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
monkeypatch.setattr(app, 'delete_if_empty', mock_delete_if_empty)
self.app.options['clean_empty_dirs'] = True
self.app.clean_empty_dirs(Path('not-empty/empty/empty'))
calls = hsutil.files.delete_if_empty.calls
self.assertEqual(3, len(calls))
self.assertEqual(Path('not-empty/empty/empty'), calls[0]['path'])
self.assertEqual(Path('not-empty/empty'), calls[1]['path'])
self.assertEqual(Path('not-empty'), calls[2]['path'])
calls = hscommon.util.delete_if_empty.calls
eq_(3, len(calls))
eq_(Path('not-empty/empty/empty'), calls[0]['path'])
eq_(Path('not-empty/empty'), calls[1]['path'])
eq_(Path('not-empty'), calls[2]['path'])
class TCDupeGuruWithResults(TestCase):
def setUp(self):
class TestCaseDupeGuruWithResults:
def pytest_funcarg__do_setup(self, request):
self.app = DupeGuru()
self.objects,self.matches,self.groups = GetTestGroups()
self.app.results.groups = self.groups
@@ -185,50 +189,13 @@ class TCDupeGuruWithResults(TestCase):
self.dpanel.connect()
self.dtree.connect()
self.rtable.connect()
tmppath = self.tmppath()
tmpdir = request.getfuncargvalue('tmpdir')
tmppath = Path(str(tmpdir))
io.mkdir(tmppath + 'foo')
io.mkdir(tmppath + 'bar')
self.app.directories.add_path(tmppath)
def check_gui_calls(self, gui, expected, verify_order=False):
"""Checks that the expected calls have been made to 'gui', then clears the log.
`expected` is an iterable of strings representing method names.
If `verify_order` is True, the order of the calls matters.
"""
if verify_order:
eq_(gui.calls, expected)
else:
eq_(set(gui.calls), set(expected))
gui.clear_calls()
def check_gui_calls_partial(self, gui, expected=None, not_expected=None):
"""Checks that the expected calls have been made to 'gui', then clears the log.
`expected` is an iterable of strings representing method names. Order doesn't matter.
Moreover, if calls have been made that are not in expected, no failure occur.
`not_expected` can be used for a more explicit check (rather than calling `check_gui_calls`
with an empty `expected`) to assert that calls have *not* been made.
"""
calls = set(gui.calls)
if expected is not None:
expected = set(expected)
not_called = expected - calls
assert not not_called, "These calls haven't been made: {0}".format(not_called)
if not_expected is not None:
not_expected = set(not_expected)
called = not_expected & calls
assert not called, "These calls shouldn't have been made: {0}".format(called)
gui.clear_calls()
def clear_gui_calls(self):
for attr in dir(self):
if attr.endswith('_gui'):
gui = getattr(self, attr)
if hasattr(gui, 'calls'): # We might have test methods ending with '_gui'
gui.clear_calls()
def test_GetObjects(self):
def test_GetObjects(self, do_setup):
objects = self.objects
groups = self.groups
r = self.rtable[0]
@@ -241,7 +208,7 @@ class TCDupeGuruWithResults(TestCase):
assert r._group is groups[1]
assert r._dupe is objects[4]
def test_GetObjects_after_sort(self):
def test_GetObjects_after_sort(self, do_setup):
objects = self.objects
groups = self.groups[:] # we need an un-sorted reference
self.rtable.sort(0, False) #0 = Filename
@@ -249,14 +216,14 @@ class TCDupeGuruWithResults(TestCase):
assert r._group is groups[1]
assert r._dupe is objects[4]
def test_selected_result_node_paths_after_deletion(self):
def test_selected_result_node_paths_after_deletion(self, do_setup):
# cases where the selected dupes aren't there are correctly handled
self.rtable.select([1, 2, 3])
self.app.remove_selected()
# The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos.
eq_(self.rtable.selected_indexes, [1]) # no exception
def test_selectResultNodePaths(self):
def test_selectResultNodePaths(self, do_setup):
app = self.app
objects = self.objects
self.rtable.select([1, 2])
@@ -264,7 +231,7 @@ class TCDupeGuruWithResults(TestCase):
assert app.selected_dupes[0] is objects[1]
assert app.selected_dupes[1] is objects[2]
def test_selectResultNodePaths_with_ref(self):
def test_selectResultNodePaths_with_ref(self, do_setup):
app = self.app
objects = self.objects
self.rtable.select([1, 2, 3])
@@ -273,7 +240,7 @@ class TCDupeGuruWithResults(TestCase):
assert app.selected_dupes[1] is objects[2]
assert app.selected_dupes[2] is self.groups[1].ref
def test_selectResultNodePaths_after_sort(self):
def test_selectResultNodePaths_after_sort(self, do_setup):
app = self.app
objects = self.objects
groups = self.groups[:] #To keep the old order in memory
@@ -285,25 +252,22 @@ class TCDupeGuruWithResults(TestCase):
assert app.selected_dupes[1] is groups[0].ref
assert app.selected_dupes[2] is objects[1]
def test_selected_powermarker_node_paths(self):
def test_selected_powermarker_node_paths(self, do_setup):
# app.selected_dupes is correctly converted into paths
app = self.app
objects = self.objects
self.rtable.power_marker = True
self.rtable.select([0, 1, 2])
self.rtable.power_marker = False
eq_(self.rtable.selected_indexes, [1, 2, 4])
def test_selected_powermarker_node_paths_after_deletion(self):
def test_selected_powermarker_node_paths_after_deletion(self, do_setup):
# cases where the selected dupes aren't there are correctly handled
app = self.app
objects = self.objects
self.rtable.power_marker = True
self.rtable.select([0, 1, 2])
app.remove_selected()
eq_(self.rtable.selected_indexes, []) # no exception
def test_selectPowerMarkerRows_after_sort(self):
def test_selectPowerMarkerRows_after_sort(self, do_setup):
app = self.app
objects = self.objects
self.rtable.power_marker = True
@@ -314,7 +278,7 @@ class TCDupeGuruWithResults(TestCase):
assert app.selected_dupes[1] is objects[2]
assert app.selected_dupes[2] is objects[1]
def test_toggleSelectedMark(self):
def test_toggleSelectedMark(self, do_setup):
app = self.app
objects = self.objects
app.toggle_selected_mark_state()
@@ -328,15 +292,15 @@ class TCDupeGuruWithResults(TestCase):
assert not app.results.is_marked(objects[3])
assert app.results.is_marked(objects[4])
def test_refreshDetailsWithSelected(self):
def test_refreshDetailsWithSelected(self, do_setup):
self.rtable.select([1, 4])
eq_(self.dpanel.row(0), ('Filename', 'bar bleh', 'foo bar'))
self.check_gui_calls(self.dpanel_gui, ['refresh'])
self.dpanel_gui.check_gui_calls(['refresh'])
self.rtable.select([])
eq_(self.dpanel.row(0), ('Filename', '---', '---'))
self.check_gui_calls(self.dpanel_gui, ['refresh'])
self.dpanel_gui.check_gui_calls(['refresh'])
def test_makeSelectedReference(self):
def test_makeSelectedReference(self, do_setup):
app = self.app
objects = self.objects
groups = self.groups
@@ -345,7 +309,7 @@ class TCDupeGuruWithResults(TestCase):
assert groups[0].ref is objects[1]
assert groups[1].ref is objects[4]
def test_makeSelectedReference_by_selecting_two_dupes_in_the_same_group(self):
def test_makeSelectedReference_by_selecting_two_dupes_in_the_same_group(self, do_setup):
app = self.app
objects = self.objects
groups = self.groups
@@ -355,7 +319,7 @@ class TCDupeGuruWithResults(TestCase):
assert groups[0].ref is objects[1]
assert groups[1].ref is objects[4]
def test_removeSelected(self):
def test_removeSelected(self, do_setup):
app = self.app
self.rtable.select([1, 4])
app.remove_selected()
@@ -363,22 +327,25 @@ class TCDupeGuruWithResults(TestCase):
app.remove_selected()
eq_(len(app.results.dupes), 0)
def test_addDirectory_simple(self):
def test_addDirectory_simple(self, do_setup):
# There's already a directory in self.app, so adding another once makes 2 of em
app = self.app
eq_(app.add_directory(self.datadirpath()), 0)
# any other path that isn't a parent or child of the already added path
otherpath = Path(op.dirname(__file__))
eq_(app.add_directory(otherpath), 0)
eq_(len(app.directories), 2)
def test_addDirectory_already_there(self):
def test_addDirectory_already_there(self, do_setup):
app = self.app
self.assertEqual(0,app.add_directory(self.datadirpath()))
self.assertEqual(1,app.add_directory(self.datadirpath()))
otherpath = Path(op.dirname(__file__))
eq_(app.add_directory(otherpath), 0)
eq_(app.add_directory(otherpath), 1)
def test_addDirectory_does_not_exist(self):
def test_addDirectory_does_not_exist(self, do_setup):
app = self.app
self.assertEqual(2,app.add_directory('/does_not_exist'))
eq_(2,app.add_directory('/does_not_exist'))
def test_ignore(self):
def test_ignore(self, do_setup):
app = self.app
self.rtable.select([4]) #The dupe of the second, 2 sized group
app.add_selected_to_ignore_list()
@@ -388,20 +355,22 @@ class TCDupeGuruWithResults(TestCase):
#BOTH the ref and the other dupe should have been added
eq_(len(app.scanner.ignore_list), 3)
def test_purgeIgnoreList(self):
def test_purgeIgnoreList(self, do_setup, tmpdir):
app = self.app
p1 = self.filepath('zerofile')
p2 = self.filepath('zerofill')
p1 = str(tmpdir.join('file1'))
p2 = str(tmpdir.join('file2'))
open(p1, 'w').close()
open(p2, 'w').close()
dne = '/does_not_exist'
app.scanner.ignore_list.Ignore(dne,p1)
app.scanner.ignore_list.Ignore(p2,dne)
app.scanner.ignore_list.Ignore(p1,p2)
app.purge_ignore_list()
self.assertEqual(1,len(app.scanner.ignore_list))
self.assert_(app.scanner.ignore_list.AreIgnored(p1,p2))
self.assert_(not app.scanner.ignore_list.AreIgnored(dne,p1))
eq_(1,len(app.scanner.ignore_list))
assert app.scanner.ignore_list.AreIgnored(p1,p2)
assert not app.scanner.ignore_list.AreIgnored(dne,p1)
def test_only_unicode_is_added_to_ignore_list(self):
def test_only_unicode_is_added_to_ignore_list(self, do_setup):
def FakeIgnore(first,second):
if not isinstance(first,str):
self.fail()
@@ -413,10 +382,19 @@ class TCDupeGuruWithResults(TestCase):
self.rtable.select([4])
app.add_selected_to_ignore_list()
def test_cancel_scan_with_previous_results(self, do_setup):
# When doing a scan with results being present prior to the scan, correctly invalidate the
# results table.
app = self.app
app.JOB = Job(1, lambda *args, **kw: False) # Cancels the task
add_fake_files_to_directories(app.directories, self.objects) # We want the scan to at least start
app.start_scanning() # will be cancelled immediately
eq_(len(self.rtable), 0)
class TCDupeGuru_renameSelected(TestCase):
def setUp(self):
p = self.tmppath()
class TestCaseDupeGuru_renameSelected:
def pytest_funcarg__do_setup(self, request):
tmpdir = request.getfuncargvalue('tmpdir')
p = Path(str(tmpdir))
fp = open(str(p + 'foo bar 1'),mode='w')
fp.close()
fp = open(str(p + 'foo bar 2'),mode='w')
@@ -438,7 +416,7 @@ class TCDupeGuru_renameSelected(TestCase):
self.rtable = ResultTable(self.rtable_gui, self.app)
self.rtable.connect()
def test_simple(self):
def test_simple(self, do_setup):
app = self.app
g = self.groups[0]
self.rtable.select([1])
@@ -448,11 +426,11 @@ class TCDupeGuru_renameSelected(TestCase):
assert 'foo bar 2' not in names
eq_(g.dupes[0].name, 'renamed')
def test_none_selected(self):
def test_none_selected(self, do_setup, monkeypatch):
app = self.app
g = self.groups[0]
self.rtable.select([])
self.mock(logging, 'warning', log_calls(lambda msg: None))
monkeypatch.setattr(logging, 'warning', log_calls(lambda msg: None))
assert not app.rename_selected('renamed')
msg = logging.warning.calls[0]['msg']
eq_('dupeGuru Warning: list index out of range', msg)
@@ -461,11 +439,11 @@ class TCDupeGuru_renameSelected(TestCase):
assert 'foo bar 2' in names
eq_(g.dupes[0].name, 'foo bar 2')
def test_name_already_exists(self):
def test_name_already_exists(self, do_setup, monkeypatch):
app = self.app
g = self.groups[0]
self.rtable.select([1])
self.mock(logging, 'warning', log_calls(lambda msg: None))
monkeypatch.setattr(logging, 'warning', log_calls(lambda msg: None))
assert not app.rename_selected('foo bar 1')
msg = logging.warning.calls[0]['msg']
assert msg.startswith('dupeGuru Warning: \'foo bar 1\' already exists in')

View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-07-11
# Copyright 2010 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
# This unit is required to make tests work with py.test. When running
import py
def get_testunit(item):
if hasattr(item, 'obj'):
testunit = py.builtin._getimself(item.obj)
if hasattr(testunit, 'global_setup'):
return testunit
def pytest_runtest_setup(item):
testunit = get_testunit(item)
if testunit is not None:
testunit.global_setup()
def pytest_runtest_teardown(item):
testunit = get_testunit(item)
if testunit is not None:
testunit.global_teardown()

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2009-10-23
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
@@ -9,17 +8,18 @@
# data module for tests
from hsutil.str import format_size
from ..data import format_path, cmp_value
from hscommon.util import format_size
from ..data import format_path, cmp_value, Column
COLUMNS = [
{'attr':'name','display':'Filename'},
{'attr':'path','display':'Directory'},
{'attr':'size','display':'Size (KB)'},
{'attr':'extension','display':'Kind'},
Column('name', 'Filename'),
Column('path', 'Directory'),
Column('size', 'Size (KB)'),
Column('extension', 'Kind'),
]
METADATA_TO_READ = ['size']
DELTA_COLUMNS = {2,}
def GetDisplayInfo(dupe, group, delta):
size = dupe.size
@@ -35,10 +35,10 @@ def GetDisplayInfo(dupe, group, delta):
]
def GetDupeSortKey(dupe, get_group, key, delta):
r = cmp_value(getattr(dupe, COLUMNS[key]['attr']))
if delta and (key == 2):
r -= cmp_value(getattr(get_group().ref, COLUMNS[key]['attr']))
r = cmp_value(getattr(dupe, COLUMNS[key].attr))
if delta and (key in DELTA_COLUMNS):
r -= cmp_value(getattr(get_group().ref, COLUMNS[key].attr))
return r
def GetGroupSortKey(group, key):
return cmp_value(getattr(group.ref, COLUMNS[key]['attr']))
return cmp_value(getattr(group.ref, COLUMNS[key].attr))

View File

@@ -6,20 +6,20 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
import os.path as op
import os
import time
import tempfile
import shutil
from hsutil import io
from hsutil.path import Path
from hsutil.testutil import eq_
from hsutil.testcase import TestCase
from pytest import raises
from hscommon import io
from hscommon.path import Path
from hscommon.testutil import eq_
from ..directories import *
testpath = Path(TestCase.datadirpath())
def create_fake_fs(rootpath):
# We have it as a separate function because other units are using it.
rootpath = rootpath + 'fs'
io.mkdir(rootpath)
io.mkdir(rootpath + 'dir1')
@@ -45,215 +45,235 @@ def create_fake_fs(rootpath):
fp.close()
return rootpath
class TCDirectories(TestCase):
def test_empty(self):
d = Directories()
self.assertEqual(0,len(d))
self.assert_('foobar' not in d)
def setup_module(module):
# In this unit, we have tests depending on two directory structure. One with only one file in it
# and another with a more complex structure.
testpath = Path(tempfile.mkdtemp())
module.testpath = testpath
rootpath = testpath + 'onefile'
io.mkdir(rootpath)
fp = io.open(rootpath + 'test.txt', 'w')
fp.write('test_data')
fp.close()
create_fake_fs(testpath)
def test_add_path(self):
d = Directories()
p = testpath + 'utils'
d.add_path(p)
self.assertEqual(1,len(d))
self.assert_(p in d)
self.assert_((p + 'foobar') in d)
self.assert_(p[:-1] not in d)
p = self.tmppath()
d.add_path(p)
self.assertEqual(2,len(d))
self.assert_(p in d)
def teardown_module(module):
shutil.rmtree(str(module.testpath))
def test_AddPath_when_path_is_already_there(self):
def test_empty():
d = Directories()
p = testpath + 'utils'
d.add_path(p)
self.assertRaises(AlreadyThereError, d.add_path, p)
self.assertRaises(AlreadyThereError, d.add_path, p + 'foobar')
self.assertEqual(1, len(d))
eq_(len(d), 0)
assert 'foobar' not in d
def test_add_path_containing_paths_already_there(self):
def test_add_path():
d = Directories()
d.add_path(testpath + 'utils')
self.assertEqual(1, len(d))
p = testpath + 'onefile'
d.add_path(p)
eq_(1,len(d))
assert p in d
assert (p + 'foobar') in d
assert p[:-1] not in d
p = testpath + 'fs'
d.add_path(p)
eq_(2,len(d))
assert p in d
def test_AddPath_when_path_is_already_there():
d = Directories()
p = testpath + 'onefile'
d.add_path(p)
with raises(AlreadyThereError):
d.add_path(p)
with raises(AlreadyThereError):
d.add_path(p + 'foobar')
eq_(1, len(d))
def test_add_path_containing_paths_already_there():
d = Directories()
d.add_path(testpath + 'onefile')
eq_(1, len(d))
d.add_path(testpath)
eq_(len(d), 1)
eq_(d[0], testpath)
def test_AddPath_non_latin(self):
p = Path(self.tmpdir())
def test_AddPath_non_latin(tmpdir):
p = Path(str(tmpdir))
to_add = p + 'unicode\u201a'
os.mkdir(str(to_add))
d = Directories()
try:
d.add_path(to_add)
except UnicodeDecodeError:
self.fail()
assert False
def test_del(self):
def test_del():
d = Directories()
d.add_path(testpath + 'utils')
d.add_path(testpath + 'onefile')
try:
del d[1]
self.fail()
assert False
except IndexError:
pass
d.add_path(self.tmppath())
d.add_path(testpath + 'fs')
del d[1]
self.assertEqual(1, len(d))
eq_(1, len(d))
def test_states(self):
def test_states():
d = Directories()
p = testpath + 'utils'
p = testpath + 'onefile'
d.add_path(p)
self.assertEqual(STATE_NORMAL,d.get_state(p))
eq_(STATE_NORMAL,d.get_state(p))
d.set_state(p,STATE_REFERENCE)
self.assertEqual(STATE_REFERENCE,d.get_state(p))
self.assertEqual(STATE_REFERENCE,d.get_state(p + 'dir1'))
self.assertEqual(1,len(d.states))
self.assertEqual(p,list(d.states.keys())[0])
self.assertEqual(STATE_REFERENCE,d.states[p])
eq_(STATE_REFERENCE,d.get_state(p))
eq_(STATE_REFERENCE,d.get_state(p + 'dir1'))
eq_(1,len(d.states))
eq_(p,list(d.states.keys())[0])
eq_(STATE_REFERENCE,d.states[p])
def test_get_state_with_path_not_there(self):
def test_get_state_with_path_not_there():
# When the path's not there, just return STATE_NORMAL
d = Directories()
d.add_path(testpath + 'utils')
d.add_path(testpath + 'onefile')
eq_(d.get_state(testpath), STATE_NORMAL)
def test_states_remain_when_larger_directory_eat_smaller_ones(self):
def test_states_remain_when_larger_directory_eat_smaller_ones():
d = Directories()
p = testpath + 'utils'
p = testpath + 'onefile'
d.add_path(p)
d.set_state(p,STATE_EXCLUDED)
d.add_path(testpath)
d.set_state(testpath,STATE_REFERENCE)
self.assertEqual(STATE_EXCLUDED,d.get_state(p))
self.assertEqual(STATE_EXCLUDED,d.get_state(p + 'dir1'))
self.assertEqual(STATE_REFERENCE,d.get_state(testpath))
eq_(STATE_EXCLUDED,d.get_state(p))
eq_(STATE_EXCLUDED,d.get_state(p + 'dir1'))
eq_(STATE_REFERENCE,d.get_state(testpath))
def test_set_state_keep_state_dict_size_to_minimum(self):
def test_set_state_keep_state_dict_size_to_minimum():
d = Directories()
p = create_fake_fs(self.tmppath())
p = testpath + 'fs'
d.add_path(p)
d.set_state(p,STATE_REFERENCE)
d.set_state(p + 'dir1',STATE_REFERENCE)
self.assertEqual(1,len(d.states))
self.assertEqual(STATE_REFERENCE,d.get_state(p + 'dir1'))
eq_(1,len(d.states))
eq_(STATE_REFERENCE,d.get_state(p + 'dir1'))
d.set_state(p + 'dir1',STATE_NORMAL)
self.assertEqual(2,len(d.states))
self.assertEqual(STATE_NORMAL,d.get_state(p + 'dir1'))
eq_(2,len(d.states))
eq_(STATE_NORMAL,d.get_state(p + 'dir1'))
d.set_state(p + 'dir1',STATE_REFERENCE)
self.assertEqual(1,len(d.states))
self.assertEqual(STATE_REFERENCE,d.get_state(p + 'dir1'))
eq_(1,len(d.states))
eq_(STATE_REFERENCE,d.get_state(p + 'dir1'))
def test_get_files(self):
def test_get_files():
d = Directories()
p = create_fake_fs(self.tmppath())
p = testpath + 'fs'
d.add_path(p)
d.set_state(p + 'dir1',STATE_REFERENCE)
d.set_state(p + 'dir2',STATE_EXCLUDED)
files = list(d.get_files())
self.assertEqual(5, len(files))
eq_(5, len(files))
for f in files:
if f.path[:-1] == p + 'dir1':
assert f.is_ref
else:
assert not f.is_ref
def test_get_files_with_inherited_exclusion(self):
def test_get_files_with_inherited_exclusion():
d = Directories()
p = testpath + 'utils'
p = testpath + 'onefile'
d.add_path(p)
d.set_state(p,STATE_EXCLUDED)
self.assertEqual([], list(d.get_files()))
eq_([], list(d.get_files()))
def test_save_and_load(self):
def test_save_and_load(tmpdir):
d1 = Directories()
d2 = Directories()
p1 = self.tmppath()
p2 = self.tmppath()
p1 = Path(str(tmpdir.join('p1')))
io.mkdir(p1)
p2 = Path(str(tmpdir.join('p2')))
io.mkdir(p2)
d1.add_path(p1)
d1.add_path(p2)
d1.set_state(p1, STATE_REFERENCE)
d1.set_state(p1 + 'dir1',STATE_EXCLUDED)
tmpxml = op.join(self.tmpdir(), 'directories_testunit.xml')
tmpxml = str(tmpdir.join('directories_testunit.xml'))
d1.save_to_file(tmpxml)
d2.load_from_file(tmpxml)
self.assertEqual(2, len(d2))
self.assertEqual(STATE_REFERENCE,d2.get_state(p1))
self.assertEqual(STATE_EXCLUDED,d2.get_state(p1 + 'dir1'))
eq_(2, len(d2))
eq_(STATE_REFERENCE,d2.get_state(p1))
eq_(STATE_EXCLUDED,d2.get_state(p1 + 'dir1'))
def test_invalid_path(self):
def test_invalid_path():
d = Directories()
p = Path('does_not_exist')
self.assertRaises(InvalidPathError, d.add_path, p)
self.assertEqual(0, len(d))
with raises(InvalidPathError):
d.add_path(p)
eq_(0, len(d))
def test_set_state_on_invalid_path(self):
def test_set_state_on_invalid_path():
d = Directories()
try:
d.set_state(Path('foobar',),STATE_NORMAL)
except LookupError:
self.fail()
assert False
def test_load_from_file_with_invalid_path(self):
def test_load_from_file_with_invalid_path(tmpdir):
#This test simulates a load from file resulting in a
#InvalidPath raise. Other directories must be loaded.
d1 = Directories()
d1.add_path(testpath + 'utils')
d1.add_path(testpath + 'onefile')
#Will raise InvalidPath upon loading
p = self.tmppath()
p = Path(str(tmpdir.join('toremove')))
io.mkdir(p)
d1.add_path(p)
io.rmdir(p)
tmpxml = op.join(self.tmpdir(), 'directories_testunit.xml')
tmpxml = str(tmpdir.join('directories_testunit.xml'))
d1.save_to_file(tmpxml)
d2 = Directories()
d2.load_from_file(tmpxml)
self.assertEqual(1, len(d2))
eq_(1, len(d2))
def test_unicode_save(self):
def test_unicode_save(tmpdir):
d = Directories()
p1 = self.tmppath() + 'hello\xe9'
p1 = Path(str(tmpdir)) + 'hello\xe9'
io.mkdir(p1)
io.mkdir(p1 + 'foo\xe9')
d.add_path(p1)
d.set_state(p1 + 'foo\xe9', STATE_EXCLUDED)
tmpxml = op.join(self.tmpdir(), 'directories_testunit.xml')
tmpxml = str(tmpdir.join('directories_testunit.xml'))
try:
d.save_to_file(tmpxml)
except UnicodeDecodeError:
self.fail()
assert False
def test_get_files_refreshes_its_directories(self):
def test_get_files_refreshes_its_directories():
d = Directories()
p = create_fake_fs(self.tmppath())
p = testpath + 'fs'
d.add_path(p)
files = d.get_files()
self.assertEqual(6, len(list(files)))
eq_(6, len(list(files)))
time.sleep(1)
os.remove(str(p + ('dir1','file1.test')))
files = d.get_files()
self.assertEqual(5, len(list(files)))
eq_(5, len(list(files)))
def test_get_files_does_not_choke_on_non_existing_directories(self):
def test_get_files_does_not_choke_on_non_existing_directories(tmpdir):
d = Directories()
p = Path(self.tmpdir())
p = Path(str(tmpdir))
d.add_path(p)
io.rmtree(p)
self.assertEqual([], list(d.get_files()))
eq_([], list(d.get_files()))
def test_get_state_returns_excluded_by_default_for_hidden_directories(self):
def test_get_state_returns_excluded_by_default_for_hidden_directories(tmpdir):
d = Directories()
p = Path(self.tmpdir())
p = Path(str(tmpdir))
hidden_dir_path = p + '.foo'
io.mkdir(p + '.foo')
d.add_path(p)
self.assertEqual(d.get_state(hidden_dir_path), STATE_EXCLUDED)
eq_(d.get_state(hidden_dir_path), STATE_EXCLUDED)
# But it can be overriden
d.set_state(hidden_dir_path, STATE_NORMAL)
self.assertEqual(d.get_state(hidden_dir_path), STATE_NORMAL)
eq_(d.get_state(hidden_dir_path), STATE_NORMAL)
def test_default_path_state_override(self):
def test_default_path_state_override(tmpdir):
# It's possible for a subclass to override the default state of a path
class MyDirectories(Directories):
def _default_state_for_path(self, path):
@@ -261,7 +281,7 @@ class TCDirectories(TestCase):
return STATE_EXCLUDED
d = MyDirectories()
p1 = self.tmppath()
p1 = Path(str(tmpdir))
io.mkdir(p1 + 'foobar')
io.open(p1 + 'foobar/somefile', 'w').close()
io.mkdir(p1 + 'foobaz')

View File

@@ -9,15 +9,13 @@
import sys
from jobprogress import job
from hsutil.decorators import log_calls
from hsutil.misc import first
from hsutil.testutil import eq_
from hsutil.testcase import TestCase
from hscommon.util import first
from hscommon.testutil import eq_, log_calls
from .. import engine
from ..engine import *
class NamedObject(object):
class NamedObject:
def __init__(self, name="foobar", with_words=False, size=1):
self.name = name
self.size = size
@@ -55,179 +53,179 @@ def assert_match(m, name1, name2):
eq_(m.first.name, name2)
eq_(m.second.name, name1)
class TCgetwords(TestCase):
class TestCasegetwords:
def test_spaces(self):
self.assertEqual(['a', 'b', 'c', 'd'], getwords("a b c d"))
self.assertEqual(['a', 'b', 'c', 'd'], getwords(" a b c d "))
eq_(['a', 'b', 'c', 'd'], getwords("a b c d"))
eq_(['a', 'b', 'c', 'd'], getwords(" a b c d "))
def test_splitter_chars(self):
self.assertEqual(
eq_(
[chr(i) for i in range(ord('a'),ord('z')+1)],
getwords("a-b_c&d+e(f)g;h\\i[j]k{l}m:n.o,p<q>r/s?t~u!v@w#x$y*z")
)
def test_joiner_chars(self):
self.assertEqual(["aec"], getwords("a'e\u0301c"))
eq_(["aec"], getwords("a'e\u0301c"))
def test_empty(self):
self.assertEqual([], getwords(''))
eq_([], getwords(''))
def test_returns_lowercase(self):
self.assertEqual(['foo', 'bar'], getwords('FOO BAR'))
eq_(['foo', 'bar'], getwords('FOO BAR'))
def test_decompose_unicode(self):
self.assertEqual(getwords('foo\xe9bar'), ['fooebar'])
eq_(getwords('foo\xe9bar'), ['fooebar'])
class TCgetfields(TestCase):
class TestCasegetfields:
def test_simple(self):
self.assertEqual([['a', 'b'], ['c', 'd', 'e']], getfields('a b - c d e'))
eq_([['a', 'b'], ['c', 'd', 'e']], getfields('a b - c d e'))
def test_empty(self):
self.assertEqual([], getfields(''))
eq_([], getfields(''))
def test_cleans_empty_fields(self):
expected = [['a', 'bc', 'def']]
actual = getfields(' - a bc def')
self.assertEqual(expected, actual)
eq_(expected, actual)
expected = [['bc', 'def']]
class TCunpack_fields(TestCase):
class TestCaseunpack_fields:
def test_with_fields(self):
expected = ['a', 'b', 'c', 'd', 'e', 'f']
actual = unpack_fields([['a'], ['b', 'c'], ['d', 'e', 'f']])
self.assertEqual(expected, actual)
eq_(expected, actual)
def test_without_fields(self):
expected = ['a', 'b', 'c', 'd', 'e', 'f']
actual = unpack_fields(['a', 'b', 'c', 'd', 'e', 'f'])
self.assertEqual(expected, actual)
eq_(expected, actual)
def test_empty(self):
self.assertEqual([], unpack_fields([]))
eq_([], unpack_fields([]))
class TCWordCompare(TestCase):
class TestCaseWordCompare:
def test_list(self):
self.assertEqual(100, compare(['a', 'b', 'c', 'd'],['a', 'b', 'c', 'd']))
self.assertEqual(86, compare(['a', 'b', 'c', 'd'],['a', 'b', 'c']))
eq_(100, compare(['a', 'b', 'c', 'd'],['a', 'b', 'c', 'd']))
eq_(86, compare(['a', 'b', 'c', 'd'],['a', 'b', 'c']))
def test_unordered(self):
#Sometimes, users don't want fuzzy matching too much When they set the slider
#to 100, they don't expect a filename with the same words, but not the same order, to match.
#Thus, we want to return 99 in that case.
self.assertEqual(99, compare(['a', 'b', 'c', 'd'], ['d', 'b', 'c', 'a']))
eq_(99, compare(['a', 'b', 'c', 'd'], ['d', 'b', 'c', 'a']))
def test_word_occurs_twice(self):
#if a word occurs twice in first, but once in second, we want the word to be only counted once
self.assertEqual(89, compare(['a', 'b', 'c', 'd', 'a'], ['d', 'b', 'c', 'a']))
eq_(89, compare(['a', 'b', 'c', 'd', 'a'], ['d', 'b', 'c', 'a']))
def test_uses_copy_of_lists(self):
first = ['foo', 'bar']
second = ['bar', 'bleh']
compare(first, second)
self.assertEqual(['foo', 'bar'], first)
self.assertEqual(['bar', 'bleh'], second)
eq_(['foo', 'bar'], first)
eq_(['bar', 'bleh'], second)
def test_word_weight(self):
self.assertEqual(int((6.0 / 13.0) * 100), compare(['foo', 'bar'], ['bar', 'bleh'], (WEIGHT_WORDS, )))
eq_(int((6.0 / 13.0) * 100), compare(['foo', 'bar'], ['bar', 'bleh'], (WEIGHT_WORDS, )))
def test_similar_words(self):
self.assertEqual(100, compare(['the', 'white', 'stripes'],['the', 'whites', 'stripe'], (MATCH_SIMILAR_WORDS, )))
eq_(100, compare(['the', 'white', 'stripes'],['the', 'whites', 'stripe'], (MATCH_SIMILAR_WORDS, )))
def test_empty(self):
self.assertEqual(0, compare([], []))
eq_(0, compare([], []))
def test_with_fields(self):
self.assertEqual(67, compare([['a', 'b'], ['c', 'd', 'e']], [['a', 'b'], ['c', 'd', 'f']]))
eq_(67, compare([['a', 'b'], ['c', 'd', 'e']], [['a', 'b'], ['c', 'd', 'f']]))
def test_propagate_flags_with_fields(self):
def test_propagate_flags_with_fields(self, monkeypatch):
def mock_compare(first, second, flags):
self.assertEqual((0, 1, 2, 3, 5), flags)
eq_((0, 1, 2, 3, 5), flags)
self.mock(engine, 'compare_fields', mock_compare)
monkeypatch.setattr(engine, 'compare_fields', mock_compare)
compare([['a']], [['a']], (0, 1, 2, 3, 5))
class TCWordCompareWithFields(TestCase):
class TestCaseWordCompareWithFields:
def test_simple(self):
self.assertEqual(67, compare_fields([['a', 'b'], ['c', 'd', 'e']], [['a', 'b'], ['c', 'd', 'f']]))
eq_(67, compare_fields([['a', 'b'], ['c', 'd', 'e']], [['a', 'b'], ['c', 'd', 'f']]))
def test_empty(self):
self.assertEqual(0, compare_fields([], []))
eq_(0, compare_fields([], []))
def test_different_length(self):
self.assertEqual(0, compare_fields([['a'], ['b']], [['a'], ['b'], ['c']]))
eq_(0, compare_fields([['a'], ['b']], [['a'], ['b'], ['c']]))
def test_propagates_flags(self):
def test_propagates_flags(self, monkeypatch):
def mock_compare(first, second, flags):
self.assertEqual((0, 1, 2, 3, 5), flags)
eq_((0, 1, 2, 3, 5), flags)
self.mock(engine, 'compare_fields', mock_compare)
monkeypatch.setattr(engine, 'compare_fields', mock_compare)
compare_fields([['a']], [['a']],(0, 1, 2, 3, 5))
def test_order(self):
first = [['a', 'b'], ['c', 'd', 'e']]
second = [['c', 'd', 'f'], ['a', 'b']]
self.assertEqual(0, compare_fields(first, second))
eq_(0, compare_fields(first, second))
def test_no_order(self):
first = [['a','b'],['c','d','e']]
second = [['c','d','f'],['a','b']]
self.assertEqual(67, compare_fields(first, second, (NO_FIELD_ORDER, )))
eq_(67, compare_fields(first, second, (NO_FIELD_ORDER, )))
first = [['a','b'],['a','b']] #a field can only be matched once.
second = [['c','d','f'],['a','b']]
self.assertEqual(0, compare_fields(first, second, (NO_FIELD_ORDER, )))
eq_(0, compare_fields(first, second, (NO_FIELD_ORDER, )))
first = [['a','b'],['a','b','c']]
second = [['c','d','f'],['a','b']]
self.assertEqual(33, compare_fields(first, second, (NO_FIELD_ORDER, )))
eq_(33, compare_fields(first, second, (NO_FIELD_ORDER, )))
def test_compare_fields_without_order_doesnt_alter_fields(self):
#The NO_ORDER comp type altered the fields!
first = [['a','b'],['c','d','e']]
second = [['c','d','f'],['a','b']]
self.assertEqual(67, compare_fields(first, second, (NO_FIELD_ORDER, )))
self.assertEqual([['a','b'],['c','d','e']],first)
self.assertEqual([['c','d','f'],['a','b']],second)
eq_(67, compare_fields(first, second, (NO_FIELD_ORDER, )))
eq_([['a','b'],['c','d','e']],first)
eq_([['c','d','f'],['a','b']],second)
class TCbuild_word_dict(TestCase):
class TestCasebuild_word_dict:
def test_with_standard_words(self):
l = [NamedObject('foo bar',True)]
l.append(NamedObject('bar baz',True))
l.append(NamedObject('baz bleh foo',True))
d = build_word_dict(l)
self.assertEqual(4,len(d))
self.assertEqual(2,len(d['foo']))
self.assert_(l[0] in d['foo'])
self.assert_(l[2] in d['foo'])
self.assertEqual(2,len(d['bar']))
self.assert_(l[0] in d['bar'])
self.assert_(l[1] in d['bar'])
self.assertEqual(2,len(d['baz']))
self.assert_(l[1] in d['baz'])
self.assert_(l[2] in d['baz'])
self.assertEqual(1,len(d['bleh']))
self.assert_(l[2] in d['bleh'])
eq_(4,len(d))
eq_(2,len(d['foo']))
assert l[0] in d['foo']
assert l[2] in d['foo']
eq_(2,len(d['bar']))
assert l[0] in d['bar']
assert l[1] in d['bar']
eq_(2,len(d['baz']))
assert l[1] in d['baz']
assert l[2] in d['baz']
eq_(1,len(d['bleh']))
assert l[2] in d['bleh']
def test_unpack_fields(self):
o = NamedObject('')
o.words = [['foo','bar'],['baz']]
d = build_word_dict([o])
self.assertEqual(3,len(d))
self.assertEqual(1,len(d['foo']))
eq_(3,len(d))
eq_(1,len(d['foo']))
def test_words_are_unaltered(self):
o = NamedObject('')
o.words = [['foo','bar'],['baz']]
d = build_word_dict([o])
self.assertEqual([['foo','bar'],['baz']],o.words)
build_word_dict([o])
eq_([['foo','bar'],['baz']],o.words)
def test_object_instances_can_only_be_once_in_words_object_list(self):
o = NamedObject('foo foo',True)
d = build_word_dict([o])
self.assertEqual(1,len(d['foo']))
eq_(1,len(d['foo']))
def test_job(self):
def do_progress(p,d=''):
@@ -239,11 +237,11 @@ class TCbuild_word_dict(TestCase):
s = "foo bar"
build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
# We don't have intermediate log because iter_with_progress is called with every > 1
self.assertEqual(0,self.log[0])
self.assertEqual(100,self.log[1])
eq_(0,self.log[0])
eq_(100,self.log[1])
class TCmerge_similar_words(TestCase):
class TestCasemerge_similar_words:
def test_some_similar_words(self):
d = {
'foobar':set([1]),
@@ -251,20 +249,20 @@ class TCmerge_similar_words(TestCase):
'foobar2':set([3]),
}
merge_similar_words(d)
self.assertEqual(1,len(d))
self.assertEqual(3,len(d['foobar']))
eq_(1,len(d))
eq_(3,len(d['foobar']))
class TCreduce_common_words(TestCase):
class TestCasereduce_common_words:
def test_typical(self):
d = {
'foo': set([NamedObject('foo bar',True) for i in range(50)]),
'bar': set([NamedObject('foo bar',True) for i in range(49)])
}
reduce_common_words(d, 50)
self.assert_('foo' not in d)
self.assertEqual(49,len(d['bar']))
assert 'foo' not in d
eq_(49,len(d['bar']))
def test_dont_remove_objects_with_only_common_words(self):
d = {
@@ -272,8 +270,8 @@ class TCreduce_common_words(TestCase):
'uncommon': set([NamedObject("common uncommon",True)])
}
reduce_common_words(d, 50)
self.assertEqual(1,len(d['common']))
self.assertEqual(1,len(d['uncommon']))
eq_(1,len(d['common']))
eq_(1,len(d['uncommon']))
def test_values_still_are_set_instances(self):
d = {
@@ -281,8 +279,8 @@ class TCreduce_common_words(TestCase):
'uncommon': set([NamedObject("common uncommon",True)])
}
reduce_common_words(d, 50)
self.assert_(isinstance(d['common'],set))
self.assert_(isinstance(d['uncommon'],set))
assert isinstance(d['common'],set)
assert isinstance(d['uncommon'],set)
def test_dont_raise_KeyError_when_a_word_has_been_removed(self):
#If a word has been removed by the reduce, an object in a subsequent common word that
@@ -324,42 +322,42 @@ class TCreduce_common_words(TestCase):
'baz': set([NamedObject('foo bar baz',True) for i in range(49)])
}
reduce_common_words(d, 50)
self.assertEqual(1,len(d['foo']))
self.assertEqual(1,len(d['bar']))
self.assertEqual(49,len(d['baz']))
eq_(1,len(d['foo']))
eq_(1,len(d['bar']))
eq_(49,len(d['baz']))
class TCget_match(TestCase):
class TestCaseget_match:
def test_simple(self):
o1 = NamedObject("foo bar",True)
o2 = NamedObject("bar bleh",True)
m = get_match(o1,o2)
self.assertEqual(50,m.percentage)
self.assertEqual(['foo','bar'],m.first.words)
self.assertEqual(['bar','bleh'],m.second.words)
self.assert_(m.first is o1)
self.assert_(m.second is o2)
eq_(50,m.percentage)
eq_(['foo','bar'],m.first.words)
eq_(['bar','bleh'],m.second.words)
assert m.first is o1
assert m.second is o2
def test_in(self):
o1 = NamedObject("foo",True)
o2 = NamedObject("bar",True)
m = get_match(o1,o2)
self.assert_(o1 in m)
self.assert_(o2 in m)
self.assert_(object() not in m)
assert o1 in m
assert o2 in m
assert object() not in m
def test_word_weight(self):
self.assertEqual(int((6.0 / 13.0) * 100),get_match(NamedObject("foo bar",True),NamedObject("bar bleh",True),(WEIGHT_WORDS,)).percentage)
eq_(int((6.0 / 13.0) * 100),get_match(NamedObject("foo bar",True),NamedObject("bar bleh",True),(WEIGHT_WORDS,)).percentage)
class GetMatches(TestCase):
class TestCaseGetMatches:
def test_empty(self):
eq_(getmatches([]), [])
def test_simple(self):
l = [NamedObject("foo bar"),NamedObject("bar bleh"),NamedObject("a b c foo")]
r = getmatches(l)
self.assertEqual(2,len(r))
eq_(2,len(r))
m = first(m for m in r if m.percentage == 50) #"foo bar" and "bar bleh"
assert_match(m, 'foo bar', 'bar bleh')
m = first(m for m in r if m.percentage == 33) #"foo bar" and "a b c foo"
@@ -376,17 +374,17 @@ class GetMatches(TestCase):
def test_twice_the_same_word(self):
l = [NamedObject("foo foo bar"),NamedObject("bar bleh")]
r = getmatches(l)
self.assertEqual(1,len(r))
eq_(1,len(r))
def test_twice_the_same_word_when_preworded(self):
l = [NamedObject("foo foo bar",True),NamedObject("bar bleh",True)]
r = getmatches(l)
self.assertEqual(1,len(r))
eq_(1,len(r))
def test_two_words_match(self):
l = [NamedObject("foo bar"),NamedObject("foo bar bleh")]
r = getmatches(l)
self.assertEqual(1,len(r))
eq_(1,len(r))
def test_match_files_with_only_common_words(self):
#If a word occurs more than 50 times, it is excluded from the matching process
@@ -395,7 +393,7 @@ class GetMatches(TestCase):
# This test assumes that the common word threashold const is 50
l = [NamedObject("foo") for i in range(50)]
r = getmatches(l)
self.assertEqual(1225,len(r))
eq_(1225,len(r))
def test_use_words_already_there_if_there(self):
o1 = NamedObject('foo')
@@ -412,14 +410,14 @@ class GetMatches(TestCase):
self.log = []
s = "foo bar"
getmatches([NamedObject(s), NamedObject(s), NamedObject(s)], j=j)
self.assert_(len(self.log) > 2)
self.assertEqual(0,self.log[0])
self.assertEqual(100,self.log[-1])
assert len(self.log) > 2
eq_(0,self.log[0])
eq_(100,self.log[-1])
def test_weight_words(self):
l = [NamedObject("foo bar"),NamedObject("bar bleh")]
m = getmatches(l, weight_words=True)[0]
self.assertEqual(int((6.0 / 13.0) * 100),m.percentage)
eq_(int((6.0 / 13.0) * 100),m.percentage)
def test_similar_word(self):
l = [NamedObject("foobar"),NamedObject("foobars")]
@@ -439,7 +437,7 @@ class GetMatches(TestCase):
def test_double_words_get_counted_only_once(self):
l = [NamedObject("foo bar foo bleh"),NamedObject("foo bar bleh bar")]
m = getmatches(l)[0]
self.assertEqual(75,m.percentage)
eq_(75,m.percentage)
def test_with_fields(self):
o1 = NamedObject("foo bar - foo bleh")
@@ -447,7 +445,7 @@ class GetMatches(TestCase):
o1.words = getfields(o1.name)
o2.words = getfields(o2.name)
m = getmatches([o1, o2])[0]
self.assertEqual(50, m.percentage)
eq_(50, m.percentage)
def test_with_fields_no_order(self):
o1 = NamedObject("foo bar - foo bleh")
@@ -475,9 +473,9 @@ class GetMatches(TestCase):
def test_min_match_percentage(self):
l = [NamedObject("foo bar"),NamedObject("bar bleh"),NamedObject("a b c foo")]
r = getmatches(l, min_match_percentage=50)
self.assertEqual(1,len(r)) #Only "foo bar" / "bar bleh" should match
eq_(1,len(r)) #Only "foo bar" / "bar bleh" should match
def test_MemoryError(self):
def test_MemoryError(self, monkeypatch):
@log_calls
def mocked_match(first, second, flags):
if len(mocked_match.calls) > 42:
@@ -485,35 +483,35 @@ class GetMatches(TestCase):
return Match(first, second, 0)
objects = [NamedObject() for i in range(10)] # results in 45 matches
self.mock(engine, 'get_match', mocked_match)
monkeypatch.setattr(engine, 'get_match', mocked_match)
try:
r = getmatches(objects)
except MemoryError:
self.fail('MemorryError must be handled')
self.assertEqual(42, len(r))
eq_(42, len(r))
class GetMatchesByContents(TestCase):
class TestCaseGetMatchesByContents:
def test_dont_compare_empty_files(self):
o1, o2 = no(size=0), no(size=0)
assert not getmatches_by_contents([o1, o2])
class TCGroup(TestCase):
class TestCaseGroup:
def test_empy(self):
g = Group()
self.assertEqual(None,g.ref)
self.assertEqual([],g.dupes)
self.assertEqual(0,len(g.matches))
eq_(None,g.ref)
eq_([],g.dupes)
eq_(0,len(g.matches))
def test_add_match(self):
g = Group()
m = get_match(NamedObject("foo",True),NamedObject("bar",True))
g.add_match(m)
self.assert_(g.ref is m.first)
self.assertEqual([m.second],g.dupes)
self.assertEqual(1,len(g.matches))
self.assert_(m in g.matches)
assert g.ref is m.first
eq_([m.second],g.dupes)
eq_(1,len(g.matches))
assert m in g.matches
def test_multiple_add_match(self):
g = Group()
@@ -522,49 +520,49 @@ class TCGroup(TestCase):
o3 = NamedObject("c",True)
o4 = NamedObject("d",True)
g.add_match(get_match(o1,o2))
self.assert_(g.ref is o1)
self.assertEqual([o2],g.dupes)
self.assertEqual(1,len(g.matches))
assert g.ref is o1
eq_([o2],g.dupes)
eq_(1,len(g.matches))
g.add_match(get_match(o1,o3))
self.assertEqual([o2],g.dupes)
self.assertEqual(2,len(g.matches))
eq_([o2],g.dupes)
eq_(2,len(g.matches))
g.add_match(get_match(o2,o3))
self.assertEqual([o2,o3],g.dupes)
self.assertEqual(3,len(g.matches))
eq_([o2,o3],g.dupes)
eq_(3,len(g.matches))
g.add_match(get_match(o1,o4))
self.assertEqual([o2,o3],g.dupes)
self.assertEqual(4,len(g.matches))
eq_([o2,o3],g.dupes)
eq_(4,len(g.matches))
g.add_match(get_match(o2,o4))
self.assertEqual([o2,o3],g.dupes)
self.assertEqual(5,len(g.matches))
eq_([o2,o3],g.dupes)
eq_(5,len(g.matches))
g.add_match(get_match(o3,o4))
self.assertEqual([o2,o3,o4],g.dupes)
self.assertEqual(6,len(g.matches))
eq_([o2,o3,o4],g.dupes)
eq_(6,len(g.matches))
def test_len(self):
g = Group()
self.assertEqual(0,len(g))
eq_(0,len(g))
g.add_match(get_match(NamedObject("foo",True),NamedObject("bar",True)))
self.assertEqual(2,len(g))
eq_(2,len(g))
def test_add_same_match_twice(self):
g = Group()
m = get_match(NamedObject("foo",True),NamedObject("foo",True))
g.add_match(m)
self.assertEqual(2,len(g))
self.assertEqual(1,len(g.matches))
eq_(2,len(g))
eq_(1,len(g.matches))
g.add_match(m)
self.assertEqual(2,len(g))
self.assertEqual(1,len(g.matches))
eq_(2,len(g))
eq_(1,len(g.matches))
def test_in(self):
g = Group()
o1 = NamedObject("foo",True)
o2 = NamedObject("bar",True)
self.assert_(o1 not in g)
assert o1 not in g
g.add_match(get_match(o1,o2))
self.assert_(o1 in g)
self.assert_(o2 in g)
assert o1 in g
assert o2 in g
def test_remove(self):
g = Group()
@@ -574,14 +572,14 @@ class TCGroup(TestCase):
g.add_match(get_match(o1,o2))
g.add_match(get_match(o1,o3))
g.add_match(get_match(o2,o3))
self.assertEqual(3,len(g.matches))
self.assertEqual(3,len(g))
eq_(3,len(g.matches))
eq_(3,len(g))
g.remove_dupe(o3)
self.assertEqual(1,len(g.matches))
self.assertEqual(2,len(g))
eq_(1,len(g.matches))
eq_(2,len(g))
g.remove_dupe(o1)
self.assertEqual(0,len(g.matches))
self.assertEqual(0,len(g))
eq_(0,len(g.matches))
eq_(0,len(g))
def test_remove_with_ref_dupes(self):
g = Group()
@@ -594,21 +592,21 @@ class TCGroup(TestCase):
o1.is_ref = True
o2.is_ref = True
g.remove_dupe(o3)
self.assertEqual(0,len(g))
eq_(0,len(g))
def test_switch_ref(self):
o1 = NamedObject(with_words=True)
o2 = NamedObject(with_words=True)
g = Group()
g.add_match(get_match(o1,o2))
self.assert_(o1 is g.ref)
assert o1 is g.ref
g.switch_ref(o2)
self.assert_(o2 is g.ref)
self.assertEqual([o1],g.dupes)
assert o2 is g.ref
eq_([o1],g.dupes)
g.switch_ref(o2)
self.assert_(o2 is g.ref)
assert o2 is g.ref
g.switch_ref(NamedObject('',True))
self.assert_(o2 is g.ref)
assert o2 is g.ref
def test_get_match_of(self):
g = Group()
@@ -616,10 +614,10 @@ class TCGroup(TestCase):
g.add_match(m)
o = g.dupes[0]
m = g.get_match_of(o)
self.assert_(g.ref in m)
self.assert_(o in m)
self.assert_(g.get_match_of(NamedObject('',True)) is None)
self.assert_(g.get_match_of(g.ref) is None)
assert g.ref in m
assert o in m
assert g.get_match_of(NamedObject('',True)) is None
assert g.get_match_of(g.ref) is None
def test_percentage(self):
#percentage should return the avg percentage in relation to the ref
@@ -631,18 +629,18 @@ class TCGroup(TestCase):
g.add_match(m1)
g.add_match(m2)
g.add_match(m3)
self.assertEqual(75,g.percentage)
eq_(75,g.percentage)
g.switch_ref(g.dupes[0])
self.assertEqual(66,g.percentage)
eq_(66,g.percentage)
g.remove_dupe(g.dupes[0])
self.assertEqual(33,g.percentage)
eq_(33,g.percentage)
g.add_match(m1)
g.add_match(m2)
self.assertEqual(66,g.percentage)
eq_(66,g.percentage)
def test_percentage_on_empty_group(self):
g = Group()
self.assertEqual(0,g.percentage)
eq_(0,g.percentage)
def test_prioritize(self):
m1,m2,m3 = get_match_triangle()
@@ -656,9 +654,9 @@ class TCGroup(TestCase):
g.add_match(m1)
g.add_match(m2)
g.add_match(m3)
self.assert_(o1 is g.ref)
assert o1 is g.ref
g.prioritize(lambda x:x.name)
self.assert_(o3 is g.ref)
assert o3 is g.ref
def test_prioritize_with_tie_breaker(self):
# if the ref has the same key as one or more of the dupe, run the tie_breaker func among them
@@ -666,7 +664,7 @@ class TCGroup(TestCase):
o1, o2, o3 = g.ordered
tie_breaker = lambda ref, dupe: dupe is o3
g.prioritize(lambda x:0, tie_breaker)
self.assertTrue(g.ref is o3)
assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_on_all_dupes(self):
# Even if a dupe is chosen to switch with ref with a tie breaker, we still run the tie breaker
@@ -678,7 +676,7 @@ class TCGroup(TestCase):
o3.foo = 3
tie_breaker = lambda ref, dupe: dupe.foo > ref.foo
g.prioritize(lambda x:0, tie_breaker)
self.assertTrue(g.ref is o3)
assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self):
# The tie breaker only runs on dupes that had the same value for the key_func
@@ -693,14 +691,14 @@ class TCGroup(TestCase):
key_func = lambda x: -x.foo
tie_breaker = lambda ref, dupe: dupe.bar > ref.bar
g.prioritize(key_func, tie_breaker)
self.assertTrue(g.ref is o2)
assert g.ref is o2
def test_list_like(self):
g = Group()
o1,o2 = (NamedObject("foo",True),NamedObject("bar",True))
g.add_match(get_match(o1,o2))
self.assert_(g[0] is o1)
self.assert_(g[1] is o2)
assert g[0] is o1
assert g[1] is o2
def test_discard_matches(self):
g = Group()
@@ -708,33 +706,33 @@ class TCGroup(TestCase):
g.add_match(get_match(o1,o2))
g.add_match(get_match(o1,o3))
g.discard_matches()
self.assertEqual(1,len(g.matches))
self.assertEqual(0,len(g.candidates))
eq_(1,len(g.matches))
eq_(0,len(g.candidates))
class TCget_groups(TestCase):
class TestCaseget_groups:
def test_empty(self):
r = get_groups([])
self.assertEqual([],r)
eq_([],r)
def test_simple(self):
l = [NamedObject("foo bar"),NamedObject("bar bleh")]
matches = getmatches(l)
m = matches[0]
r = get_groups(matches)
self.assertEqual(1,len(r))
eq_(1,len(r))
g = r[0]
self.assert_(g.ref is m.first)
self.assertEqual([m.second],g.dupes)
assert g.ref is m.first
eq_([m.second],g.dupes)
def test_group_with_multiple_matches(self):
#This results in 3 matches
l = [NamedObject("foo"),NamedObject("foo"),NamedObject("foo")]
matches = getmatches(l)
r = get_groups(matches)
self.assertEqual(1,len(r))
eq_(1,len(r))
g = r[0]
self.assertEqual(3,len(g))
eq_(3,len(g))
def test_must_choose_a_group(self):
l = [NamedObject("a b"),NamedObject("a b"),NamedObject("b c"),NamedObject("c d"),NamedObject("c d")]
@@ -742,8 +740,8 @@ class TCget_groups(TestCase):
#"b c" can go either of them, but not both.
matches = getmatches(l)
r = get_groups(matches)
self.assertEqual(2,len(r))
self.assertEqual(5,len(r[0])+len(r[1]))
eq_(2,len(r))
eq_(5,len(r[0])+len(r[1]))
def test_should_all_go_in_the_same_group(self):
l = [NamedObject("a b"),NamedObject("a b"),NamedObject("a b"),NamedObject("a b")]
@@ -751,7 +749,7 @@ class TCget_groups(TestCase):
#"b c" can fit in both, but it must be in only one of them
matches = getmatches(l)
r = get_groups(matches)
self.assertEqual(1,len(r))
eq_(1,len(r))
def test_give_priority_to_matches_with_higher_percentage(self):
o1 = NamedObject(with_words=True)
@@ -760,19 +758,19 @@ class TCget_groups(TestCase):
m1 = Match(o1, o2, 1)
m2 = Match(o2, o3, 2)
r = get_groups([m1,m2])
self.assertEqual(1,len(r))
eq_(1,len(r))
g = r[0]
self.assertEqual(2,len(g))
self.assert_(o1 not in g)
self.assert_(o2 in g)
self.assert_(o3 in g)
eq_(2,len(g))
assert o1 not in g
assert o2 in g
assert o3 in g
def test_four_sized_group(self):
l = [NamedObject("foobar") for i in range(4)]
m = getmatches(l)
r = get_groups(m)
self.assertEqual(1,len(r))
self.assertEqual(4,len(r[0]))
eq_(1,len(r))
eq_(4,len(r[0]))
def test_referenced_by_ref2(self):
o1 = NamedObject(with_words=True)
@@ -782,7 +780,7 @@ class TCget_groups(TestCase):
m2 = get_match(o3,o1)
m3 = get_match(o3,o2)
r = get_groups([m1,m2,m3])
self.assertEqual(3,len(r[0]))
eq_(3,len(r[0]))
def test_job(self):
def do_progress(p,d=''):
@@ -795,8 +793,8 @@ class TCget_groups(TestCase):
#101%: To make sure it is processed first so the job test works correctly
m4 = Match(NamedObject('a',True), NamedObject('a',True), 101)
get_groups([m1,m2,m3,m4],j)
self.assertEqual(0,self.log[0])
self.assertEqual(100,self.log[-1])
eq_(0,self.log[0])
eq_(100,self.log[-1])
def test_group_admissible_discarded_dupes(self):
# If, with a (A, B, C, D) set, all match with A, but C and D don't match with B and that the

Some files were not shown because too many files have changed in this diff Show More