mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-25 08:01:39 +00:00
Compare commits
32 Commits
se2.10.0
...
before-py3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ae0e8759 | ||
|
|
09f73988b3 | ||
|
|
9e6f289319 | ||
|
|
d2a55ffd31 | ||
|
|
793c2aa423 | ||
|
|
5daa332b6c | ||
|
|
d5511a857c | ||
|
|
7fecd21331 | ||
|
|
88b79e512f | ||
|
|
853bf63777 | ||
|
|
ff16fea54a | ||
|
|
a03e2a69d4 | ||
|
|
56a39df635 | ||
|
|
ac1593ff75 | ||
|
|
4d66b4667c | ||
|
|
fdde538b66 | ||
|
|
de1147219c | ||
|
|
371426a08e | ||
|
|
75eb005ba0 | ||
|
|
601b67145c | ||
|
|
c65afbc057 | ||
|
|
378589a473 | ||
|
|
fa264972a4 | ||
|
|
6b10e01c03 | ||
|
|
5a6d74ab37 | ||
|
|
73f1bb6968 | ||
|
|
d1a7f51859 | ||
|
|
2ae16396a6 | ||
|
|
ef090a5dc5 | ||
|
|
5c0799e82b | ||
|
|
fa2ee01d3f | ||
|
|
d6ba80bd3f |
8
.hgtags
8
.hgtags
@@ -15,3 +15,11 @@ cbcf9c80fee4c908ef2efbf1c143c9e47676c9b2 pe1.8.0
|
||||
4c3cb1e671a333eabde1151c7c6ffb3609cab025 pe1.8.4
|
||||
0a71306434bca51bea9a5d5ae54fe1bf0e4900d8 pe1.8.5
|
||||
556baf4a410779e9bbf43129de133e4c4b26d679 pe1.8.6
|
||||
9149024283959a50fe9a47a5f175b905d1672c19 se2.10.0
|
||||
388a7e5aef6385e515189f4a15b4c4fed3ae2fcf me5.8.0
|
||||
27501167e3b9262ecb60c967941294f36d77eb25 pe1.9.0
|
||||
cb0a860430bacd712820bce426bcf47a4135efe1 se2.10.1
|
||||
cb0a860430bacd712820bce426bcf47a4135efe1 se2.10.1
|
||||
f71d405e62badcfdc1b037facaac043cece40ee5 se2.10.1
|
||||
3742e83edd9eadf44e1a501859f5e2462b1ef6fd me5.8.1
|
||||
724ff565dd785fb739774588c6ee652cfc0612d5 pe1.9.1
|
||||
|
||||
7
README
7
README
@@ -12,9 +12,8 @@ This package contains the source for dupeGuru. To learns how to build it, refer
|
||||
There are also other sub-folder that comes from external repositories (automatically checked out
|
||||
with svn:externals):
|
||||
|
||||
- hsutil: A collection of helpers used across HS applications.
|
||||
- hscommon: A collection of helpers used across HS applications.
|
||||
- hsdocgen: An ad-hoc document generation used across HS project (used for help files)
|
||||
- hsmedia: A library to read audio file metadata, used in dupeGuru ME.
|
||||
- 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.
|
||||
|
||||
@@ -28,10 +27,12 @@ General dependencies
|
||||
|
||||
- Python 2.6 (http://www.python.org)
|
||||
- Send2Trash (http://hg.hardcoded.net/send2trash)
|
||||
- hsutil (http://hg.hardcoded.net/hsutil)
|
||||
- hsaudiotag (for ME) (http://hg.hardcoded.net/hsaudiotag)
|
||||
- lxml, to read and write XML files. (http://codespeak.net/lxml/)
|
||||
- Mako, to generate help files. (http://www.makotemplates.org/)
|
||||
- PyYaml, for help files and the build system. (http://pyyaml.org/)
|
||||
- Nose, to run unit tests. (http://somethingaboutorange.com/mrl/projects/nose/)
|
||||
- py.test, to run unit tests. (http://codespeak.net/py/dist/test/)
|
||||
|
||||
OS X prerequisites
|
||||
-----
|
||||
|
||||
13
build.py
13
build.py
@@ -15,8 +15,8 @@ import shutil
|
||||
from setuptools import setup
|
||||
import yaml
|
||||
|
||||
from hsdocgen import generate_help, filters
|
||||
from hsutil.build import add_to_pythonpath, print_and_do, build_all_qt_ui, copy_packages
|
||||
from hscommon import helpgen
|
||||
from hscommon.build import add_to_pythonpath, print_and_do, build_all_qt_ui, copy_packages
|
||||
|
||||
def build_cocoa(edition, dev, help_destpath):
|
||||
if not dev:
|
||||
@@ -30,10 +30,10 @@ def build_cocoa(edition, dev, help_destpath):
|
||||
if not dev:
|
||||
specific_packages = {
|
||||
'se': ['core_se'],
|
||||
'me': ['core_me', 'hsmedia'],
|
||||
'me': ['core_me'],
|
||||
'pe': ['core_pe'],
|
||||
}[edition]
|
||||
copy_packages(['core', 'hsutil'] + specific_packages, 'build')
|
||||
copy_packages(['core', 'hscommon'] + specific_packages, 'build')
|
||||
cocoa_project_path = 'cocoa/{0}'.format(edition)
|
||||
shutil.copy(op.join(cocoa_project_path, 'dg_cocoa.py'), 'build')
|
||||
os.chdir('build')
|
||||
@@ -85,13 +85,12 @@ def main():
|
||||
add_to_pythonpath('.')
|
||||
print "Generating Help"
|
||||
windows = sys.platform == 'win32'
|
||||
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}")
|
||||
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))
|
||||
generate_help.main(help_basepath, help_destpath, force_render=not dev, tix=tix, windows=windows)
|
||||
|
||||
helpgen.gen(help_basepath, help_destpath, profile=profile)
|
||||
print "Building dupeGuru"
|
||||
if edition == 'pe':
|
||||
os.chdir('core_pe')
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>hsft</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5.7.2</string>
|
||||
<string>5.8.1</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsutil.cocoa import signature
|
||||
from hscommon.cocoa import signature
|
||||
|
||||
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
||||
from core_me.app_cocoa import DupeGuruME
|
||||
@@ -13,7 +13,7 @@ from core.scanner import (SCAN_TYPE_FILENAME, SCAN_TYPE_FIELDS, SCAN_TYPE_FIELDS
|
||||
|
||||
# Fix py2app imports which chokes on relative imports and other stuff
|
||||
from core_me import app_cocoa, data, fs, scanner
|
||||
from hsmedia import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
|
||||
from hsaudiotag import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
|
||||
from lxml import etree, _elementpath
|
||||
import gzip
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B3D6611243F83009A7A30 /* ResultOutline.m */; };
|
||||
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
|
||||
CE14259F0AFB719300BD5167 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
|
||||
@@ -108,6 +111,13 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
CE0B3D6411243F83009A7A30 /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
|
||||
CE0B3D6511243F83009A7A30 /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
|
||||
CE0B3D6611243F83009A7A30 /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
|
||||
@@ -155,8 +165,6 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
|
||||
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
|
||||
CEDF07A1112493B200EE5BC0 /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
|
||||
@@ -181,21 +189,19 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
080E96DDFE201D6D7F000001 /* Classes */ = {
|
||||
080E96DDFE201D6D7F000001 /* DGME */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CE381C9509914ACE003581CE /* AppDelegate.h */,
|
||||
CE381C9409914ACE003581CE /* AppDelegate.m */,
|
||||
CE848A1809DD85810004CB44 /* Consts.h */,
|
||||
CECA899A09DB132E00A3D774 /* DetailsPanel.h */,
|
||||
CECA899B09DB132E00A3D774 /* DetailsPanel.m */,
|
||||
CE68EE6509ABC48000971085 /* DirectoryPanel.h */,
|
||||
CE68EE6609ABC48000971085 /* DirectoryPanel.m */,
|
||||
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */,
|
||||
CE381C9B09914ADF003581CE /* ResultWindow.h */,
|
||||
CE381C9A09914ADF003581CE /* ResultWindow.m */,
|
||||
);
|
||||
name = Classes;
|
||||
name = DGME;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||
@@ -228,7 +234,7 @@
|
||||
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
080E96DDFE201D6D7F000001 /* Classes */,
|
||||
080E96DDFE201D6D7F000001 /* DGME */,
|
||||
CE515E140FC6C17900EC695D /* dgbase */,
|
||||
CE515DDD0FC6C09400EC695D /* cocoalib */,
|
||||
29B97315FDCFA39411CA2CEA /* Other Sources */,
|
||||
@@ -277,6 +283,8 @@
|
||||
CE003CB411242D00004B0AA7 /* HSGUIController.m */,
|
||||
CE003CB511242D00004B0AA7 /* HSOutline.h */,
|
||||
CE003CB611242D00004B0AA7 /* HSOutline.m */,
|
||||
CE0A0BFE1175A1C000DCA3C6 /* HSTable.h */,
|
||||
CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */,
|
||||
CE003CB711242D00004B0AA7 /* HSWindowController.h */,
|
||||
CE003CB811242D00004B0AA7 /* HSWindowController.m */,
|
||||
);
|
||||
@@ -289,6 +297,7 @@
|
||||
children = (
|
||||
CE003CBC11242D00004B0AA7 /* PyGUI.h */,
|
||||
CE003CBD11242D00004B0AA7 /* PyOutline.h */,
|
||||
CE0A0C131175A28100DCA3C6 /* PyTable.h */,
|
||||
);
|
||||
name = proxies;
|
||||
path = ../../cocoalib/proxies;
|
||||
@@ -315,6 +324,7 @@
|
||||
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
|
||||
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
|
||||
CE900AD1109B238600754048 /* Preferences.xib */,
|
||||
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */,
|
||||
);
|
||||
path = xib;
|
||||
sourceTree = "<group>";
|
||||
@@ -383,6 +393,8 @@
|
||||
CE6032BF0FE6784C007E33FF /* DetailsPanel.m */,
|
||||
CE515E180FC6C19300EC695D /* DirectoryPanel.h */,
|
||||
CE515E190FC6C19300EC695D /* DirectoryPanel.m */,
|
||||
CE0A0C011175A1DE00DCA3C6 /* ProblemDialog.h */,
|
||||
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */,
|
||||
CE515E1B0FC6C19300EC695D /* ResultWindow.h */,
|
||||
CE515E1C0FC6C19300EC695D /* ResultWindow.m */,
|
||||
CE0B3D6511243F83009A7A30 /* ResultOutline.h */,
|
||||
@@ -391,6 +403,7 @@
|
||||
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */,
|
||||
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */,
|
||||
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */,
|
||||
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */,
|
||||
CE0B3D6411243F83009A7A30 /* PyResultTree.h */,
|
||||
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */,
|
||||
);
|
||||
@@ -466,6 +479,7 @@
|
||||
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */,
|
||||
CE4B59C91119919700C06C9E /* progress.xib in Resources */,
|
||||
CE4B59CA1119919700C06C9E /* registration.xib in Resources */,
|
||||
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -502,6 +516,8 @@
|
||||
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */,
|
||||
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */,
|
||||
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */,
|
||||
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */,
|
||||
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>hsft</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.6</string>
|
||||
<string>1.9.1</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
|
||||
@@ -84,6 +87,13 @@
|
||||
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; };
|
||||
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; };
|
||||
CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
|
||||
@@ -180,7 +190,7 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
080E96DDFE201D6D7F000001 /* Classes */ = {
|
||||
080E96DDFE201D6D7F000001 /* DGPE */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CE381C9509914ACE003581CE /* AppDelegate.h */,
|
||||
@@ -194,7 +204,7 @@
|
||||
CE381C9B09914ADF003581CE /* ResultWindow.h */,
|
||||
CE381C9A09914ADF003581CE /* ResultWindow.m */,
|
||||
);
|
||||
name = Classes;
|
||||
name = DGPE;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||
@@ -227,7 +237,7 @@
|
||||
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
080E96DDFE201D6D7F000001 /* Classes */,
|
||||
080E96DDFE201D6D7F000001 /* DGPE */,
|
||||
CE80DB1A0FC192AB0086DCA6 /* cocoalib */,
|
||||
CE80DB810FC194BD0086DCA6 /* dgbase */,
|
||||
29B97315FDCFA39411CA2CEA /* Other Sources */,
|
||||
@@ -276,6 +286,7 @@
|
||||
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */,
|
||||
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */,
|
||||
CE031750109B340A00517EE6 /* Preferences.xib */,
|
||||
CE0C2AC71177021600BC749F /* ProblemDialog.xib */,
|
||||
);
|
||||
path = xib;
|
||||
sourceTree = "<group>";
|
||||
@@ -335,19 +346,22 @@
|
||||
CE6044EB0FE6796200B71262 /* DetailsPanel.m */,
|
||||
CE80DB850FC1951C0086DCA6 /* DirectoryPanel.h */,
|
||||
CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */,
|
||||
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
|
||||
CE9EA76F1122CA0B008CD2BC /* DirectoryOutline.h */,
|
||||
CE9EA7701122CA0B008CD2BC /* DirectoryOutline.m */,
|
||||
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
|
||||
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */,
|
||||
CE0C2ABA1177014200BC749F /* ProblemDialog.h */,
|
||||
CE0C2ABB1177014200BC749F /* ProblemDialog.m */,
|
||||
CE80DB880FC1951C0086DCA6 /* ResultWindow.h */,
|
||||
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */,
|
||||
CE958658112C516400F95FD2 /* PyResultTree.h */,
|
||||
CE95865A112C516400F95FD2 /* ResultOutline.h */,
|
||||
CE95865B112C516400F95FD2 /* ResultOutline.m */,
|
||||
CE958659112C516400F95FD2 /* PyStatsLabel.h */,
|
||||
CE95865C112C516400F95FD2 /* StatsLabel.h */,
|
||||
CE95865D112C516400F95FD2 /* StatsLabel.m */,
|
||||
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
|
||||
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */,
|
||||
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
|
||||
CE0C2ABC1177014200BC749F /* PyProblemDialog.h */,
|
||||
CE958659112C516400F95FD2 /* PyStatsLabel.h */,
|
||||
);
|
||||
name = dgbase;
|
||||
sourceTree = "<group>";
|
||||
@@ -359,6 +373,8 @@
|
||||
CE9EA7441122C96C008CD2BC /* HSGUIController.m */,
|
||||
CE9EA7451122C96C008CD2BC /* HSOutline.h */,
|
||||
CE9EA7461122C96C008CD2BC /* HSOutline.m */,
|
||||
CE0C2AB41177011000BC749F /* HSTable.h */,
|
||||
CE0C2AB51177011000BC749F /* HSTable.m */,
|
||||
CE9EA7471122C96C008CD2BC /* HSWindowController.h */,
|
||||
CE9EA7481122C96C008CD2BC /* HSWindowController.m */,
|
||||
);
|
||||
@@ -371,6 +387,7 @@
|
||||
children = (
|
||||
CE9EA74C1122C96C008CD2BC /* PyGUI.h */,
|
||||
CE9EA74D1122C96C008CD2BC /* PyOutline.h */,
|
||||
CE0C2AAA117700E700BC749F /* PyTable.h */,
|
||||
);
|
||||
name = proxies;
|
||||
path = ../../cocoalib/proxies;
|
||||
@@ -470,6 +487,7 @@
|
||||
CE7AC9181119911200D02F6C /* ErrorReportWindow.xib in Resources */,
|
||||
CE7AC9191119911200D02F6C /* progress.xib in Resources */,
|
||||
CE7AC91A1119911200D02F6C /* registration.xib in Resources */,
|
||||
CE0C2AC81177021600BC749F /* ProblemDialog.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -509,6 +527,8 @@
|
||||
CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */,
|
||||
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */,
|
||||
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */,
|
||||
CE0C2AB61177011000BC749F /* HSTable.m in Sources */,
|
||||
CE0C2ABD1177014200BC749F /* ProblemDialog.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>hsft</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.10.0</string>
|
||||
<string>2.10.1</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsutil.cocoa import signature
|
||||
from hscommon.cocoa import signature
|
||||
|
||||
from core import scanner
|
||||
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
||||
|
||||
@@ -15,11 +15,11 @@ import subprocess
|
||||
import re
|
||||
|
||||
from send2trash import send2trash
|
||||
from hscommon.reg import RegistrableApplication, RegistrationRequired
|
||||
from hscommon.notify import Broadcaster
|
||||
from hsutil import io, files
|
||||
from hsutil.path import Path
|
||||
from hsutil.reg import RegistrableApplication, RegistrationRequired
|
||||
from hsutil.misc import flatten, first
|
||||
from hsutil.notify import Broadcaster
|
||||
from hsutil.str import escape
|
||||
|
||||
from . import directories, results, scanner, export, fs
|
||||
@@ -88,7 +88,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
||||
try:
|
||||
for file in j.iter_with_progress(files, 'Reading metadata %d/%d'):
|
||||
file._read_all_info(attrnames=self.data.METADATA_TO_READ)
|
||||
except OSError:
|
||||
except (OSError, IOError):
|
||||
# If this error is raised, it means that a file was deleted while we were reading
|
||||
# metadata. Proper handling of this rare occurrence is complex because there's no easy
|
||||
# way to remove an arbitrary file from the Results. Thus, we simply clear them.
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
import logging
|
||||
import os.path as op
|
||||
|
||||
from hsutil import cocoa, job
|
||||
from hsutil.cocoa import install_exception_hook
|
||||
from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
|
||||
from hscommon import cocoa, job
|
||||
from hscommon.cocoa import install_exception_hook
|
||||
from hscommon.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
|
||||
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
|
||||
NSWorkspace)
|
||||
from hsutil.reg import RegistrationRequired
|
||||
from hscommon.reg import RegistrationRequired
|
||||
|
||||
from . import app
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# Common interface for all editions' dg_cocoa unit.
|
||||
|
||||
from hsutil.cocoa.inter import signature, PyTable, PyOutline, PyGUIObject, PyRegistrable
|
||||
from hscommon.cocoa.inter import signature, PyTable, PyOutline, PyGUIObject, PyRegistrable
|
||||
|
||||
from .gui.details_panel import DetailsPanel
|
||||
from .gui.directory_tree import DirectoryTree
|
||||
|
||||
@@ -16,7 +16,7 @@ from unicodedata import normalize
|
||||
|
||||
from hsutil.misc import flatten
|
||||
from hsutil.str import multi_replace
|
||||
from hsutil import job
|
||||
from hscommon import job
|
||||
|
||||
(WEIGHT_WORDS,
|
||||
MATCH_SIMILAR_WORDS,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsutil.notify import Listener
|
||||
from hscommon.notify import Listener
|
||||
|
||||
class GUIObject(Listener):
|
||||
def __init__(self, view, app):
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsutil.notify import Broadcaster
|
||||
from hscommon.notify import Broadcaster
|
||||
|
||||
from .base import GUIObject
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsutil.notify import Listener
|
||||
from hscommon.notify import Listener
|
||||
from hsgui.table import GUITable, Row
|
||||
|
||||
class ProblemTable(GUITable, Listener):
|
||||
|
||||
@@ -11,8 +11,8 @@ import re
|
||||
from lxml import etree
|
||||
|
||||
from . import engine
|
||||
from hsutil.job import nulljob
|
||||
from hsutil.markable import Markable
|
||||
from hscommon.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
|
||||
@@ -284,9 +284,12 @@ class Results(Markable):
|
||||
except AttributeError:
|
||||
words = ()
|
||||
file_elem = etree.SubElement(group_elem, 'file')
|
||||
file_elem.set('path', unicode(d.path))
|
||||
try:
|
||||
file_elem.set('path', unicode(d.path))
|
||||
file_elem.set('words', ','.join(words))
|
||||
except ValueError: # If there's an invalid character, just skip the file
|
||||
file_elem.set('path', '')
|
||||
file_elem.set('is_ref', ('y' if d.is_ref else 'n'))
|
||||
file_elem.set('words', ','.join(words))
|
||||
file_elem.set('marked', ('y' if self.is_marked(d) else 'n'))
|
||||
for match in g.matches:
|
||||
match_elem = etree.SubElement(group_elem, 'match')
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
import logging
|
||||
|
||||
|
||||
from hsutil import job, io
|
||||
from hscommon import job
|
||||
from hsutil import io
|
||||
from hsutil.misc import dedupe
|
||||
from hsutil.str import get_file_ext, rem_file_ext
|
||||
|
||||
|
||||
@@ -9,14 +9,13 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
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 hsutil.job import nulljob
|
||||
from hscommon.job import nulljob
|
||||
|
||||
from . import data
|
||||
from .results_test import GetTestGroups
|
||||
|
||||
28
core/tests/conftest.py
Normal file
28
core/tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- 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()
|
||||
@@ -10,10 +10,9 @@ import os.path as op
|
||||
import os
|
||||
import time
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
from hsutil import io
|
||||
from hsutil.path import Path
|
||||
from hsutil.testutil import eq_
|
||||
from hsutil.testcase import TestCase
|
||||
|
||||
from ..directories import *
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
import sys
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
from hsutil import job
|
||||
from hscommon import job
|
||||
from hsutil.decorators import log_calls
|
||||
from hsutil.misc import first
|
||||
from hsutil.testutil import eq_
|
||||
from hsutil.testcase import TestCase
|
||||
|
||||
from .. import engine, fs
|
||||
from .. import engine
|
||||
from ..engine import *
|
||||
|
||||
class NamedObject(object):
|
||||
@@ -46,6 +46,15 @@ def get_test_group():
|
||||
result.add_match(m3)
|
||||
return result
|
||||
|
||||
def assert_match(m, name1, name2):
|
||||
# When testing matches, whether objects are in first or second position very often doesn't
|
||||
# matter. This function makes this test more convenient.
|
||||
if m.first.name == name1:
|
||||
eq_(m.second.name, name2)
|
||||
else:
|
||||
eq_(m.first.name, name2)
|
||||
eq_(m.second.name, name1)
|
||||
|
||||
class TCgetwords(TestCase):
|
||||
def test_spaces(self):
|
||||
self.assertEqual(['a', 'b', 'c', 'd'], getwords("a b c d"))
|
||||
@@ -351,23 +360,18 @@ class GetMatches(TestCase):
|
||||
l = [NamedObject("foo bar"),NamedObject("bar bleh"),NamedObject("a b c foo")]
|
||||
r = getmatches(l)
|
||||
self.assertEqual(2,len(r))
|
||||
seek = [m for m in r if m.percentage == 50] #"foo bar" and "bar bleh"
|
||||
m = seek[0]
|
||||
self.assertEqual(['foo','bar'],m.first.words)
|
||||
self.assertEqual(['bar','bleh'],m.second.words)
|
||||
seek = [m for m in r if m.percentage == 33] #"foo bar" and "a b c foo"
|
||||
m = seek[0]
|
||||
self.assertEqual(['foo','bar'],m.first.words)
|
||||
self.assertEqual(['a','b','c','foo'],m.second.words)
|
||||
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"
|
||||
assert_match(m, 'foo bar', 'a b c foo')
|
||||
|
||||
def test_null_and_unrelated_objects(self):
|
||||
l = [NamedObject("foo bar"),NamedObject("bar bleh"),NamedObject(""),NamedObject("unrelated object")]
|
||||
r = getmatches(l)
|
||||
self.assertEqual(1,len(r))
|
||||
eq_(len(r), 1)
|
||||
m = r[0]
|
||||
self.assertEqual(50,m.percentage)
|
||||
self.assertEqual(['foo','bar'],m.first.words)
|
||||
self.assertEqual(['bar','bleh'],m.second.words)
|
||||
eq_(m.percentage, 50)
|
||||
assert_match(m, 'foo bar', 'bar bleh')
|
||||
|
||||
def test_twice_the_same_word(self):
|
||||
l = [NamedObject("foo foo bar"),NamedObject("bar bleh")]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import cStringIO
|
||||
from lxml import etree
|
||||
|
||||
from nose.tools import eq_
|
||||
from hsutil.testutil import eq_
|
||||
|
||||
from ..ignore import *
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ import StringIO
|
||||
import os.path as op
|
||||
|
||||
from lxml import etree
|
||||
from nose.tools import eq_
|
||||
|
||||
from hsutil.path import Path
|
||||
from hsutil.testutil import eq_
|
||||
from hsutil.testcase import TestCase
|
||||
from hsutil.misc import first
|
||||
|
||||
@@ -575,6 +575,12 @@ class TCResultsXML(TestCase):
|
||||
self.results.apply_filter(u'basepath')
|
||||
eq_(len(self.results.groups), 2)
|
||||
|
||||
def test_save_xml_with_invalid_characters(self):
|
||||
# Don't crash when saving files that have invalid xml characters in their path
|
||||
self.objects[0].name = u'foo\x19'
|
||||
self.results.save_to_xml(StringIO.StringIO()) # don't crash
|
||||
|
||||
|
||||
class TCResultsFilter(TestCase):
|
||||
def setUp(self):
|
||||
self.results = Results(data)
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
from hsutil import job, io
|
||||
from hscommon import job
|
||||
from hsutil import io
|
||||
from hsutil.path import Path
|
||||
from hsutil.testutil import eq_
|
||||
from hsutil.testcase import TestCase
|
||||
|
||||
from .. import fs
|
||||
|
||||
@@ -10,7 +10,7 @@ import logging
|
||||
from appscript import app, k, CommandError
|
||||
import time
|
||||
|
||||
from hsutil.cocoa import as_fetch
|
||||
from hscommon.cocoa import as_fetch
|
||||
|
||||
from core.app_cocoa import JOBID2TITLE, DupeGuru as DupeGuruBase
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# which should be included with this package. The terms are also available at
|
||||
# http://www.hardcoded.net/licenses/hs_license
|
||||
|
||||
from hsmedia import mpeg, wma, mp4, ogg, flac, aiff
|
||||
from hsaudiotag import mpeg, wma, mp4, ogg, flac, aiff
|
||||
from hsutil.str import get_file_ext
|
||||
from core import fs
|
||||
|
||||
|
||||
28
core_me/tests/conftest.py
Normal file
28
core_me/tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- 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()
|
||||
@@ -15,8 +15,8 @@ from appscript import app, k, CommandError
|
||||
from hsutil import io
|
||||
from hsutil.str import get_file_ext
|
||||
from hsutil.path import Path
|
||||
from hsutil.cocoa import as_fetch
|
||||
from hsutil.cocoa.objcmin import NSUserDefaults, NSURL
|
||||
from hscommon.cocoa import as_fetch
|
||||
from hscommon.cocoa.objcmin import NSUserDefaults, NSURL
|
||||
|
||||
from core import fs
|
||||
from core import app_cocoa, directories
|
||||
|
||||
@@ -8,11 +8,9 @@
|
||||
|
||||
import logging
|
||||
import multiprocessing
|
||||
from Queue import Empty
|
||||
from collections import defaultdict
|
||||
from collections import defaultdict, deque
|
||||
|
||||
from hsutil import job
|
||||
from hsutil.misc import dedupe
|
||||
from hscommon import job
|
||||
|
||||
from core.engine import Match
|
||||
from .block import avgdiff, DifferentBlockCountError, NoBlocksError
|
||||
@@ -42,7 +40,7 @@ def prepare_pictures(pictures, cache_path, j=job.nulljob):
|
||||
blocks = picture.get_blocks(BLOCK_COUNT_PER_SIDE)
|
||||
cache[picture.unicode_path] = blocks
|
||||
prepared.append(picture)
|
||||
except IOError as e:
|
||||
except (IOError, ValueError) as e:
|
||||
logging.warning(unicode(e))
|
||||
except MemoryError:
|
||||
logging.warning(u'Ran out of memory while reading %s of size %d' % (picture.unicode_path, picture.size))
|
||||
@@ -76,13 +74,6 @@ def async_compare(ref_id, other_ids, dbname, threshold):
|
||||
return results
|
||||
|
||||
def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nulljob):
|
||||
def empty_out_queue(queue, into):
|
||||
try:
|
||||
while True:
|
||||
into.append(queue.get(block=False))
|
||||
except Empty:
|
||||
pass
|
||||
|
||||
j = j.start_subjob([3, 7])
|
||||
pictures = prepare_pictures(pictures, cache_path, j)
|
||||
j = j.start_subjob([9, 1], 'Preparing for matching')
|
||||
@@ -100,7 +91,7 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
|
||||
cache.close()
|
||||
pictures = [p for p in pictures if hasattr(p, 'cache_id')]
|
||||
pool = multiprocessing.Pool()
|
||||
async_results = []
|
||||
async_results = deque()
|
||||
matches = []
|
||||
pictures_copy = set(pictures)
|
||||
for ref in j.iter_with_progress(pictures, 'Matched %d/%d pictures'):
|
||||
@@ -118,8 +109,10 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
|
||||
args = (ref.cache_id, cache_ids[:ARG_LIMIT], cache_path, threshold)
|
||||
async_results.append(pool.apply_async(async_compare, args))
|
||||
cache_ids = cache_ids[ARG_LIMIT:]
|
||||
if len(async_results) > RESULTS_QUEUE_LIMIT:
|
||||
result = async_results.pop(0)
|
||||
# We use a while here because it's possible that more than one result has been added if
|
||||
# ARG_LIMIT has been reached.
|
||||
while len(async_results) > RESULTS_QUEUE_LIMIT:
|
||||
result = async_results.popleft()
|
||||
matches.extend(result.get())
|
||||
for result in async_results: # process the rest of the results
|
||||
matches.extend(result.get())
|
||||
|
||||
@@ -158,6 +158,11 @@ static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PySequence_Length(path) == 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "empty path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_path = pystring2cfstring(path);
|
||||
if (image_path == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
|
||||
28
core_pe/tests/conftest.py
Normal file
28
core_pe/tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- 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()
|
||||
@@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from hsutil import io
|
||||
from hsutil.path import Path
|
||||
from hsutil.cocoa.objcmin import NSWorkspace
|
||||
from hscommon.cocoa.objcmin import NSWorkspace
|
||||
|
||||
from core import fs
|
||||
from core.app_cocoa import DupeGuru as DupeGuruBase
|
||||
|
||||
28
core_se/tests/conftest.py
Normal file
28
core_se/tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- 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()
|
||||
@@ -9,9 +9,8 @@
|
||||
|
||||
import hashlib
|
||||
|
||||
from nose.tools import eq_
|
||||
|
||||
from hsutil.testcase import TestCase
|
||||
from hsutil.testutil import eq_
|
||||
from core.fs import File
|
||||
from core.tests.directories_test import create_fake_fs
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
Copyright 2010 Hardcoded Software Inc. (http://www.hardcoded.net)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Hardcoded Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
* If the source code has been published less than two years ago, any redistribution, in whole or in part, must retain full licensing functionality, without any attempt to change, obscure or in other ways circumvent its intent.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,3 +1,13 @@
|
||||
- date: 2010-07-16
|
||||
version: 5.8.1
|
||||
description: |
|
||||
* Fixed a couple of crashes. (#95, #97, #100)
|
||||
- date: 2010-04-14
|
||||
version: 5.8.0
|
||||
description: |
|
||||
* Improved error messages when files can't be sent to trash, moved or copied.
|
||||
* Added a custom command invocation action. (#12)
|
||||
* Filters are now applied on whole paths. (#4)
|
||||
- date: 2010-02-13
|
||||
version: 5.7.2
|
||||
description: |
|
||||
|
||||
6
help_me/conf.yaml
Normal file
6
help_me/conf.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
base:
|
||||
pages: en/pages.yaml
|
||||
skeleton: skeleton
|
||||
changelog: changelog.yaml
|
||||
tixurl: "https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}"
|
||||
firstpage_meta: "<meta name=\"AppleTitle\" content=\"dupeGuru Help\"></meta>"
|
||||
26
help_me/en/credits.md
Normal file
26
help_me/en/credits.md
Normal file
@@ -0,0 +1,26 @@
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
**Virgil Dupras, Developer**<br/>
|
||||
<http://www.hardcoded.net>
|
||||
|
||||
**Jérôme Cantin, Icon designer**<br/>
|
||||
Icons in dupeGuru are from him
|
||||
|
||||
**Python, Programming language**<br/>
|
||||
The bestest of the bests<br/>
|
||||
<http://www.python.org>
|
||||
|
||||
**PyObjC, Python-to-Cocoa bridge**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://pyobjc.sourceforge.net>
|
||||
|
||||
**PyQt, Python-to-Qt bridge**<br/>
|
||||
Used for the Windows version<br/>
|
||||
<http://www.riverbankcomputing.co.uk>
|
||||
|
||||
**Sparkle, Auto-update library**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://andymatuschak.org/pages/sparkle>
|
||||
|
||||
**You, dupeGuru user**<br/>
|
||||
You rock.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Directories'
|
||||
selected_menu_item = 'Directories'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
There is a panel in dupeGuru called **Directories**. You can open it by clicking on the **Directories** button. This directory contains the list of the directories that will be scanned when you click on **Start Scanning**.
|
||||
|
||||
This panel is quite straightforward to use. If you want to add a directory, click on **Add**. If you added directories before, a popup menu with a list of recent directories you added will pop. You can click on one of them to add it directly to your list. If you click on the first item of the popup menu, **Add New Directory...**, you will be prompted for a directory to add. If you never added a directory, no menu will pop and you will directly be prompted for a new directory to add.
|
||||
@@ -1,10 +1,3 @@
|
||||
<%!
|
||||
title = 'dupeGuru ME F.A.Q.'
|
||||
selected_menu_item = 'F.A.Q.'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
<%text filter="md">
|
||||
### What is dupeGuru Music Edition?
|
||||
|
||||
dupeGuru Music Edition is a tool to find duplicate songs in your music collection. It can base its scan on filenames, tags or content. The filename and tag scans feature a fuzzy matching algorithm that can find duplicate filenames or tags even when they are not exactly the same.
|
||||
@@ -72,4 +65,3 @@ Most of the time, the reason why dupeGuru can't send files to Trash is because o
|
||||
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
|
||||
|
||||
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
|
||||
</%text>
|
||||
@@ -1,13 +1,5 @@
|
||||
<%!
|
||||
title = 'Introduction to dupeGuru ME'
|
||||
selected_menu_item = 'introduction'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
dupeGuru Music Edition is a tool to find duplicate files on your computer. It can scan either filenames or contents. The filename scan features a fuzzy matching algorithm that can find duplicate filenames even when they are not exactly the same.
|
||||
|
||||
Although dupeGuru can easily be used without documentation, reading this file will help you to master it. If you are looking for guidance for your first duplicate scan, you can take a look at the [Quick Start](quick_start.htm) section.
|
||||
|
||||
It is a good idea to keep dupeGuru updated. You can download the latest version on the [dupeGuru ME homepage](http://www.hardcoded.net/dupeguru_me/).
|
||||
|
||||
<%def name="meta()"><meta name="AppleTitle" content="dupeGuru ME Help"></meta></%def>
|
||||
45
help_me/en/pages.yaml
Normal file
45
help_me/en/pages.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
-
|
||||
name: intro
|
||||
title: Introduction to dupeGuru ME
|
||||
menutitle: Introduction
|
||||
menudesc: Introduction to dupeGuru
|
||||
-
|
||||
name: quick_start
|
||||
title: Quick Start
|
||||
menutitle: Quick Start
|
||||
menudesc: Quickly get into the action
|
||||
-
|
||||
name: directories
|
||||
title: Directories
|
||||
menutitle: Directories
|
||||
menudesc: Managing dupeGuru directories
|
||||
-
|
||||
name: preferences
|
||||
title: Preferences
|
||||
menutitle: Preferences
|
||||
menudesc: Setting dupeGuru preferences
|
||||
-
|
||||
name: results
|
||||
title: Results
|
||||
menutitle: Results
|
||||
menudesc: Time to delete these duplicates!
|
||||
-
|
||||
name: power_marker
|
||||
title: Power Marker
|
||||
menutitle: Power Marker
|
||||
menudesc: Take control of your duplicates
|
||||
-
|
||||
name: faq
|
||||
title: Frequently Asked Questions
|
||||
menutitle: F.A.Q.
|
||||
menudesc: Frequently Asked Questions
|
||||
-
|
||||
name: versions
|
||||
title: Version History
|
||||
menutitle: Version History
|
||||
menudesc: Changes moneyGuru went through
|
||||
-
|
||||
name: credits
|
||||
title: Credits
|
||||
menutitle: Credits
|
||||
menudesc: People who contributed to dupeGuru
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Power Marker'
|
||||
selected_menu_item = 'Power Marker'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
You will probably not use the Power Marker feature very often, but if you get into a situation where you need it, you will be pretty happy that this feature exists.
|
||||
|
||||
What is it?
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Preferences'
|
||||
selected_menu_item = 'Preferences'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
**Scan Type:** This option determines what aspect of the files will be compared in the duplicate scan. The nature of the duplicate scan varies greatly depending on what you select for this option.
|
||||
|
||||
* **Filename:** Every song will have its filename split into words, and then every word will be compared to compute a matching percentage. If this percentage is higher or equal to the **Filter Hardness** (see below for more details), dupeGuru will consider the 2 songs duplicates.
|
||||
@@ -34,3 +28,11 @@
|
||||
* **Recreate absolute path:** The source file's path will be re-created in the destination directory in it's entirety. For example, if you move "/Users/foobar/Music/Artist/Album/the_song.mp3" to the destination "/Users/foobar/MyDestination", the final destination for the file will be "/Users/foobar/MyDestination/Users/foobar/Music/Artist/Album".
|
||||
|
||||
In all cases, dupeGuru nicely handles naming conflicts by prepending a number to the destination filename if the filename already exists in the destination.
|
||||
|
||||
**Custom Command:** This preference determines the command that will be invoked by the "Invoke Custom Command" action. You can invoke any external application through this action. This can be useful if, for example, you have a nice diffing application installed.
|
||||
|
||||
The format of the command is the same as what you would write in the command line, except that there are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the selected dupe (%d) and the path of the selected dupe's reference file (%r).
|
||||
|
||||
If the path to your executable contains space characters, you should enclose it in "" quotes. You should also enclose placeholders in quotes because it's very possible that paths to dupes and refs will contain spaces. Here's an example custom command:
|
||||
|
||||
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Quick Start'
|
||||
selected_menu_item = 'Quick Start'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
To get you quickly started with dupeGuru, let's just make a standard scan using default preferences.
|
||||
|
||||
* Click on **Directories**.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Results'
|
||||
selected_menu_item = 'Results'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
When dupeGuru is finished scanning for duplicates, it will show its results in the form of duplicate group list.
|
||||
|
||||
About duplicate groups
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'dupeGuru ME version history'
|
||||
selected_menu_item = 'Version History'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
A large part of this version history is not serious (especially before v3), but it is always interesting to remember that I learnt most of what I know about designing/implementing/supporting a software through that.
|
||||
|
||||
${self.output_changelogs(changelog)}
|
||||
{changelog}
|
||||
@@ -1,14 +0,0 @@
|
||||
<%inherit file="/base_help.mako"/>
|
||||
${next.body()}
|
||||
|
||||
<%def name="menu()"><%
|
||||
self.menuitem('intro.htm', 'Introduction', 'Introduction to dupeGuru')
|
||||
self.menuitem('quick_start.htm', 'Quick Start', 'Quickly get into the action')
|
||||
self.menuitem('directories.htm', 'Directories', 'Managing dupeGuru directories')
|
||||
self.menuitem('preferences.htm', 'Preferences', 'Setting dupeGuru preferences')
|
||||
self.menuitem('results.htm', 'Results', 'Time to delete these duplicates!')
|
||||
self.menuitem('power_marker.htm', 'Power Marker', 'Take control of your duplicates')
|
||||
self.menuitem('faq.htm', 'F.A.Q.', 'Frequently Asked Questions')
|
||||
self.menuitem('versions.htm', 'Version History', 'Changes dupeGuru went through')
|
||||
self.menuitem('credits.htm', 'Credits', 'People who contributed to dupeGuru')
|
||||
%></%def>
|
||||
@@ -1,20 +0,0 @@
|
||||
<%!
|
||||
title = 'Credits'
|
||||
selected_menu_item = 'Credits'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
${self.credit('Virgil Dupras', 'Developer', "That's me, Hardcoded Software founder", 'www.hardcoded.net', 'hsoft@hardcoded.net')}
|
||||
|
||||
${self.credit('Python', 'Programming language', "The bestest of the bests", 'www.python.org')}
|
||||
|
||||
${self.credit('PyObjC', 'Python-to-Cocoa bridge', "Used for the Mac OS X version", 'pyobjc.sourceforge.net')}
|
||||
|
||||
${self.credit('PyQt', 'Python-to-Qt bridge', "Used for the Windows version", 'www.riverbankcomputing.co.uk')}
|
||||
|
||||
${self.credit('Qt', 'GUI Toolkit', "Used for the Windows version", 'www.qtsoftware.com')}
|
||||
|
||||
${self.credit('Sparkle', 'Auto-update library', "Used for the Mac OS X version", 'andymatuschak.org/pages/sparkle')}
|
||||
|
||||
${self.credit('You', 'dupeGuru user', "What would I do without you?")}
|
||||
@@ -1,11 +0,0 @@
|
||||
Copyright 2010 Hardcoded Software Inc. (http://www.hardcoded.net)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Hardcoded Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
* If the source code has been published less than two years ago, any redistribution, in whole or in part, must retain full licensing functionality, without any attempt to change, obscure or in other ways circumvent its intent.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,3 +1,13 @@
|
||||
- date: 2010-07-17
|
||||
version: 1.9.1
|
||||
description: |
|
||||
* Fixed a couple of crashes. (#95, #96, #97, #100)
|
||||
- date: 2010-04-15
|
||||
version: 1.9.0
|
||||
description: |
|
||||
* Improved error messages when files can't be sent to trash, moved or copied.
|
||||
* Added a custom command invocation action. (#12)
|
||||
* Filters are now applied on whole paths. (#4)
|
||||
- date: 2010-04-08
|
||||
version: 1.8.6
|
||||
description: |
|
||||
|
||||
6
help_pe/conf.yaml
Normal file
6
help_pe/conf.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
base:
|
||||
pages: en/pages.yaml
|
||||
skeleton: skeleton
|
||||
changelog: changelog.yaml
|
||||
tixurl: "https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}"
|
||||
firstpage_meta: "<meta name=\"AppleTitle\" content=\"dupeGuru Help\"></meta>"
|
||||
30
help_pe/en/credits.md
Normal file
30
help_pe/en/credits.md
Normal file
@@ -0,0 +1,30 @@
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
**Virgil Dupras, Developer**<br/>
|
||||
<http://www.hardcoded.net>
|
||||
|
||||
**Jérôme Cantin, Icon designer**<br/>
|
||||
Icons in dupeGuru are from him
|
||||
|
||||
**Python, Programming language**<br/>
|
||||
The bestest of the bests<br/>
|
||||
<http://www.python.org>
|
||||
|
||||
**PyObjC, Python-to-Cocoa bridge**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://pyobjc.sourceforge.net>
|
||||
|
||||
**PyQt, Python-to-Qt bridge**<br/>
|
||||
Used for the Windows version<br/>
|
||||
<http://www.riverbankcomputing.co.uk>
|
||||
|
||||
**Sparkle, Auto-update library**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://andymatuschak.org/pages/sparkle>
|
||||
|
||||
**Python Imaging Library, Picture analyzer**<br/>
|
||||
Used for the Windows version<br/>
|
||||
<http://www.pythonware.com/products/pil/>
|
||||
|
||||
**You, dupeGuru user**<br/>
|
||||
You rock.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Directories'
|
||||
selected_menu_item = 'Directories'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
There is a panel in dupeGuru called **Directories**. You can open it by clicking on the **Directories** button. This directory contains the list of the directories that will be scanned when you click on **Start Scanning**.
|
||||
|
||||
This panel is quite straightforward to use. If you want to add a directory, click on **Add**. If you added directories before, a popup menu with a list of recent directories you added will pop. You can click on one of them to add it directly to your list. If you click on the first item of the popup menu, **Add New Directory...**, you will be prompted for a directory to add. If you never added a directory, no menu will pop and you will directly be prompted for a new directory to add.
|
||||
@@ -1,10 +1,3 @@
|
||||
<%!
|
||||
title = 'dupeGuru F.A.Q.'
|
||||
selected_menu_item = 'F.A.Q.'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
<%text filter="md">
|
||||
### What is dupeGuru PE?
|
||||
|
||||
dupeGuru Picture Edition (PE for short) is a tool to find duplicate pictures on your computer. Not only can it find exact matches, but it can also find duplicates among pictures of different kind (PNG, JPG, GIF etc..) and quality.
|
||||
@@ -71,4 +64,3 @@ If dupeGuru still gives you troubles after fixing your permissions, there have b
|
||||
If you're trying to delete *iPhoto* pictures, then the reason for the failure is different. The deletion fails because dupeGuru can't communicate with iPhoto. Be aware that for the deletion to work correctly, you're not supposed to play around iPhoto while dupeGuru is working. Also, sometimes, the Applescript system doesn't seem to know where to find iPhoto to launch it. It might help in these cases to launch iPhoto *before* you send your duplicates to Trash.
|
||||
|
||||
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
|
||||
</%text>
|
||||
@@ -1,13 +1,5 @@
|
||||
<%!
|
||||
title = 'Introduction to dupeGuru PE'
|
||||
selected_menu_item = 'introduction'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
dupeGuru Picture Edition (PE for short) is a tool to find duplicate pictures on your computer. Not only can it find exact matches, but it can also find duplicates among pictures of different kind (PNG, JPG, GIF etc..) and quality.
|
||||
|
||||
Although dupeGuru can easily be used without documentation, reading this file will help you to master it. If you are looking for guidance for your first duplicate scan, you can take a look at the [Quick Start](quick_start.htm) section.
|
||||
|
||||
It is a good idea to keep dupeGuru PE updated. You can download the latest version on the [dupeGuru PE homepage](http://www.hardcoded.net/dupeguru_pe/).
|
||||
|
||||
<%def name="meta()"><meta name="AppleTitle" content="dupeGuru PE Help"></meta></%def>
|
||||
45
help_pe/en/pages.yaml
Normal file
45
help_pe/en/pages.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
-
|
||||
name: intro
|
||||
title: Introduction to dupeGuru PE
|
||||
menutitle: Introduction
|
||||
menudesc: Introduction to dupeGuru
|
||||
-
|
||||
name: quick_start
|
||||
title: Quick Start
|
||||
menutitle: Quick Start
|
||||
menudesc: Quickly get into the action
|
||||
-
|
||||
name: directories
|
||||
title: Directories
|
||||
menutitle: Directories
|
||||
menudesc: Managing dupeGuru directories
|
||||
-
|
||||
name: preferences
|
||||
title: Preferences
|
||||
menutitle: Preferences
|
||||
menudesc: Setting dupeGuru preferences
|
||||
-
|
||||
name: results
|
||||
title: Results
|
||||
menutitle: Results
|
||||
menudesc: Time to delete these duplicates!
|
||||
-
|
||||
name: power_marker
|
||||
title: Power Marker
|
||||
menutitle: Power Marker
|
||||
menudesc: Take control of your duplicates
|
||||
-
|
||||
name: faq
|
||||
title: Frequently Asked Questions
|
||||
menutitle: F.A.Q.
|
||||
menudesc: Frequently Asked Questions
|
||||
-
|
||||
name: versions
|
||||
title: Version History
|
||||
menutitle: Version History
|
||||
menudesc: Changes moneyGuru went through
|
||||
-
|
||||
name: credits
|
||||
title: Credits
|
||||
menutitle: Credits
|
||||
menudesc: People who contributed to dupeGuru
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Power Marker'
|
||||
selected_menu_item = 'Power Marker'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
You will probably not use the Power Marker feature very often, but if you get into a situation where you need it, you will be pretty happy that this feature exists.
|
||||
|
||||
What is it?
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Preferences'
|
||||
selected_menu_item = 'Preferences'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
**Filter Hardness:** The higher is this setting, the "harder" is the filter (In other words, the less results you get). Most pictures of the same quality match at 100% even if the format is different (PNG and JPG for example.). However, if you want to make a PNG match with a lower quality JPG, you will have to set the filer hardness to lower than 100. The default, 95, is a sweet spot.
|
||||
|
||||
**Match scaled pictures together:** If you check this box, pictures of different dimensions will be allowed in the same duplicate group.
|
||||
@@ -21,3 +15,11 @@
|
||||
* **Recreate absolute path:** The source file's path will be re-created in the destination directory in it's entirety. For example, if you move "/Users/foobar/Picture/2006/06/photo.jpg" to the destination "/Users/foobar/MyDestination", the final destination for the file will be "/Users/foobar/MyDestination/Users/foobar/Picture/2006/06".
|
||||
|
||||
In all cases, dupeGuru PE nicely handles naming conflicts by prepending a number to the destination filename if the filename already exists in the destination.
|
||||
|
||||
**Custom Command:** This preference determines the command that will be invoked by the "Invoke Custom Command" action. You can invoke any external application through this action. This can be useful if, for example, you have a nice diffing application installed.
|
||||
|
||||
The format of the command is the same as what you would write in the command line, except that there are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the selected dupe (%d) and the path of the selected dupe's reference file (%r).
|
||||
|
||||
If the path to your executable contains space characters, you should enclose it in "" quotes. You should also enclose placeholders in quotes because it's very possible that paths to dupes and refs will contain spaces. Here's an example custom command:
|
||||
|
||||
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Quick Start'
|
||||
selected_menu_item = 'Quick Start'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
To get you quickly started with dupeGuru, let's just make a standard scan using default preferences.
|
||||
|
||||
* Click on **Directories**.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Results'
|
||||
selected_menu_item = 'Results'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
When dupeGuru is finished scanning for duplicates, it will show its results in the form of duplicate group list.
|
||||
|
||||
About duplicate groups
|
||||
@@ -70,4 +64,5 @@ Action Menu
|
||||
* **Add Selected to Ignore List:** This first removes all selected duplicates from results, and then add the match of that duplicate and the current reference in the ignore list. This match will not come up again in further scan. The duplicate itself might come back, but it will be matched with another reference file. You can clear the ignore list with the Clear Ignore List command.
|
||||
* **Open Selected with Default Application:** Open the file with the application associated with selected file's type.
|
||||
* **Reveal Selected in Finder:** Open the folder containing selected file.
|
||||
* **Invoke Custom Command:** Invokes the external application you've set up in your preferences using the current selection as arguments in the invocation.
|
||||
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.
|
||||
1
help_pe/en/versions.md
Normal file
1
help_pe/en/versions.md
Normal file
@@ -0,0 +1 @@
|
||||
{changelog}
|
||||
@@ -1,14 +0,0 @@
|
||||
<%inherit file="/base_help.mako"/>
|
||||
${next.body()}
|
||||
|
||||
<%def name="menu()"><%
|
||||
self.menuitem('intro.htm', 'Introduction', 'Introduction to dupeGuru')
|
||||
self.menuitem('quick_start.htm', 'Quick Start', 'Quickly get into the action')
|
||||
self.menuitem('directories.htm', 'Directories', 'Managing dupeGuru directories')
|
||||
self.menuitem('preferences.htm', 'Preferences', 'Setting dupeGuru preferences')
|
||||
self.menuitem('results.htm', 'Results', 'Time to delete these duplicates!')
|
||||
self.menuitem('power_marker.htm', 'Power Marker', 'Take control of your duplicates')
|
||||
self.menuitem('faq.htm', 'F.A.Q.', 'Frequently Asked Questions')
|
||||
self.menuitem('versions.htm', 'Version History', 'Changes dupeGuru went through')
|
||||
self.menuitem('credits.htm', 'Credits', 'People who contributed to dupeGuru')
|
||||
%></%def>
|
||||
@@ -1,25 +0,0 @@
|
||||
## -*- coding: utf-8 -*-
|
||||
<%!
|
||||
title = 'Credits'
|
||||
selected_menu_item = 'Credits'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
${self.credit('Virgil Dupras', 'Developer', "That's me, Hardcoded Software founder", 'www.hardcoded.net', 'hsoft@hardcoded.net')}
|
||||
|
||||
${self.credit(u'Jérôme Cantin', u'Icon designer', u"Icons in dupeGuru are from him")}
|
||||
|
||||
${self.credit('Python', 'Programming language', "The bestest of the bests", 'www.python.org')}
|
||||
|
||||
${self.credit('PyObjC', 'Python-to-Cocoa bridge', "Used for the Mac OS X version", 'pyobjc.sourceforge.net')}
|
||||
|
||||
${self.credit('PyQt', 'Python-to-Qt bridge', "Used for the Windows version", 'www.riverbankcomputing.co.uk')}
|
||||
|
||||
${self.credit('Qt', 'GUI Toolkit', "Used for the Windows version", 'www.qtsoftware.com')}
|
||||
|
||||
${self.credit('Sparkle', 'Auto-update library', "Used for the Mac OS X version", 'andymatuschak.org/pages/sparkle')}
|
||||
|
||||
${self.credit('Python Imaging Library', 'Picture analyzer', "Used for the Windows version", 'www.pythonware.com/products/pil/')}
|
||||
|
||||
${self.credit('You', 'dupeGuru user', "What would I do without you?")}
|
||||
@@ -1,6 +0,0 @@
|
||||
<%!
|
||||
title = 'dupeGuru PE version history'
|
||||
selected_menu_item = 'Version History'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
${self.output_changelogs(changelog)}
|
||||
@@ -1,11 +0,0 @@
|
||||
Copyright 2010 Hardcoded Software Inc. (http://www.hardcoded.net)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Hardcoded Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
* If the source code has been published less than two years ago, any redistribution, in whole or in part, must retain full licensing functionality, without any attempt to change, obscure or in other ways circumvent its intent.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,3 +1,7 @@
|
||||
- date: 2010-07-15
|
||||
version: 2.10.1
|
||||
description: |
|
||||
* Fixed a couple of crashes. (#95, #97, #100)
|
||||
- date: 2010-04-13
|
||||
version: 2.10.0
|
||||
description: |
|
||||
|
||||
6
help_se/conf.yaml
Normal file
6
help_se/conf.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
base:
|
||||
pages: en/pages.yaml
|
||||
skeleton: skeleton
|
||||
changelog: changelog.yaml
|
||||
tixurl: "https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}"
|
||||
firstpage_meta: "<meta name=\"AppleTitle\" content=\"dupeGuru Help\"></meta>"
|
||||
26
help_se/en/credits.md
Normal file
26
help_se/en/credits.md
Normal file
@@ -0,0 +1,26 @@
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
**Virgil Dupras, Developer**<br/>
|
||||
<http://www.hardcoded.net>
|
||||
|
||||
**Jérôme Cantin, Icon designer**<br/>
|
||||
Icons in dupeGuru are from him
|
||||
|
||||
**Python, Programming language**<br/>
|
||||
The bestest of the bests<br/>
|
||||
<http://www.python.org>
|
||||
|
||||
**PyObjC, Python-to-Cocoa bridge**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://pyobjc.sourceforge.net>
|
||||
|
||||
**PyQt, Python-to-Qt bridge**<br/>
|
||||
Used for the Windows version<br/>
|
||||
<http://www.riverbankcomputing.co.uk>
|
||||
|
||||
**Sparkle, Auto-update library**<br/>
|
||||
Used for the Mac OS X version<br/>
|
||||
<http://andymatuschak.org/pages/sparkle>
|
||||
|
||||
**You, dupeGuru user**<br/>
|
||||
You rock.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Directories'
|
||||
selected_menu_item = 'Directories'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
There is a panel in dupeGuru called **Directories**. You can open it by clicking on the **Directories** button. This directory contains the list of the directories that will be scanned when you click on **Start Scanning**.
|
||||
|
||||
This panel is quite straightforward to use. If you want to add a directory, click on **Add**. If you added directories before, a popup menu with a list of recent directories you added will pop. You can click on one of them to add it directly to your list. If you click on the first item of the popup menu, **Add New Directory...**, you will be prompted for a directory to add. If you never added a directory, no menu will pop and you will directly be prompted for a new directory to add.
|
||||
@@ -1,10 +1,3 @@
|
||||
<%!
|
||||
title = 'dupeGuru F.A.Q.'
|
||||
selected_menu_item = 'F.A.Q.'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
<%text filter="md">
|
||||
### What is dupeGuru?
|
||||
|
||||
dupeGuru is a tool to find duplicate files on your computer. It can scan either filenames or content. The filename scan features a fuzzy matching algorithm that can find duplicate filenames even when they are not exactly the same.
|
||||
@@ -69,4 +62,3 @@ Most of the time, the reason why dupeGuru can't send files to Trash is because o
|
||||
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
|
||||
|
||||
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
|
||||
</%text>
|
||||
@@ -1,13 +1,5 @@
|
||||
<%!
|
||||
title = 'Introduction to dupeGuru'
|
||||
selected_menu_item = 'introduction'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
dupeGuru is a tool to find duplicate files on your computer. It can scan either filenames or contents. The filename scan features a fuzzy matching algorithm that can find duplicate filenames even when they are not exactly the same.
|
||||
|
||||
Although dupeGuru can easily be used without documentation, reading this file will help you to master it. If you are looking for guidance for your first duplicate scan, you can take a look at the [Quick Start](quick_start.htm) section.
|
||||
|
||||
It is a good idea to keep dupeGuru updated. You can download the latest version on the [dupeGuru homepage](http://www.hardcoded.net/dupeguru/).
|
||||
|
||||
<%def name="meta()"><meta name="AppleTitle" content="dupeGuru Help"></meta></%def>
|
||||
45
help_se/en/pages.yaml
Normal file
45
help_se/en/pages.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
-
|
||||
name: intro
|
||||
title: Introduction to dupeGuru
|
||||
menutitle: Introduction
|
||||
menudesc: Introduction to dupeGuru
|
||||
-
|
||||
name: quick_start
|
||||
title: Quick Start
|
||||
menutitle: Quick Start
|
||||
menudesc: Quickly get into the action
|
||||
-
|
||||
name: directories
|
||||
title: Directories
|
||||
menutitle: Directories
|
||||
menudesc: Managing dupeGuru directories
|
||||
-
|
||||
name: preferences
|
||||
title: Preferences
|
||||
menutitle: Preferences
|
||||
menudesc: Setting dupeGuru preferences
|
||||
-
|
||||
name: results
|
||||
title: Results
|
||||
menutitle: Results
|
||||
menudesc: Time to delete these duplicates!
|
||||
-
|
||||
name: power_marker
|
||||
title: Power Marker
|
||||
menutitle: Power Marker
|
||||
menudesc: Take control of your duplicates
|
||||
-
|
||||
name: faq
|
||||
title: Frequently Asked Questions
|
||||
menutitle: F.A.Q.
|
||||
menudesc: Frequently Asked Questions
|
||||
-
|
||||
name: versions
|
||||
title: Version History
|
||||
menutitle: Version History
|
||||
menudesc: Changes moneyGuru went through
|
||||
-
|
||||
name: credits
|
||||
title: Credits
|
||||
menutitle: Credits
|
||||
menudesc: People who contributed to dupeGuru
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Power Marker'
|
||||
selected_menu_item = 'Power Marker'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
You will probably not use the Power Marker feature very often, but if you get into a situation where you need it, you will be pretty happy that this feature exists.
|
||||
|
||||
What is it?
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Preferences'
|
||||
selected_menu_item = 'Preferences'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
**Scan Type:** This option determines what aspect of the files will be compared in the duplicate scan. If you select **Filename**, dupeGuru will compare every filenames word-by-word and, depending on the other settings below, it will determine if enough words are matching to consider 2 files duplicates. If you select **Content**, only files with the exact same content will match.
|
||||
|
||||
**Filter Hardness:** If you chose the **Filename** scan type, this option determines how similar two filenames must be for dupeGuru to consider them duplicates. If the filter hardness is, for example 80, it means that 80% of the words of two filenames must match. To determine the matching percentage, dupeGuru first counts the total number of words in **both** filenames, then count the number of words matching (every word matching count as 2), and then divide the number of words matching by the total number of words. If the result is higher or equal to the filter hardness, we have a duplicate match. For example, "a b c d" and "c d e" have a matching percentage of 57 (4 words matching, 7 total words).
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Quick Start'
|
||||
selected_menu_item = 'Quick Start'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
To get you quickly started with dupeGuru, let's just make a standard scan using default preferences.
|
||||
|
||||
* Click on **Directories**.
|
||||
@@ -1,9 +1,3 @@
|
||||
<%!
|
||||
title = 'Results'
|
||||
selected_menu_item = 'Results'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
|
||||
When dupeGuru is finished scanning for duplicates, it will show its results in the form of duplicate group list.
|
||||
|
||||
About duplicate groups
|
||||
@@ -70,4 +64,5 @@ Action Menu
|
||||
* **Add Selected to Ignore List:** This first removes all selected duplicates from results, and then add the match of that duplicate and the current reference in the ignore list. This match will not come up again in further scan. The duplicate itself might come back, but it will be matched with another reference file. You can clear the ignore list with the Clear Ignore List command.
|
||||
* **Open Selected with Default Application:** Open the file with the application associated with selected file's type.
|
||||
* **Reveal Selected in Finder:** Open the folder containing selected file.
|
||||
* **Invoke Custom Command:** Invokes the external application you've set up in your preferences using the current selection as arguments in the invocation.
|
||||
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.
|
||||
1
help_se/en/versions.md
Normal file
1
help_se/en/versions.md
Normal file
@@ -0,0 +1 @@
|
||||
{changelog}
|
||||
@@ -1,14 +0,0 @@
|
||||
<%inherit file="/base_help.mako"/>
|
||||
${next.body()}
|
||||
|
||||
<%def name="menu()"><%
|
||||
self.menuitem('intro.htm', 'Introduction', 'Introduction to dupeGuru')
|
||||
self.menuitem('quick_start.htm', 'Quick Start', 'Quickly get into the action')
|
||||
self.menuitem('directories.htm', 'Directories', 'Managing dupeGuru directories')
|
||||
self.menuitem('preferences.htm', 'Preferences', 'Setting dupeGuru preferences')
|
||||
self.menuitem('results.htm', 'Results', 'Time to delete these duplicates!')
|
||||
self.menuitem('power_marker.htm', 'Power Marker', 'Take control of your duplicates')
|
||||
self.menuitem('faq.htm', 'F.A.Q.', 'Frequently Asked Questions')
|
||||
self.menuitem('versions.htm', 'Version History', 'Changes dupeGuru went through')
|
||||
self.menuitem('credits.htm', 'Credits', 'People who contributed to dupeGuru')
|
||||
%></%def>
|
||||
@@ -1,20 +0,0 @@
|
||||
<%!
|
||||
title = 'Credits'
|
||||
selected_menu_item = 'Credits'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
Below is the list of people who contributed, directly or indirectly to dupeGuru.
|
||||
|
||||
${self.credit('Virgil Dupras', 'Developer', "That's me, Hardcoded Software founder", 'www.hardcoded.net', 'hsoft@hardcoded.net')}
|
||||
|
||||
${self.credit('Jerome', 'Icon designer', "Icons in dupeGuru are from him")}
|
||||
|
||||
${self.credit('Python', 'Programming language', "The bestest of the bests", 'www.python.org')}
|
||||
|
||||
${self.credit('PyObjC', 'Python-to-Cocoa bridge', "Used for the Mac OS X version", 'pyobjc.sourceforge.net')}
|
||||
|
||||
${self.credit('Python for .NET', 'Python-to-.NET bridge', "Used for the Windows version", 'sourceforge.net/projects/pythonnet/')}
|
||||
|
||||
${self.credit('Sparkle', 'Auto-update library', "Used for the Mac OS X version", 'andymatuschak.org/pages/sparkle')}
|
||||
|
||||
${self.credit('You', 'dupeGuru user', "What would I do without you?")}
|
||||
@@ -1,6 +0,0 @@
|
||||
<%!
|
||||
title = 'dupeGuru version history'
|
||||
selected_menu_item = 'Version History'
|
||||
%>
|
||||
<%inherit file="/base_dg.mako"/>
|
||||
${self.output_changelogs(changelog)}
|
||||
10
package.py
10
package.py
@@ -15,7 +15,7 @@ import shutil
|
||||
|
||||
import yaml
|
||||
|
||||
from hsutil.build import (build_dmg, add_to_pythonpath, print_and_do, copy_packages,
|
||||
from hscommon.build import (build_dmg, add_to_pythonpath, print_and_do, copy_packages,
|
||||
build_debian_changelog, copy_qt_plugins)
|
||||
|
||||
def package_cocoa(edition):
|
||||
@@ -84,14 +84,10 @@ def package_debian(edition):
|
||||
help_src = ed('help_{0}')
|
||||
os.makedirs(destpath)
|
||||
shutil.copytree(ed('qt/{0}'), srcpath)
|
||||
packages = ['hsutil', 'hsgui', 'core', ed('core_{0}'), 'qtlib', 'qt/base']
|
||||
packages = ['hscommon', 'hsgui', 'core', ed('core_{0}'), 'qtlib', 'qt/base', 'hsutil', 'send2trash']
|
||||
if edition == 'me':
|
||||
packages.append('hsmedia')
|
||||
packages.append('hsaudiotag')
|
||||
copy_packages(packages, srcpath)
|
||||
# We also have to copy the Send2Trash package
|
||||
import send2trash
|
||||
pkg_path = op.dirname(send2trash.__file__)
|
||||
shutil.copytree(pkg_path, op.join(srcpath, 'send2trash'))
|
||||
shutil.copytree(ed('debian_{0}'), op.join(destpath, 'debian'))
|
||||
yaml_path = op.join(help_src, 'changelog.yaml')
|
||||
changelog_dest = op.join(destpath, 'debian', 'changelog')
|
||||
|
||||
@@ -15,8 +15,8 @@ import os.path as op
|
||||
from PyQt4.QtCore import QTimer, QObject, QCoreApplication, QUrl, SIGNAL
|
||||
from PyQt4.QtGui import QDesktopServices, QFileDialog, QDialog, QMessageBox
|
||||
|
||||
from hsutil import job
|
||||
from hsutil.reg import RegistrationRequired
|
||||
from hscommon import job
|
||||
from hscommon.reg import RegistrationRequired
|
||||
|
||||
from core.app import DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, JOB_DELETE
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class DupeGuru(DupeGuruBase):
|
||||
EDITION = 'me'
|
||||
LOGO_NAME = 'logo_me'
|
||||
NAME = 'dupeGuru Music Edition'
|
||||
VERSION = '5.7.2'
|
||||
VERSION = '5.8.1'
|
||||
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8])
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5" modules="professional" RootPath="." Language="en">
|
||||
<DOCUMENT Type="Advanced Installer" CreateVersion="4.7.2" version="7.6" Modules="professional" RootPath="." Language="en">
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
||||
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
||||
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
||||
@@ -28,18 +28,13 @@
|
||||
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
|
||||
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
|
||||
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
||||
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
|
||||
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
|
||||
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
|
||||
<ROW Directory="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
|
||||
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
|
||||
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
|
||||
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||
<ROW Component="AIShRegAnswer" ComponentId="{7DB5C163-2978-436F-A47D-54F1C76F1D64}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
|
||||
<ROW Component="AI_ExePath" ComponentId="{AB8EF793-B4A4-4A5C-A343-8095FFE16175}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
|
||||
<ROW Component="PyWinTypes26.dll" ComponentId="{E7DC87D7-F396-46F0-8132-D4F582709AA2}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
|
||||
<ROW Component="CurrentVersion" ComponentId="{1EF88868-DCB1-4F7D-83F6-CC17C9F65740}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
|
||||
<ROW Component="QtCore4.dll" ComponentId="{731F12A4-0DB0-4484-8BA1-399560578D68}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
|
||||
<ROW Component="QtGui4.dll" ComponentId="{3D4FDAFA-EE5E-43C5-A4F5-125F7FA6A550}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
|
||||
<ROW Component="bz2.pyd_1" ComponentId="{E34B2912-4B50-4EEA-B1EF-B56FA625FCC7}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
|
||||
@@ -47,78 +42,48 @@
|
||||
<ROW Component="dupeGuru_ME.exe" ComponentId="{14F7B73A-FA85-4C10-AA92-10BE05FE103B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_ME.exe"/>
|
||||
<ROW Component="hs_title.png" ComponentId="{A292ADA8-FEC0-49B9-81A5-6C7F837290D4}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
|
||||
<ROW Component="python26.dll" ComponentId="{20E0EA31-C5CF-4278-B7C6-5FCA0C691B7F}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
|
||||
<ROW Component="pythoncom26.dll" ComponentId="{C0489561-2362-48C1-86E8-D5F1A08DE4DE}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
|
||||
<ROW Component="qcncodecs4.dll" ComponentId="{03C97279-4453-48E0-A40D-D28E6F3E701F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
|
||||
<ROW Component="qgif4.dll" ComponentId="{5D6E676F-18BC-49C8-BBD2-E6BA1F3CA043}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
|
||||
<ROW Component="qico4.dll" ComponentId="{C23E13E3-0E14-46E8-AA73-5D592CDBB725}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
|
||||
<ROW Component="qjpcodecs4.dll" ComponentId="{E6649370-16BB-449A-8668-9995B5C1CEB5}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll"/>
|
||||
<ROW Component="qjpeg4.dll" ComponentId="{1D084E38-4A03-4C3C-87F7-3C68FEB41B4C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll"/>
|
||||
<ROW Component="qkrcodecs4.dll" ComponentId="{18F32B38-7D3F-4F3C-AB80-3778634C8676}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll"/>
|
||||
<ROW Component="qmng4.dll" ComponentId="{D7E0BF84-EB34-4E4B-81CD-93B47B31503C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
|
||||
<ROW Component="qsvg4.dll" ComponentId="{3920BD4C-9A56-4CE4-A321-E649652D3D8A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
|
||||
<ROW Component="qsvgicon4.dll" ComponentId="{F5D7A7C3-6320-4274-90DF-9F42C94FCDED}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
|
||||
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{990608A3-AD85-439A-B46A-764DF560FA3A}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
|
||||
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{1F04BD2B-42BD-412D-B101-806B130CD1B8}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
|
||||
<ROW Component="qtiff4.dll" ComponentId="{D5B4A7B8-7D9B-4A5C-9DD5-2048690EEE11}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
|
||||
<ROW Component="qtwcodecs4.dll" ComponentId="{E6C5E92F-D193-4A75-88E2-5058F069C224}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
|
||||
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_ME.exe AIShRegAnswer bz2.pyd_1 python26.dll pythoncom26.dll PyWinTypes26.dll qtaccessiblecompatwidgets4.dll qtaccessiblewidgets4.dll qcncodecs4.dll qjpcodecs4.dll qkrcodecs4.dll qtwcodecs4.dll qsvgicon4.dll qgif4.dll qico4.dll qjpeg4.dll qmng4.dll qsvg4.dll qtiff4.dll QtCore4.dll QtGui4.dll AI_ExePath credits.htm hs_title.png"/>
|
||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_ME.exe AIShRegAnswer bz2.pyd_1 python26.dll QtCore4.dll QtGui4.dll AI_ExePath credits.htm hs_title.png CurrentVersion"/>
|
||||
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
||||
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="5"/>
|
||||
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="6"/>
|
||||
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="9"/>
|
||||
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="23"/>
|
||||
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="24"/>
|
||||
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="4"/>
|
||||
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="5"/>
|
||||
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="7"/>
|
||||
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="8"/>
|
||||
<ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
|
||||
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="36"/>
|
||||
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="37"/>
|
||||
<ROW File="dupeGuru_ME.exe" Component_="dupeGuru_ME.exe" FileName="dupeGu~1.exe|dupeGuru ME.exe" Attributes="0" SourcePath="dist\dupeGuru ME.exe" SelfReg="false" Sequence="2"/>
|
||||
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="38"/>
|
||||
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="39"/>
|
||||
<ROW File="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="32"/>
|
||||
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="40"/>
|
||||
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="41"/>
|
||||
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="42"/>
|
||||
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="43"/>
|
||||
<ROW File="pyexpat.pyd" Component_="bz2.pyd_1" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="4"/>
|
||||
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="7"/>
|
||||
<ROW File="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" SelfReg="false" Sequence="8"/>
|
||||
<ROW File="qcncodecs4.dll" Component_="qcncodecs4.dll" FileName="qcncod~1.dll|qcncodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qcncodecs4.dll" SelfReg="false" Sequence="12"/>
|
||||
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="17"/>
|
||||
<ROW File="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="18"/>
|
||||
<ROW File="qjpcodecs4.dll" Component_="qjpcodecs4.dll" FileName="qjpcod~1.dll|qjpcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qjpcodecs4.dll" SelfReg="false" Sequence="13"/>
|
||||
<ROW File="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="19"/>
|
||||
<ROW File="qkrcodecs4.dll" Component_="qkrcodecs4.dll" FileName="qkrcod~1.dll|qkrcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qkrcodecs4.dll" SelfReg="false" Sequence="14"/>
|
||||
<ROW File="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="20"/>
|
||||
<ROW File="qsvg4.dll" Component_="qsvg4.dll" FileName="qsvg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qsvg4.dll" SelfReg="false" Sequence="21"/>
|
||||
<ROW File="qsvgicon4.dll" Component_="qsvgicon4.dll" FileName="qsvgic~1.dll|qsvgicon4.dll" Attributes="0" SourcePath="dist\qt4_plugins\iconengines\qsvgicon4.dll" SelfReg="false" Sequence="16"/>
|
||||
<ROW File="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="10"/>
|
||||
<ROW File="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="11"/>
|
||||
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="22"/>
|
||||
<ROW File="qtwcodecs4.dll" Component_="qtwcodecs4.dll" FileName="qtwcod~1.dll|qtwcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qtwcodecs4.dll" SelfReg="false" Sequence="15"/>
|
||||
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="44"/>
|
||||
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="45"/>
|
||||
<ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="25"/>
|
||||
<ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="26"/>
|
||||
<ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="33"/>
|
||||
<ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="34"/>
|
||||
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="27"/>
|
||||
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
||||
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="46"/>
|
||||
<ROW File="win32api.pyd" Component_="bz2.pyd_1" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="28"/>
|
||||
<ROW File="win32com.shell.shell.pyd" Component_="bz2.pyd_1" FileName="win32c~1.pyd|win32com.shell.shell.pyd" Attributes="0" SourcePath="dist\win32com.shell.shell.pyd" SelfReg="false" Sequence="29"/>
|
||||
<ROW File="win32sysloader.pyd" Component_="bz2.pyd_1" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="35"/>
|
||||
<ROW File="win32trace.pyd" Component_="bz2.pyd_1" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="30"/>
|
||||
<ROW File="win32ui.pyd" Component_="bz2.pyd_1" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="31"/>
|
||||
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="15"/>
|
||||
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="16"/>
|
||||
<ROW File="dupeGuru_ME.exe" Component_="dupeGuru_ME.exe" FileName="dupeGu~1.exe|dupeGuru ME.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru ME.exe" SelfReg="false" Sequence="2"/>
|
||||
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="17"/>
|
||||
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="18"/>
|
||||
<ROW File="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="12"/>
|
||||
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="19"/>
|
||||
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="20"/>
|
||||
<ROW File="lxml.etree.pyd" Component_="bz2.pyd_1" FileName="lxmlet~1.pyd|lxml.etree.pyd" Attributes="0" SourcePath="dist\lxml.etree.pyd" SelfReg="false" Sequence="26"/>
|
||||
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="21"/>
|
||||
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="22"/>
|
||||
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="6"/>
|
||||
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="23"/>
|
||||
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="24"/>
|
||||
<ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="9"/>
|
||||
<ROW File="send2trash_win.pyd" Component_="bz2.pyd_1" FileName="_send2~1.pyd|_send2trash_win.pyd" Attributes="0" SourcePath="dist\_send2trash_win.pyd" SelfReg="false" Sequence="27"/>
|
||||
<ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="10"/>
|
||||
<ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="13"/>
|
||||
<ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="14"/>
|
||||
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="11"/>
|
||||
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_STUBS>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
||||
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="25"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
||||
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_me_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
|
||||
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="install" PackageFileName="dupeguru_me_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
|
||||
<ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
|
||||
<ATTRIBUTE name="Enable" value="false"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
|
||||
<ROW Path="<AI_DICTS>ui.ail"/>
|
||||
<ROW Path="<AI_DICTS>ui_en.ail"/>
|
||||
@@ -239,10 +204,11 @@
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
||||
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
||||
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
||||
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
||||
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||
<ROW Shortcut="Uninstall_dupeGuru_ME" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru ME" Component_="qtwcodecs4.dll" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
|
||||
<ROW Shortcut="Uninstall_dupeGuru_ME" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru ME" Component_="AIShRegAnswer" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
|
||||
<ROW Shortcut="dupeGuru_ME" Directory_="SHORTCUTDIR" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||
<ROW Shortcut="dupeGuru_ME_1" Directory_="DesktopFolder" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||
</COMPONENT>
|
||||
|
||||
@@ -57,6 +57,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
||||
setchecked(self.useRegexpBox, prefs.use_regexp)
|
||||
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
|
||||
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
||||
self.customCommandEdit.setText(prefs.custom_command)
|
||||
|
||||
def save(self):
|
||||
prefs = self.app.prefs
|
||||
@@ -75,6 +76,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
||||
prefs.use_regexp = ischecked(self.useRegexpBox)
|
||||
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
|
||||
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
||||
prefs.custom_command = unicode(self.customCommandEdit.text())
|
||||
|
||||
def resetToDefaults(self):
|
||||
self.load(preferences.Preferences())
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>449</width>
|
||||
<height>361</height>
|
||||
<width>325</width>
|
||||
<height>360</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -19,9 +19,9 @@
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,0,0,0,1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
@@ -358,6 +358,16 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Custom Command (arguments: %d for dupe, %r for ref):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="customCommandEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -14,6 +14,9 @@ import base.dg_rc
|
||||
|
||||
from app import DupeGuru
|
||||
|
||||
if sys.platform == 'win32':
|
||||
import base.cxfreeze_fix
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
app.setWindowIcon(QIcon(QPixmap(":/logo_me")))
|
||||
|
||||
@@ -57,7 +57,7 @@ class DupeGuru(DupeGuruBase):
|
||||
EDITION = 'pe'
|
||||
LOGO_NAME = 'logo_pe'
|
||||
NAME = 'dupeGuru Picture Edition'
|
||||
VERSION = '1.8.6'
|
||||
VERSION = '1.9.1'
|
||||
DELTA_COLUMNS = frozenset([2, 5, 6])
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -35,6 +35,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
||||
setchecked(self.useRegexpBox, prefs.use_regexp)
|
||||
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
|
||||
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
||||
self.customCommandEdit.setText(prefs.custom_command)
|
||||
|
||||
def save(self):
|
||||
prefs = self.app.prefs
|
||||
@@ -45,6 +46,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
||||
prefs.use_regexp = ischecked(self.useRegexpBox)
|
||||
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
|
||||
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
||||
prefs.custom_command = unicode(self.customCommandEdit.text())
|
||||
|
||||
def resetToDefaults(self):
|
||||
self.load(preferences.Preferences())
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>366</width>
|
||||
<height>249</height>
|
||||
<width>304</width>
|
||||
<height>263</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -19,9 +19,9 @@
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
@@ -192,6 +192,16 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Custom Command (arguments: %d for dupe %r for ref):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="customCommandEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -27,7 +27,7 @@ class DupeGuru(DupeGuruBase):
|
||||
EDITION = 'se'
|
||||
LOGO_NAME = 'logo_se'
|
||||
NAME = 'dupeGuru'
|
||||
VERSION = '2.10.0'
|
||||
VERSION = '2.10.1'
|
||||
DELTA_COLUMNS = frozenset([2, 4, 5])
|
||||
|
||||
def __init__(self):
|
||||
|
||||
Reference in New Issue
Block a user