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

Compare commits

..

38 Commits

Author SHA1 Message Date
Virgil Dupras
31fc70e0f8 Updated dependencies to include cx_Freeze. 2010-04-08 15:01:21 +02:00
Virgil Dupras
a16af4560b dgse qt: fixed visual glitch in the preference dialog under linux. 2010-04-08 04:26:11 -07:00
Virgil Dupras
0782ba0dab Only do cxfreeze workarounds under Windows. 2010-04-08 04:12:29 -07:00
Virgil Dupras
83725667a4 Made the windows packaging copy qt plugins in the dist package. PyInstaller did this, but cxfreeze doesn't. 2010-04-08 11:17:03 +01:00
Virgil Dupras
f4b3163b04 Merged heads. 2010-04-08 11:14:42 +02:00
Virgil Dupras
6cd745f429 Added hsutil.files.find_in_path() 2010-04-08 11:14:01 +02:00
Virgil Dupras
6131f7f6bf Merge heads. 2010-04-08 07:55:03 +01:00
Virgil Dupras
dd4faa030f Changed the installer project so that we make sure that the executable is always overwritten.
Previously, (probably because the exe doesn't have version embedded in it anymore), we ended up, during upgrades, with executable-less installs.
2010-04-08 07:54:03 +01:00
Virgil Dupras
ab8691f5ac Changed the release date for pe 1.8.6, which has been delayed by packaging problems. 2010-04-08 08:35:17 +02:00
Virgil Dupras
77ab073cdb Added a missing python-lxml dep to the debian packages. 2010-04-07 09:32:49 -07:00
Virgil Dupras
87e0011525 Under Linux, don't show the "Check for Update" action and correctly open the help file. 2010-04-07 09:04:58 -07:00
Virgil Dupras
7af3bb7226 Merged heads. 2010-04-07 08:50:56 -07:00
Virgil Dupras
5573352ce6 PyInstaller is fucked up. Moved to cxFreeze. 2010-04-07 16:30:04 +01:00
Virgil Dupras
e6486e08ab Qt: fixed help packaging. 2010-04-07 15:04:09 +01:00
Virgil Dupras
48badaa927 pe v1.8.6 2010-04-07 13:59:40 +02:00
Virgil Dupras
2f13bf677e Adjusted details table height by 2 pixels so that it doesn't show a scrollbar under Linux. 2010-04-07 04:02:18 -07:00
Virgil Dupras
e63abc1b4b Added debian packaging support. 2010-04-07 03:56:43 -07:00
Virgil Dupras
88334acdef [#90 state:fixed] Fixed a rare crash on results loading. 2010-04-07 10:29:00 +02:00
Virgil Dupras
0491aa9f6e Updated dependencies in README. 2010-04-07 09:14:10 +02:00
Virgil Dupras
5be76d7c0f Use the send2trash lib in _do_delete_dupe(). 2010-04-07 09:11:36 +02:00
Virgil Dupras
3b510389fc cocoa: Removed obsolete refreshStats calls. 2010-04-07 09:09:19 +02:00
Virgil Dupras
32d88e9249 Limit the size of arguments sent to multiprocessing because it could cause crashes. 2010-04-05 10:15:33 +02:00
Virgil Dupras
7b1a1ff4bb Added tag pe1.8.5 for changeset 0a71306434bc 2010-03-01 17:15:23 +01:00
Virgil Dupras
19beb919d0 Fixed the automatic update check option on the Cocoa side. 2010-03-01 16:09:59 +01:00
Virgil Dupras
ba09e8bf4d Updated the readme file to add the lxml dependency. 2010-03-01 14:35:58 +01:00
Virgil Dupras
26dd2d0e8e Updated py2app workaround in dg_cocoa for lxml. 2010-03-01 04:15:27 -08:00
Virgil Dupras
69b15d58a2 Updated hsutil subrepo. 2010-03-01 12:33:16 +01:00
Virgil Dupras
ba68789fb9 pe v1.8.5 2010-03-01 12:31:34 +01:00
Virgil Dupras
47a6ceffbc Use lxml everywhere for xml save/load (instead of ElementTree and minidom). 2010-03-01 12:21:43 +01:00
Virgil Dupras
b17ca66f73 Fixed crashes when reading invalid iPhoto AlbumData file. This time, I used lxml's "recover" feature to filter out crap in the XML, so it should cover most cases of invalid stuff in iPhoto data files. 2010-03-01 12:20:21 +01:00
Virgil Dupras
93bc609026 Updated the SE cocoa project so that it includes the lastest changes in dgbase and cocoalib. 2010-03-01 12:14:49 +01:00
Virgil Dupras
3ea51c2e15 Added tag pe1.8.4 for changeset 4c3cb1e671a3 2010-02-18 15:31:59 +01:00
Virgil Dupras
1d9897ea60 (Forgot to commit). Updated the ME installer project for Advanced Installer 7.5. 2010-02-18 09:49:28 +00:00
Virgil Dupras
b6cb00bc79 pe 1.8.4 2010-02-18 10:31:24 +01:00
Virgil Dupras
6dd53c6bfd Removing duplicates now preserve selected paths. 2010-02-17 18:05:19 +01:00
Virgil Dupras
07df5126b3 Adapted the PE edition to the latest refactorings and fixed a (very) minor memory leak in ME. 2010-02-17 17:37:42 +01:00
Virgil Dupras
47b38c7d45 Preliminary linux support (it starts up, at least...). 2010-02-13 12:22:34 -08:00
Virgil Dupras
0e97bec7b2 Added tag me5.7.2 for changeset 90ed56ee6026 2010-02-13 18:36:54 +01:00
67 changed files with 1176 additions and 901 deletions

View File

@@ -11,3 +11,6 @@ cbcf9c80fee4c908ef2efbf1c143c9e47676c9b2 pe1.8.0
19e40bab20521d4256acf325dba9b32e95e135c5 pe1.8.2 19e40bab20521d4256acf325dba9b32e95e135c5 pe1.8.2
7b7c5a66ebee4e4b8125330d24fe9ce1a070ff25 se2.9.2 7b7c5a66ebee4e4b8125330d24fe9ce1a070ff25 se2.9.2
1cef6d39855f85d4be728646bc78b860e6d4e398 pe1.8.3 1cef6d39855f85d4be728646bc78b860e6d4e398 pe1.8.3
90ed56ee602666db2f267f73eac6f824347039b5 me5.7.2
4c3cb1e671a333eabde1151c7c6ffb3609cab025 pe1.8.4
0a71306434bca51bea9a5d5ae54fe1bf0e4900d8 pe1.8.5

4
README
View File

@@ -27,6 +27,8 @@ General dependencies
----- -----
- Python 2.6 (http://www.python.org) - Python 2.6 (http://www.python.org)
- Send2Trash (http://hg.hardcoded.net/send2trash)
- lxml, to read and write XML files. (http://codespeak.net/lxml/)
- Mako, to generate help files. (http://www.makotemplates.org/) - Mako, to generate help files. (http://www.makotemplates.org/)
- PyYaml, for help files and the build system. (http://pyyaml.org/) - PyYaml, for help files and the build system. (http://pyyaml.org/)
- Nose, to run unit tests. (http://somethingaboutorange.com/mrl/projects/nose/) - Nose, to run unit tests. (http://somethingaboutorange.com/mrl/projects/nose/)
@@ -45,7 +47,7 @@ Windows prerequisites
- Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/) - Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/)
- PyQt 4.6 (http://www.riverbankcomputing.co.uk/news) - PyQt 4.6 (http://www.riverbankcomputing.co.uk/news)
- Python Imaging Library for dupeGuru PE. (http://www.pythonware.com/products/pil/) - Python Imaging Library for dupeGuru PE. (http://www.pythonware.com/products/pil/)
- PyInstaller, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://www.pyinstaller.org/) - cx_Freeze, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://cx-freeze.sourceforge.net/)
- Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/) - Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/)
Building dupeGuru Building dupeGuru

View File

@@ -20,7 +20,7 @@ http://www.hardcoded.net/licenses/hs_license
{ {
[super awakeFromNib]; [super awakeFromNib];
[[self window] setTitle:@"dupeGuru Music Edition"]; [[self window] setTitle:@"dupeGuru Music Edition"];
NSMutableIndexSet *deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,7)] retain]; NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,7)];
[deltaColumns removeIndex:6]; [deltaColumns removeIndex:6];
[outline setDeltaColumns:deltaColumns]; [outline setDeltaColumns:deltaColumns];
} }

View File

@@ -11,9 +11,11 @@ from core_me.app_cocoa import DupeGuruME
from core.scanner import (SCAN_TYPE_FILENAME, SCAN_TYPE_FIELDS, SCAN_TYPE_FIELDS_NO_ORDER, from core.scanner import (SCAN_TYPE_FILENAME, SCAN_TYPE_FIELDS, SCAN_TYPE_FIELDS_NO_ORDER,
SCAN_TYPE_TAG, SCAN_TYPE_CONTENT, SCAN_TYPE_CONTENT_AUDIO) SCAN_TYPE_TAG, SCAN_TYPE_CONTENT, SCAN_TYPE_CONTENT_AUDIO)
# Fix py2app imports which chokes on relative imports # Fix py2app imports which chokes on relative imports and other stuff
from core_me import app_cocoa, data, fs, scanner from core_me import app_cocoa, data, fs, scanner
from hsmedia import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma from hsmedia import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
from lxml import etree, _elementpath
import gzip
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):

View File

@@ -2,10 +2,10 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">1050</int> <int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10B504</string> <string key="IBDocument.SystemVersion">10C540</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string> <string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.AppKitVersion">1038.2</string> <string key="IBDocument.AppKitVersion">1038.25</string>
<string key="IBDocument.HIToolboxVersion">437.00</string> <string key="IBDocument.HIToolboxVersion">458.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string> <string key="NS.object.0">740</string>
@@ -39,6 +39,10 @@
<string key="NSClassName">NSApplication</string> <string key="NSClassName">NSApplication</string>
</object> </object>
<object class="NSUserDefaultsController" id="579641073"> <object class="NSUserDefaultsController" id="579641073">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>SUEnableAutomaticChecks</string>
</object>
<bool key="NSSharedInstance">YES</bool> <bool key="NSSharedInstance">YES</bool>
</object> </object>
<object class="NSWindowTemplate" id="793317856"> <object class="NSWindowTemplate" id="793317856">
@@ -552,7 +556,7 @@
<object class="NSButtonCell" key="NSCell" id="58676792"> <object class="NSButtonCell" key="NSCell" id="58676792">
<int key="NSCellFlags">67239424</int> <int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int> <int key="NSCellFlags2">0</int>
<string key="NSContents">Check for update on startup</string> <string key="NSContents">Automatically check for updates</string>
<reference key="NSSupport" ref="26"/> <reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="147113892"/> <reference key="NSControlView" ref="147113892"/>
<int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags">1211912703</int>
@@ -980,22 +984,6 @@
</object> </object>
<int key="connectionID">84</int> <int key="connectionID">84</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUCheckAtStartup</string>
<reference key="source" ref="147113892"/>
<reference key="destination" ref="579641073"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="147113892"/>
<reference key="NSDestination" ref="579641073"/>
<string key="NSLabel">value: values.SUCheckAtStartup</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUCheckAtStartup</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">85</int>
</object>
<object class="IBConnectionRecord"> <object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection"> <object class="IBOutletConnection" key="connection">
<string key="label">nextKeyView</string> <string key="label">nextKeyView</string>
@@ -1348,6 +1336,22 @@
</object> </object>
<int key="connectionID">113</int> <int key="connectionID">113</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUEnableAutomaticChecks</string>
<reference key="source" ref="147113892"/>
<reference key="destination" ref="579641073"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="147113892"/>
<reference key="NSDestination" ref="579641073"/>
<string key="NSLabel">value: values.SUEnableAutomaticChecks</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUEnableAutomaticChecks</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">114</int>
</object>
</object> </object>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects"> <object class="NSArray" key="orderedObjects">
@@ -1838,8 +1842,6 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.IBPluginDependency</string>
<string>-2.IBPluginDependency</string>
<string>-3.IBPluginDependency</string> <string>-3.IBPluginDependency</string>
<string>1.IBPluginDependency</string> <string>1.IBPluginDependency</string>
<string>1.ImportedFromIB2</string> <string>1.ImportedFromIB2</string>
@@ -1949,8 +1951,6 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/> <boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/> <boolean value="YES"/>
@@ -2071,9 +2071,26 @@
</object> </object>
</object> </object>
<nil key="sourceID"/> <nil key="sourceID"/>
<int key="maxID">113</int> <int key="maxID">114</int>
</object> </object>
<object class="IBClassDescriber" key="IBDocument.Classes"> <object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/NSTableViewAdditions.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">

View File

@@ -23,7 +23,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.8.3</string> <string>1.8.6</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>

View File

@@ -7,7 +7,6 @@ http://www.hardcoded.net/licenses/hs_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "Outline.h"
#import "../base/ResultWindow.h" #import "../base/ResultWindow.h"
@interface ResultWindow : ResultWindowBase {} @interface ResultWindow : ResultWindowBase {}

View File

@@ -20,9 +20,10 @@ http://www.hardcoded.net/licenses/hs_license
{ {
[super awakeFromNib]; [super awakeFromNib];
[[self window] setTitle:@"dupeGuru Picture Edition"]; [[self window] setTitle:@"dupeGuru Picture Edition"];
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,5)] retain]; NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,5)];
[_deltaColumns removeIndex:3]; [deltaColumns removeIndex:3];
[_deltaColumns removeIndex:4]; [deltaColumns removeIndex:4];
[outline setDeltaColumns:deltaColumns];
} }
/* Actions */ /* Actions */
@@ -63,8 +64,6 @@ http://www.hardcoded.net/licenses/hs_license
[_py setMixFileKind:[ud objectForKey:@"mixFileKind"]]; [_py setMixFileKind:[ud objectForKey:@"mixFileKind"]];
[_py setMatchScaled:[ud objectForKey:@"matchScaled"]]; [_py setMatchScaled:[ud objectForKey:@"matchScaled"]];
int r = n2i([py doScan]); int r = n2i([py doScan]);
[matches reloadData];
[self refreshStats];
if (r != 0) if (r != 0)
[[ProgressController mainProgressController] hide]; [[ProgressController mainProgressController] hide];
if (r == 1) if (r == 1)

View File

@@ -7,8 +7,10 @@
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_pe import app_cocoa as app_pe_cocoa from core_pe import app_cocoa as app_pe_cocoa
# Fix py2app imports which chokes on relative imports # Fix py2app imports which chokes on relative imports and other stuff
from core_pe import block, cache, matchbase, data, _block_osx from core_pe import block, cache, matchbase, data, _block_osx
from lxml import etree, _elementpath
import gzip
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):

View File

@@ -27,7 +27,6 @@
CE7AC91A1119911200D02F6C /* registration.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE7AC9171119911200D02F6C /* registration.xib */; }; CE7AC91A1119911200D02F6C /* registration.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE7AC9171119911200D02F6C /* registration.xib */; };
CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1C0FC192D60086DCA6 /* Dialogs.m */; }; CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1C0FC192D60086DCA6 /* Dialogs.m */; };
CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */; }; CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */; };
CE80DB300FC192D60086DCA6 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB200FC192D60086DCA6 /* Outline.m */; };
CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB220FC192D60086DCA6 /* ProgressController.m */; }; CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB220FC192D60086DCA6 /* ProgressController.m */; };
CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB250FC192D60086DCA6 /* RecentDirectories.m */; }; CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB250FC192D60086DCA6 /* RecentDirectories.m */; };
CE80DB330FC192D60086DCA6 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB270FC192D60086DCA6 /* RegistrationInterface.m */; }; CE80DB330FC192D60086DCA6 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB270FC192D60086DCA6 /* RegistrationInterface.m */; };
@@ -39,6 +38,8 @@
CE80DB8B0FC1951C0086DCA6 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */; }; CE80DB8B0FC1951C0086DCA6 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */; };
CE80DB8C0FC1951C0086DCA6 /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB890FC1951C0086DCA6 /* ResultWindow.m */; }; CE80DB8C0FC1951C0086DCA6 /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB890FC1951C0086DCA6 /* ResultWindow.m */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; }; CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE95865B112C516400F95FD2 /* ResultOutline.m */; };
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE95865D112C516400F95FD2 /* StatsLabel.m */; };
CE9EA7561122C96C008CD2BC /* HSGUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7441122C96C008CD2BC /* HSGUIController.m */; }; CE9EA7561122C96C008CD2BC /* HSGUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7441122C96C008CD2BC /* HSGUIController.m */; };
CE9EA7571122C96C008CD2BC /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7461122C96C008CD2BC /* HSOutline.m */; }; CE9EA7571122C96C008CD2BC /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7461122C96C008CD2BC /* HSOutline.m */; };
CE9EA7581122C96C008CD2BC /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7481122C96C008CD2BC /* HSWindowController.m */; }; CE9EA7581122C96C008CD2BC /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7481122C96C008CD2BC /* HSWindowController.m */; };
@@ -104,8 +105,6 @@
CE80DB1C0FC192D60086DCA6 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; }; CE80DB1C0FC192D60086DCA6 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; }; CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; }; CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; };
CE80DB1F0FC192D60086DCA6 /* Outline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Outline.h; path = ../../cocoalib/Outline.h; sourceTree = SOURCE_ROOT; };
CE80DB200FC192D60086DCA6 /* Outline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Outline.m; path = ../../cocoalib/Outline.m; sourceTree = SOURCE_ROOT; };
CE80DB210FC192D60086DCA6 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; }; CE80DB210FC192D60086DCA6 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CE80DB220FC192D60086DCA6 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; }; CE80DB220FC192D60086DCA6 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CE80DB230FC192D60086DCA6 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; }; CE80DB230FC192D60086DCA6 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
@@ -130,6 +129,12 @@
CE80DB880FC1951C0086DCA6 /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultWindow.h; path = ../base/ResultWindow.h; sourceTree = SOURCE_ROOT; }; CE80DB880FC1951C0086DCA6 /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultWindow.h; path = ../base/ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultWindow.m; path = ../base/ResultWindow.m; sourceTree = SOURCE_ROOT; }; CE80DB890FC1951C0086DCA6 /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultWindow.m; path = ../base/ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; }; CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE958658112C516400F95FD2 /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE958659112C516400F95FD2 /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CE95865A112C516400F95FD2 /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE95865B112C516400F95FD2 /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
CE95865C112C516400F95FD2 /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
CE95865D112C516400F95FD2 /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CE9EA7431122C96C008CD2BC /* HSGUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSGUIController.h; sourceTree = "<group>"; }; CE9EA7431122C96C008CD2BC /* HSGUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSGUIController.h; sourceTree = "<group>"; };
CE9EA7441122C96C008CD2BC /* HSGUIController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSGUIController.m; sourceTree = "<group>"; }; CE9EA7441122C96C008CD2BC /* HSGUIController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSGUIController.m; sourceTree = "<group>"; };
CE9EA7451122C96C008CD2BC /* HSOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSOutline.h; sourceTree = "<group>"; }; CE9EA7451122C96C008CD2BC /* HSOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSOutline.h; sourceTree = "<group>"; };
@@ -304,8 +309,6 @@
CE80DB1C0FC192D60086DCA6 /* Dialogs.m */, CE80DB1C0FC192D60086DCA6 /* Dialogs.m */,
CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */, CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */,
CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */, CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */,
CE80DB1F0FC192D60086DCA6 /* Outline.h */,
CE80DB200FC192D60086DCA6 /* Outline.m */,
CE80DB210FC192D60086DCA6 /* ProgressController.h */, CE80DB210FC192D60086DCA6 /* ProgressController.h */,
CE80DB220FC192D60086DCA6 /* ProgressController.m */, CE80DB220FC192D60086DCA6 /* ProgressController.m */,
CE80DB230FC192D60086DCA6 /* PyApp.h */, CE80DB230FC192D60086DCA6 /* PyApp.h */,
@@ -325,7 +328,6 @@
CE80DB810FC194BD0086DCA6 /* dgbase */ = { CE80DB810FC194BD0086DCA6 /* dgbase */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
CE80DB820FC1951C0086DCA6 /* AppDelegate.h */, CE80DB820FC1951C0086DCA6 /* AppDelegate.h */,
CE80DB830FC1951C0086DCA6 /* AppDelegate.m */, CE80DB830FC1951C0086DCA6 /* AppDelegate.m */,
CE80DB840FC1951C0086DCA6 /* Consts.h */, CE80DB840FC1951C0086DCA6 /* Consts.h */,
@@ -333,12 +335,19 @@
CE6044EB0FE6796200B71262 /* DetailsPanel.m */, CE6044EB0FE6796200B71262 /* DetailsPanel.m */,
CE80DB850FC1951C0086DCA6 /* DirectoryPanel.h */, CE80DB850FC1951C0086DCA6 /* DirectoryPanel.h */,
CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */, CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */,
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
CE9EA76F1122CA0B008CD2BC /* DirectoryOutline.h */, CE9EA76F1122CA0B008CD2BC /* DirectoryOutline.h */,
CE9EA7701122CA0B008CD2BC /* DirectoryOutline.m */, CE9EA7701122CA0B008CD2BC /* DirectoryOutline.m */,
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */, CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */, CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */,
CE80DB880FC1951C0086DCA6 /* ResultWindow.h */, CE80DB880FC1951C0086DCA6 /* ResultWindow.h */,
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */, CE80DB890FC1951C0086DCA6 /* ResultWindow.m */,
CE958658112C516400F95FD2 /* PyResultTree.h */,
CE95865A112C516400F95FD2 /* ResultOutline.h */,
CE95865B112C516400F95FD2 /* ResultOutline.m */,
CE958659112C516400F95FD2 /* PyStatsLabel.h */,
CE95865C112C516400F95FD2 /* StatsLabel.h */,
CE95865D112C516400F95FD2 /* StatsLabel.m */,
); );
name = dgbase; name = dgbase;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -478,7 +487,6 @@
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */, CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */,
CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */, CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */,
CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */, CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */,
CE80DB300FC192D60086DCA6 /* Outline.m in Sources */,
CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */, CE80DB310FC192D60086DCA6 /* ProgressController.m in Sources */,
CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */, CE80DB320FC192D60086DCA6 /* RecentDirectories.m in Sources */,
CE80DB330FC192D60086DCA6 /* RegistrationInterface.m in Sources */, CE80DB330FC192D60086DCA6 /* RegistrationInterface.m in Sources */,
@@ -499,6 +507,8 @@
CE9EA75B1122C96C008CD2BC /* NSIndexPathAdditions.m in Sources */, CE9EA75B1122C96C008CD2BC /* NSIndexPathAdditions.m in Sources */,
CE9EA75C1122C96C008CD2BC /* NSTableViewAdditions.m in Sources */, CE9EA75C1122C96C008CD2BC /* NSTableViewAdditions.m in Sources */,
CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */, CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */,
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */,
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -2,17 +2,17 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">1050</int> <int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10B504</string> <string key="IBDocument.SystemVersion">10C540</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string> <string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.AppKitVersion">1038.2</string> <string key="IBDocument.AppKitVersion">1038.25</string>
<string key="IBDocument.HIToolboxVersion">437.00</string> <string key="IBDocument.HIToolboxVersion">458.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string> <string key="NS.object.0">740</string>
</object> </object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<integer value="2"/> <integer value="3"/>
</object> </object>
<object class="NSArray" key="IBDocument.PluginDependencies"> <object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
@@ -39,6 +39,10 @@
<string key="NSClassName">NSApplication</string> <string key="NSClassName">NSApplication</string>
</object> </object>
<object class="NSUserDefaultsController" id="455472712"> <object class="NSUserDefaultsController" id="455472712">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>SUEnableAutomaticChecks</string>
</object>
<bool key="NSSharedInstance">YES</bool> <bool key="NSSharedInstance">YES</bool>
</object> </object>
<object class="NSWindowTemplate" id="809668081"> <object class="NSWindowTemplate" id="809668081">
@@ -411,7 +415,7 @@
<object class="NSButtonCell" key="NSCell" id="2297113"> <object class="NSButtonCell" key="NSCell" id="2297113">
<int key="NSCellFlags">67239424</int> <int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int> <int key="NSCellFlags2">0</int>
<string key="NSContents">Check for update on startup</string> <string key="NSContents">Automatically check for updates</string>
<reference key="NSSupport" ref="26"/> <reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="472028782"/> <reference key="NSControlView" ref="472028782"/>
<int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags">1211912703</int>
@@ -541,22 +545,6 @@
</object> </object>
<int key="connectionID">39</int> <int key="connectionID">39</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUCheckAtStartup</string>
<reference key="source" ref="472028782"/>
<reference key="destination" ref="455472712"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="472028782"/>
<reference key="NSDestination" ref="455472712"/>
<string key="NSLabel">value: values.SUCheckAtStartup</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUCheckAtStartup</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">40</int>
</object>
<object class="IBConnectionRecord"> <object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection"> <object class="IBActionConnection" key="connection">
<string key="label">revertToInitialValues:</string> <string key="label">revertToInitialValues:</string>
@@ -677,6 +665,22 @@
</object> </object>
<int key="connectionID">51</int> <int key="connectionID">51</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUEnableAutomaticChecks</string>
<reference key="source" ref="472028782"/>
<reference key="destination" ref="455472712"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="472028782"/>
<reference key="NSDestination" ref="455472712"/>
<string key="NSLabel">value: values.SUEnableAutomaticChecks</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUEnableAutomaticChecks</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">58</int>
</object>
</object> </object>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects"> <object class="NSArray" key="orderedObjects">
@@ -1110,9 +1114,26 @@
</object> </object>
</object> </object>
<nil key="sourceID"/> <nil key="sourceID"/>
<int key="maxID">51</int> <int key="maxID">58</int>
</object> </object>
<object class="IBClassDescriber" key="IBDocument.Classes"> <object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/NSTableViewAdditions.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">

View File

@@ -7,7 +7,6 @@ http://www.hardcoded.net/licenses/hs_license
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "../../cocoalib/Outline.h"
#import "../base/ResultWindow.h" #import "../base/ResultWindow.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"

View File

@@ -18,8 +18,9 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib - (void)awakeFromNib
{ {
[super awakeFromNib]; [super awakeFromNib];
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)] retain]; NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)];
[_deltaColumns removeIndex:3]; [deltaColumns removeIndex:3];
[outline setDeltaColumns:deltaColumns];
} }
/* Actions */ /* Actions */
@@ -56,8 +57,6 @@ http://www.hardcoded.net/licenses/hs_license
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
[_py setSizeThreshold:sizeThreshold]; [_py setSizeThreshold:sizeThreshold];
int r = n2i([py doScan]); int r = n2i([py doScan]);
[matches reloadData];
[self refreshStats];
if (r != 0) if (r != 0)
[[ProgressController mainProgressController] hide]; [[ProgressController mainProgressController] hide];
if (r == 1) if (r == 1)

View File

@@ -10,8 +10,10 @@ from core import scanner
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_se.app_cocoa import DupeGuru from core_se.app_cocoa import DupeGuru
# Fix py2app imports with chokes on relative imports # Fix py2app imports with chokes on relative imports and other stuff
from core_se import fs, data from core_se import fs, data
from lxml import etree, _elementpath
import gzip
class PyDupeGuru(PyDupeGuruBase): class PyDupeGuru(PyDupeGuruBase):
def init(self): def init(self):

View File

@@ -27,6 +27,8 @@
CE76FDD4111EE3A7006618EA /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */; }; CE76FDD4111EE3A7006618EA /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */; };
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; }; CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; };
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; }; CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91F212113BC22D0010360B /* ResultOutline.m */; };
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91F214113BC22D0010360B /* StatsLabel.m */; };
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; }; CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; };
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */; }; CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */; };
CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; }; CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; };
@@ -39,7 +41,6 @@
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; }; CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8B0FC9517500CD5728 /* Dialogs.m */; }; CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8B0FC9517500CD5728 /* Dialogs.m */; };
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */; }; CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */; };
CEFC7FA00FC9517500CD5728 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8F0FC9517500CD5728 /* Outline.m */; };
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F910FC9517500CD5728 /* ProgressController.m */; }; CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F910FC9517500CD5728 /* ProgressController.m */; };
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F950FC9517500CD5728 /* RecentDirectories.m */; }; CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F950FC9517500CD5728 /* RecentDirectories.m */; };
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F970FC9517500CD5728 /* RegistrationInterface.m */; }; CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F970FC9517500CD5728 /* RegistrationInterface.m */; };
@@ -101,6 +102,12 @@
CE76FDDE111EE42F006618EA /* HSOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSOutline.m; sourceTree = "<group>"; }; CE76FDDE111EE42F006618EA /* HSOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSOutline.m; sourceTree = "<group>"; };
CE76FDF5111EE561006618EA /* NSEventAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSEventAdditions.h; path = ../../cocoalib/NSEventAdditions.h; sourceTree = SOURCE_ROOT; }; CE76FDF5111EE561006618EA /* NSEventAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSEventAdditions.h; path = ../../cocoalib/NSEventAdditions.h; sourceTree = SOURCE_ROOT; };
CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; }; CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; };
CE91F20F113BC22D0010360B /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE91F210113BC22D0010360B /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F211113BC22D0010360B /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE91F212113BC22D0010360B /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
CE91F213113BC22D0010360B /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F214113BC22D0010360B /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; }; CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSWindowController.h; sourceTree = "<group>"; }; CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSWindowController.h; sourceTree = "<group>"; };
CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSWindowController.m; sourceTree = "<group>"; }; CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSWindowController.m; sourceTree = "<group>"; };
@@ -118,8 +125,6 @@
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; }; CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; }; CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; }; CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; };
CEFC7F8E0FC9517500CD5728 /* Outline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Outline.h; path = ../../cocoalib/Outline.h; sourceTree = SOURCE_ROOT; };
CEFC7F8F0FC9517500CD5728 /* Outline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Outline.m; path = ../../cocoalib/Outline.m; sourceTree = SOURCE_ROOT; };
CEFC7F900FC9517500CD5728 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; }; CEFC7F900FC9517500CD5728 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CEFC7F910FC9517500CD5728 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; }; CEFC7F910FC9517500CD5728 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CEFC7F920FC9517500CD5728 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; }; CEFC7F920FC9517500CD5728 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
@@ -326,8 +331,6 @@
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */, CEFC7F8B0FC9517500CD5728 /* Dialogs.m */,
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */, CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */,
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */, CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */,
CEFC7F8E0FC9517500CD5728 /* Outline.h */,
CEFC7F8F0FC9517500CD5728 /* Outline.m */,
CEFC7F900FC9517500CD5728 /* ProgressController.h */, CEFC7F900FC9517500CD5728 /* ProgressController.h */,
CEFC7F910FC9517500CD5728 /* ProgressController.m */, CEFC7F910FC9517500CD5728 /* ProgressController.m */,
CEFC7F920FC9517500CD5728 /* PyApp.h */, CEFC7F920FC9517500CD5728 /* PyApp.h */,
@@ -347,6 +350,12 @@
CEFC7FB00FC9518F00CD5728 /* dgbase */ = { CEFC7FB00FC9518F00CD5728 /* dgbase */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CE91F20F113BC22D0010360B /* PyResultTree.h */,
CE91F210113BC22D0010360B /* PyStatsLabel.h */,
CE91F211113BC22D0010360B /* ResultOutline.h */,
CE91F212113BC22D0010360B /* ResultOutline.m */,
CE91F213113BC22D0010360B /* StatsLabel.h */,
CE91F214113BC22D0010360B /* StatsLabel.m */,
CE76FDD1111EE3A7006618EA /* DirectoryOutline.h */, CE76FDD1111EE3A7006618EA /* DirectoryOutline.h */,
CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */, CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */,
CE76FDD3111EE3A7006618EA /* PyDirectoryOutline.h */, CE76FDD3111EE3A7006618EA /* PyDirectoryOutline.h */,
@@ -441,7 +450,6 @@
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */, CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */,
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */, CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */,
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */, CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */,
CEFC7FA00FC9517500CD5728 /* Outline.m in Sources */,
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */, CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */,
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */, CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */,
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */, CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */,
@@ -460,6 +468,8 @@
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */, CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */,
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */, CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */,
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */, CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */,
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */,
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -39,6 +39,10 @@
<string key="NSClassName">NSApplication</string> <string key="NSClassName">NSApplication</string>
</object> </object>
<object class="NSUserDefaultsController" id="75941798"> <object class="NSUserDefaultsController" id="75941798">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>SUEnableAutomaticChecks</string>
</object>
<bool key="NSSharedInstance">YES</bool> <bool key="NSSharedInstance">YES</bool>
</object> </object>
<object class="NSWindowTemplate" id="489014306"> <object class="NSWindowTemplate" id="489014306">
@@ -507,7 +511,7 @@
<object class="NSButtonCell" key="NSCell" id="456303302"> <object class="NSButtonCell" key="NSCell" id="456303302">
<int key="NSCellFlags">67239424</int> <int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int> <int key="NSCellFlags2">0</int>
<string key="NSContents">Check for update on startup</string> <string key="NSContents">Automatically check for updates</string>
<reference key="NSSupport" ref="26"/> <reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="551239185"/> <reference key="NSControlView" ref="551239185"/>
<int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags">1211912703</int>
@@ -844,22 +848,6 @@
</object> </object>
<int key="connectionID">110</int> <int key="connectionID">110</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUCheckAtStartup</string>
<reference key="source" ref="551239185"/>
<reference key="destination" ref="75941798"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="551239185"/>
<reference key="NSDestination" ref="75941798"/>
<string key="NSLabel">value: values.SUCheckAtStartup</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUCheckAtStartup</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">111</int>
</object>
<object class="IBConnectionRecord"> <object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection"> <object class="IBBindingConnection" key="connection">
<string key="label">value: values.removeEmptyFolders</string> <string key="label">value: values.removeEmptyFolders</string>
@@ -972,6 +960,22 @@
</object> </object>
<int key="connectionID">121</int> <int key="connectionID">121</int>
</object> </object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.SUEnableAutomaticChecks</string>
<reference key="source" ref="551239185"/>
<reference key="destination" ref="75941798"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="551239185"/>
<reference key="NSDestination" ref="75941798"/>
<string key="NSLabel">value: values.SUEnableAutomaticChecks</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.SUEnableAutomaticChecks</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">122</int>
</object>
</object> </object>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects"> <object class="NSArray" key="orderedObjects">
@@ -1582,9 +1586,26 @@
</object> </object>
</object> </object>
<nil key="sourceID"/> <nil key="sourceID"/>
<int key="maxID">121</int> <int key="maxID">122</int>
</object> </object>
<object class="IBClassDescriber" key="IBDocument.Classes"> <object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/NSTableViewAdditions.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Created By: Virgil Dupras # Created By: Virgil Dupras
# Created On: 2006/11/11 # Created On: 2006/11/11
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net) # Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
@@ -13,6 +12,7 @@ import os
import os.path as op import os.path as op
import logging import logging
from send2trash import send2trash
from hsutil import io, files from hsutil import io, files
from hsutil.path import Path from hsutil.path import Path
from hsutil.reg import RegistrableApplication, RegistrationRequired from hsutil.reg import RegistrableApplication, RegistrationRequired
@@ -75,12 +75,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def _do_delete_dupe(self, dupe): def _do_delete_dupe(self, dupe):
if not io.exists(dupe.path): if not io.exists(dupe.path):
return True return True
self._recycle_dupe(dupe) try:
self.clean_empty_dirs(dupe.path[:-1]) send2trash(unicode(dupe.path))
if not io.exists(dupe.path): except OSError as e:
return True msg = "Could not send {0} to trash: {1}"
logging.warning("Could not send {0} to trash.".format(unicode(dupe.path))) logging.warning(msg.format(unicode(dupe.path), unicode(e)))
return False return False
self.clean_empty_dirs(dupe.path[:-1])
return True
def _do_load(self, j): def _do_load(self, j):
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml')) self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
@@ -88,8 +90,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
j = j.start_subjob([1, 9]) j = j.start_subjob([1, 9])
self.results.load_from_xml(op.join(self.appdata, 'last_results.xml'), self._get_file, j) self.results.load_from_xml(op.join(self.appdata, 'last_results.xml'), self._get_file, j)
files = flatten(g[:] for g in self.results.groups) files = flatten(g[:] for g in self.results.groups)
try:
for file in j.iter_with_progress(files, 'Reading metadata %d/%d'): for file in j.iter_with_progress(files, 'Reading metadata %d/%d'):
file._read_all_info(attrnames=self.data.METADATA_TO_READ) file._read_all_info(attrnames=self.data.METADATA_TO_READ)
except OSError:
# 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.
self.results.groups = []
def _get_display_info(self, dupe, group, delta=False): def _get_display_info(self, dupe, group, delta=False):
if (dupe is None) or (group is None): if (dupe is None) or (group is None):
@@ -113,10 +121,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def _open_path(path): def _open_path(path):
raise NotImplementedError() raise NotImplementedError()
@staticmethod
def _recycle_dupe(dupe):
raise NotImplementedError()
@staticmethod @staticmethod
def _reveal_path(path): def _reveal_path(path):
raise NotImplementedError() raise NotImplementedError()
@@ -239,7 +243,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
if g not in changed_groups: if g not in changed_groups:
self.results.make_ref(dupe) self.results.make_ref(dupe)
changed_groups.add(g) changed_groups.add(g)
self.notify('results_switched') self.notify('results_changed_but_keep_selection')
def mark_all(self): def mark_all(self):
self.results.mark_all() self.results.mark_all()
@@ -276,7 +280,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def remove_duplicates(self, duplicates): def remove_duplicates(self, duplicates):
self.results.remove_duplicates(self.without_ref(duplicates)) self.results.remove_duplicates(self.without_ref(duplicates))
self.notify('results_changed') self.notify('results_changed_but_keep_selection')
def remove_marked(self): def remove_marked(self):
self.results.perform_on_marked(lambda x:True, True) self.results.perform_on_marked(lambda x:True, True)

View File

@@ -13,10 +13,10 @@ from hsutil import cocoa, job
from hsutil.cocoa import install_exception_hook from hsutil.cocoa import install_exception_hook
from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults, from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask, NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
NSWorkspace, NSWorkspaceRecycleOperation) NSWorkspace)
from hsutil.reg import RegistrationRequired from hsutil.reg import RegistrationRequired
from . import app, fs from . import app
JOBID2TITLE = { JOBID2TITLE = {
app.JOB_SCAN: "Scanning for duplicates", app.JOB_SCAN: "Scanning for duplicates",
@@ -51,14 +51,6 @@ class DupeGuru(app.DupeGuru):
def _open_path(path): def _open_path(path):
NSWorkspace.sharedWorkspace().openFile_(unicode(path)) NSWorkspace.sharedWorkspace().openFile_(unicode(path))
@staticmethod
def _recycle_dupe(dupe):
# local import because first appkit import takes a lot of memory. we want to avoid it.
directory = unicode(dupe.path[:-1])
filename = dupe.name
result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
NSWorkspaceRecycleOperation, directory, '', [filename], None)
@staticmethod @staticmethod
def _reveal_path(path): def _reveal_path(path):
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(unicode(path), '') NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(unicode(path), '')

View File

@@ -6,7 +6,7 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
import xml.dom.minidom from lxml import etree
from hsutil import io from hsutil import io
from hsutil.files import FileOrPath from hsutil.files import FileOrPath
@@ -126,38 +126,38 @@ class Directories(object):
def load_from_file(self, infile): def load_from_file(self, infile):
try: try:
doc = xml.dom.minidom.parse(infile) root = etree.parse(infile).getroot()
except: except:
return return
root_path_nodes = doc.getElementsByTagName('root_directory') for rdn in root.iterchildren('root_directory'):
for rdn in root_path_nodes: attrib = rdn.attrib
if not rdn.getAttributeNode('path'): if 'path' not in attrib:
continue continue
path = rdn.getAttributeNode('path').nodeValue path = attrib['path']
try: try:
self.add_path(Path(path)) self.add_path(Path(path))
except (AlreadyThereError, InvalidPathError): except (AlreadyThereError, InvalidPathError):
pass pass
state_nodes = doc.getElementsByTagName('state') for sn in root.iterchildren('state'):
for sn in state_nodes: attrib = sn.attrib
if not (sn.getAttributeNode('path') and sn.getAttributeNode('value')): if not ('path' in attrib and 'value' in attrib):
continue continue
path = sn.getAttributeNode('path').nodeValue path = attrib['path']
state = sn.getAttributeNode('value').nodeValue state = attrib['value']
self.set_state(Path(path), int(state)) self.set_state(Path(path), int(state))
def save_to_file(self, outfile): def save_to_file(self, outfile):
with FileOrPath(outfile, 'wb') as fp: with FileOrPath(outfile, 'wb') as fp:
doc = xml.dom.minidom.Document() root = etree.Element('directories')
root = doc.appendChild(doc.createElement('directories'))
for root_path in self: for root_path in self:
root_path_node = root.appendChild(doc.createElement('root_directory')) root_path_node = etree.SubElement(root, 'root_directory')
root_path_node.setAttribute('path', unicode(root_path).encode('utf-8')) root_path_node.set('path', unicode(root_path))
for path, state in self.states.iteritems(): for path, state in self.states.iteritems():
state_node = root.appendChild(doc.createElement('state')) state_node = etree.SubElement(root, 'state')
state_node.setAttribute('path', unicode(path).encode('utf-8')) state_node.set('path', unicode(path))
state_node.setAttribute('value', str(state)) state_node.set('value', unicode(state))
doc.writexml(fp, '\t', '\t', '\n', encoding='utf-8') tree = etree.ElementTree(root)
tree.write(fp, encoding='utf-8')
def set_state(self, path, state): def set_state(self, path, state):
if self.get_state(path) == state: if self.get_state(path) == state:

View File

@@ -27,6 +27,6 @@ class GUIObject(Listener):
def results_changed(self): def results_changed(self):
pass pass
def results_switched(self): def results_changed_but_keep_selection(self):
pass pass

View File

@@ -149,7 +149,7 @@ class ResultTree(GUIObject, Tree):
self._refresh() self._refresh()
self.view.refresh() self.view.refresh()
def results_switched(self): def results_changed_but_keep_selection(self):
# What we want to to here is that instead of restoring selected *dupes* after refresh, we # What we want to to here is that instead of restoring selected *dupes* after refresh, we
# restore selected *paths*. # restore selected *paths*.
paths = self.selected_paths paths = self.selected_paths

View File

@@ -6,9 +6,9 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
from hsutil.files import FileOrPath from lxml import etree
import xml.dom.minidom from hsutil.files import FileOrPath
class IgnoreList(object): class IgnoreList(object):
"""An ignore list implementation that is iterable, filterable and exportable to XML. """An ignore list implementation that is iterable, filterable and exportable to XML.
@@ -77,19 +77,16 @@ class IgnoreList(object):
infile can be a file object or a filename. infile can be a file object or a filename.
""" """
try: try:
doc = xml.dom.minidom.parse(infile) root = etree.parse(infile).getroot()
except Exception: except Exception:
return return
file_nodes = doc.getElementsByTagName('file') for fn in root.iterchildren('file'):
for fn in file_nodes: file_path = fn.get('path')
if not fn.getAttributeNode('path'): if not file_path:
continue continue
file_path = fn.getAttributeNode('path').nodeValue for sfn in fn.iterchildren('file'):
subfile_nodes = fn.getElementsByTagName('file') subfile_path = sfn.get('path')
for sfn in subfile_nodes: if subfile_path:
if not sfn.getAttributeNode('path'):
continue
subfile_path = sfn.getAttributeNode('path').nodeValue
self.Ignore(file_path, subfile_path) self.Ignore(file_path, subfile_path)
def save_to_xml(self, outfile): def save_to_xml(self, outfile):
@@ -97,19 +94,15 @@ class IgnoreList(object):
outfile can be a file object or a filename. outfile can be a file object or a filename.
""" """
doc = xml.dom.minidom.Document() root = etree.Element('ignore_list')
root = doc.appendChild(doc.createElement('ignore_list')) for filename, subfiles in self._ignored.items():
for file,subfiles in self._ignored.items(): file_node = etree.SubElement(root, 'file')
file_node = root.appendChild(doc.createElement('file')) file_node.set('path', filename)
if isinstance(file,unicode): for subfilename in subfiles:
file = file.encode('utf-8') subfile_node = etree.SubElement(file_node, 'file')
file_node.setAttribute('path',file) subfile_node.set('path', subfilename)
for subfile in subfiles: tree = etree.ElementTree(root)
subfile_node = file_node.appendChild(doc.createElement('file'))
if isinstance(subfile,unicode):
subfile = subfile.encode('utf-8')
subfile_node.setAttribute('path',subfile)
with FileOrPath(outfile, 'wb') as fp: with FileOrPath(outfile, 'wb') as fp:
doc.writexml(fp,'\t','\t','\n',encoding='utf-8') tree.write(fp, encoding='utf-8')

View File

@@ -8,16 +8,14 @@
import logging import logging
import re import re
from xml.sax import handler, make_parser, SAXException from lxml import etree
from xml.sax.saxutils import XMLGenerator
from xml.sax.xmlreader import AttributesImpl
from . import engine from . import engine
from hsutil.job import nulljob from hsutil.job import nulljob
from hsutil.markable import Markable from hsutil.markable import Markable
from hsutil.misc import flatten, cond, nonone from hsutil.misc import flatten, nonone
from hsutil.str import format_size from hsutil.str import format_size
from hsutil.files import open_if_filename from hsutil.files import FileOrPath
class Results(Markable): class Results(Markable):
#---Override #---Override
@@ -168,42 +166,54 @@ class Results(Markable):
is_markable = _is_markable is_markable = _is_markable
def load_from_xml(self, infile, get_file, j=nulljob): def load_from_xml(self, infile, get_file, j=nulljob):
def do_match(ref_file, other_files, group):
if not other_files:
return
for other_file in other_files:
group.add_match(engine.get_match(ref_file, other_file))
do_match(other_files[0], other_files[1:], group)
self.apply_filter(None) self.apply_filter(None)
handler = _ResultsHandler(get_file)
try: try:
parser = make_parser() root = etree.parse(infile).getroot()
except Exception as e: except Exception:
# This special handling is to try to figure out the cause of #47
# We don't silently return, because we want the user to send error report.
logging.exception(e)
try:
import xml.parsers.expat
logging.warning('importing xml.parsers.expat went ok, WTF?')
except Exception as e:
# This log should give a little more details about the cause of this all
logging.exception(e)
raise
raise
parser.setContentHandler(handler)
try:
infile, must_close = open_if_filename(infile)
except IOError:
return return
BUFSIZE = 1024 * 1024 # 1mb buffer group_elems = list(root.iterchildren('group'))
infile.seek(0, 2) groups = []
j.start_job(infile.tell() // BUFSIZE) marked = set()
infile.seek(0, 0) for group_elem in j.iter_with_progress(group_elems, every=100):
group = engine.Group()
dupes = []
for file_elem in group_elem.iterchildren('file'):
path = file_elem.get('path')
words = file_elem.get('words', '')
if not path:
continue
file = get_file(path)
if file is None:
continue
file.words = words.split(',')
file.is_ref = file_elem.get('is_ref') == 'y'
dupes.append(file)
if file_elem.get('marked') == 'y':
marked.add(file)
for match_elem in group_elem.iterchildren('match'):
try: try:
while True: attrs = match_elem.attrib
data = infile.read(BUFSIZE) first_file = dupes[int(attrs['first'])]
if not data: second_file = dupes[int(attrs['second'])]
break percentage = int(attrs['percentage'])
parser.feed(data) group.add_match(engine.Match(first_file, second_file, percentage))
except (IndexError, KeyError, ValueError): # Covers missing attr, non-int values and indexes out of bounds
pass
if (not group.matches) and (len(dupes) >= 2):
do_match(dupes[0], dupes[1:], group)
group.prioritize(lambda x: dupes.index(x))
if len(group):
groups.append(group)
j.add_progress() j.add_progress()
except SAXException: self.groups = groups
return for dupe_file in marked:
self.groups = handler.groups
for dupe_file in handler.marked:
self.mark(dupe_file) self.mark(dupe_file)
def make_ref(self, dupe): def make_ref(self, dupe):
@@ -256,13 +266,10 @@ class Results(Markable):
def save_to_xml(self, outfile): def save_to_xml(self, outfile):
self.apply_filter(None) self.apply_filter(None)
outfile, must_close = open_if_filename(outfile, 'wb') root = etree.Element('results')
writer = XMLGenerator(outfile, 'utf-8') # writer = XMLGenerator(outfile, 'utf-8')
writer.startDocument()
empty_attrs = AttributesImpl({})
writer.startElement('results', empty_attrs)
for g in self.groups: for g in self.groups:
writer.startElement('group', empty_attrs) group_elem = etree.SubElement(root, 'group')
dupe2index = {} dupe2index = {}
for index, d in enumerate(g): for index, d in enumerate(g):
dupe2index[d] = index dupe2index[d] = index
@@ -270,27 +277,19 @@ class Results(Markable):
words = engine.unpack_fields(d.words) words = engine.unpack_fields(d.words)
except AttributeError: except AttributeError:
words = () words = ()
attrs = AttributesImpl({ file_elem = etree.SubElement(group_elem, 'file')
'path': unicode(d.path), file_elem.set('path', unicode(d.path))
'is_ref': cond(d.is_ref, 'y', 'n'), file_elem.set('is_ref', ('y' if d.is_ref else 'n'))
'words': ','.join(words), file_elem.set('words', ','.join(words))
'marked': cond(self.is_marked(d), 'y', 'n') file_elem.set('marked', ('y' if self.is_marked(d) else 'n'))
})
writer.startElement('file', attrs)
writer.endElement('file')
for match in g.matches: for match in g.matches:
attrs = AttributesImpl({ match_elem = etree.SubElement(group_elem, 'match')
'first': str(dupe2index[match.first]), match_elem.set('first', unicode(dupe2index[match.first]))
'second': str(dupe2index[match.second]), match_elem.set('second', unicode(dupe2index[match.second]))
'percentage': str(int(match.percentage)), match_elem.set('percentage', unicode(int(match.percentage)))
}) tree = etree.ElementTree(root)
writer.startElement('match', attrs) with FileOrPath(outfile, 'wb') as fp:
writer.endElement('match') tree.write(fp, encoding='utf-8')
writer.endElement('group')
writer.endElement('results')
writer.endDocument()
if must_close:
outfile.close()
def sort_dupes(self, key, asc=True, delta=False): def sort_dupes(self, key, asc=True, delta=False):
if not self.__dupes: if not self.__dupes:
@@ -310,60 +309,3 @@ class Results(Markable):
dupes = property(__get_dupe_list) dupes = property(__get_dupe_list)
groups = property(__get_groups, __set_groups) groups = property(__get_groups, __set_groups)
stat_line = property(__get_stat_line) stat_line = property(__get_stat_line)
class _ResultsHandler(handler.ContentHandler):
def __init__(self, get_file):
self.group = None
self.dupes = None
self.marked = set()
self.groups = []
self.get_file = get_file
def startElement(self, name, attrs):
if name == 'group':
self.group = engine.Group()
self.dupes = []
return
if (name == 'file') and (self.group is not None):
if not (('path' in attrs) and ('words' in attrs)):
return
path = attrs['path']
file = self.get_file(path)
if file is None:
return
file.words = attrs['words'].split(',')
file.is_ref = attrs.get('is_ref') == 'y'
self.dupes.append(file)
if attrs.get('marked') == 'y':
self.marked.add(file)
if (name == 'match') and (self.group is not None):
try:
first_file = self.dupes[int(attrs['first'])]
second_file = self.dupes[int(attrs['second'])]
percentage = int(attrs['percentage'])
self.group.add_match(engine.Match(first_file, second_file, percentage))
except (IndexError, KeyError, ValueError): # Covers missing attr, non-int values and indexes out of bounds
pass
def endElement(self, name):
def do_match(ref_file, other_files, group):
if not other_files:
return
for other_file in other_files:
group.add_match(engine.get_match(ref_file, other_file))
do_match(other_files[0], other_files[1:], group)
if name == 'group':
group = self.group
self.group = None
dupes = self.dupes
self.dupes = []
if group is None:
return
if len(dupes) < 2:
return
if not group.matches: # <match> elements not present, do it manually, without %
do_match(dupes[0], dupes[1:], group)
group.prioritize(lambda x: dupes.index(x))
self.groups.append(group)

View File

@@ -248,7 +248,7 @@ class TCDupeGuruWithResults(TestCase):
self.rtree.selected_paths = paths self.rtree.selected_paths = paths
self.app.remove_selected() self.app.remove_selected()
# The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos. # The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos.
eq_(self.rtree.selected_paths, [[0]]) # no exception eq_(self.rtree.selected_paths, [[0, 0]]) # no exception
def test_selectResultNodePaths(self): def test_selectResultNodePaths(self):
app = self.app app = self.app
@@ -366,10 +366,7 @@ class TCDupeGuruWithResults(TestCase):
app = self.app app = self.app
self.rtree.selected_paths = [[0, 0], [1, 0]] self.rtree.selected_paths = [[0, 0], [1, 0]]
app.remove_selected() app.remove_selected()
eq_(len(app.results.dupes), 1) eq_(len(app.results.dupes), 1) # the first path is now selected
app.remove_selected()
eq_(len(app.results.dupes), 1)
self.rtree.selected_path = [0, 0]
app.remove_selected() app.remove_selected()
eq_(len(app.results.dupes), 0) eq_(len(app.results.dupes), 0)

View File

@@ -229,10 +229,9 @@ class TCbuild_word_dict(TestCase):
self.log = [] self.log = []
s = "foo bar" s = "foo bar"
build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j) build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
# We don't have intermediate log because iter_with_progress is called with every > 1
self.assertEqual(0,self.log[0]) self.assertEqual(0,self.log[0])
self.assertEqual(33,self.log[1]) self.assertEqual(100,self.log[1])
self.assertEqual(66,self.log[2])
self.assertEqual(100,self.log[3])
class TCmerge_similar_words(TestCase): class TCmerge_similar_words(TestCase):

View File

@@ -7,7 +7,7 @@
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
import cStringIO import cStringIO
import xml.dom.minidom from lxml import etree
from nose.tools import eq_ from nose.tools import eq_
@@ -62,16 +62,14 @@ def test_save_to_xml():
f = cStringIO.StringIO() f = cStringIO.StringIO()
il.save_to_xml(f) il.save_to_xml(f)
f.seek(0) f.seek(0)
doc = xml.dom.minidom.parse(f) doc = etree.parse(f)
root = doc.documentElement root = doc.getroot()
eq_('ignore_list',root.nodeName) eq_(root.tag, 'ignore_list')
children = [c for c in root.childNodes if c.localName] eq_(len(root), 2)
eq_(2,len(children)) eq_(len([c for c in root if c.tag == 'file']), 2)
eq_(2,len([c for c in children if c.nodeName == 'file'])) f1, f2 = root[:]
f1,f2 = children subchildren = [c for c in f1 if c.tag == 'file'] + [c for c in f2 if c.tag == 'file']
subchildren = [c for c in f1.childNodes if c.localName == 'file'] +\ eq_(len(subchildren), 3)
[c for c in f2.childNodes if c.localName == 'file']
eq_(3,len(subchildren))
def test_SaveThenLoad(): def test_SaveThenLoad():
il = IgnoreList() il = IgnoreList()
@@ -82,6 +80,7 @@ def test_SaveThenLoad():
f = cStringIO.StringIO() f = cStringIO.StringIO()
il.save_to_xml(f) il.save_to_xml(f)
f.seek(0) f.seek(0)
f.seek(0)
il = IgnoreList() il = IgnoreList()
il.load_from_xml(f) il.load_from_xml(f)
eq_(4,len(il)) eq_(4,len(il))
@@ -129,9 +128,9 @@ def test_filter():
assert not il.AreIgnored('foo','bar') assert not il.AreIgnored('foo','bar')
assert il.AreIgnored('bar','baz') assert il.AreIgnored('bar','baz')
def test_save_with_non_ascii_non_unicode_items(): def test_save_with_non_ascii_items():
il = IgnoreList() il = IgnoreList()
il.Ignore('\xac','\xbf') il.Ignore(u'\xac', u'\xbf')
f = cStringIO.StringIO() f = cStringIO.StringIO()
try: try:
il.save_to_xml(f) il.save_to_xml(f)

View File

@@ -7,10 +7,9 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
import unittest
import StringIO import StringIO
import xml.dom.minidom
import os.path as op import os.path as op
from lxml import etree
from hsutil.path import Path from hsutil.path import Path
from hsutil.testcase import TestCase from hsutil.testcase import TestCase
@@ -18,7 +17,7 @@ from hsutil.misc import first
from . import engine_test, data from . import engine_test, data
from .. import engine from .. import engine
from ..results import * from ..results import Results
class NamedObject(engine_test.NamedObject): class NamedObject(engine_test.NamedObject):
path = property(lambda x:Path('basepath') + x.name) path = property(lambda x:Path('basepath') + x.name)
@@ -65,9 +64,9 @@ class TCResultsEmpty(TestCase):
f = StringIO.StringIO() f = StringIO.StringIO()
self.results.save_to_xml(f) self.results.save_to_xml(f)
f.seek(0) f.seek(0)
doc = xml.dom.minidom.parse(f) doc = etree.parse(f)
root = doc.documentElement root = doc.getroot()
self.assertEqual('results',root.nodeName) self.assertEqual('results', root.tag)
class TCResultsWithSomeGroups(TestCase): class TCResultsWithSomeGroups(TestCase):
@@ -321,16 +320,16 @@ class TCResultsMarkings(TestCase):
f = StringIO.StringIO() f = StringIO.StringIO()
self.results.save_to_xml(f) self.results.save_to_xml(f)
f.seek(0) f.seek(0)
doc = xml.dom.minidom.parse(f) doc = etree.parse(f)
root = doc.documentElement root = doc.getroot()
g1,g2 = root.getElementsByTagName('group') g1, g2 = root.iterchildren('group')
d1,d2,d3 = g1.getElementsByTagName('file') d1, d2, d3 = g1.iterchildren('file')
self.assertEqual('n',d1.getAttributeNode('marked').nodeValue) self.assertEqual('n', d1.get('marked'))
self.assertEqual('n',d2.getAttributeNode('marked').nodeValue) self.assertEqual('n', d2.get('marked'))
self.assertEqual('y',d3.getAttributeNode('marked').nodeValue) self.assertEqual('y', d3.get('marked'))
d1,d2 = g2.getElementsByTagName('file') d1, d2 = g2.iterchildren('file')
self.assertEqual('n',d1.getAttributeNode('marked').nodeValue) self.assertEqual('n', d1.get('marked'))
self.assertEqual('y',d2.getAttributeNode('marked').nodeValue) self.assertEqual('y', d2.get('marked'))
def test_LoadXML(self): def test_LoadXML(self):
def get_file(path): def get_file(path):
@@ -366,38 +365,35 @@ class TCResultsXML(TestCase):
f = StringIO.StringIO() f = StringIO.StringIO()
self.results.save_to_xml(f) self.results.save_to_xml(f)
f.seek(0) f.seek(0)
doc = xml.dom.minidom.parse(f) doc = etree.parse(f)
root = doc.documentElement root = doc.getroot()
self.assertEqual('results',root.nodeName) self.assertEqual('results', root.tag)
children = [c for c in root.childNodes if c.localName] self.assertEqual(2, len(root))
self.assertEqual(2,len(children)) self.assertEqual(2, len([c for c in root if c.tag == 'group']))
self.assertEqual(2,len([c for c in children if c.nodeName == 'group'])) g1, g2 = root
g1,g2 = children self.assertEqual(6,len(g1))
children = [c for c in g1.childNodes if c.localName] self.assertEqual(3,len([c for c in g1 if c.tag == 'file']))
self.assertEqual(6,len(children)) self.assertEqual(3,len([c for c in g1 if c.tag == 'match']))
self.assertEqual(3,len([c for c in children if c.nodeName == 'file'])) d1, d2, d3 = [c for c in g1 if c.tag == 'file']
self.assertEqual(3,len([c for c in children if c.nodeName == 'match'])) self.assertEqual(op.join('basepath','foo bar'),d1.get('path'))
d1,d2,d3 = [c for c in children if c.nodeName == 'file'] self.assertEqual(op.join('basepath','bar bleh'),d2.get('path'))
self.assertEqual(op.join('basepath','foo bar'),d1.getAttributeNode('path').nodeValue) self.assertEqual(op.join('basepath','foo bleh'),d3.get('path'))
self.assertEqual(op.join('basepath','bar bleh'),d2.getAttributeNode('path').nodeValue) self.assertEqual('y',d1.get('is_ref'))
self.assertEqual(op.join('basepath','foo bleh'),d3.getAttributeNode('path').nodeValue) self.assertEqual('n',d2.get('is_ref'))
self.assertEqual('y',d1.getAttributeNode('is_ref').nodeValue) self.assertEqual('n',d3.get('is_ref'))
self.assertEqual('n',d2.getAttributeNode('is_ref').nodeValue) self.assertEqual('foo,bar',d1.get('words'))
self.assertEqual('n',d3.getAttributeNode('is_ref').nodeValue) self.assertEqual('bar,bleh',d2.get('words'))
self.assertEqual('foo,bar',d1.getAttributeNode('words').nodeValue) self.assertEqual('foo,bleh',d3.get('words'))
self.assertEqual('bar,bleh',d2.getAttributeNode('words').nodeValue) self.assertEqual(3,len(g2))
self.assertEqual('foo,bleh',d3.getAttributeNode('words').nodeValue) self.assertEqual(2,len([c for c in g2 if c.tag == 'file']))
children = [c for c in g2.childNodes if c.localName] self.assertEqual(1,len([c for c in g2 if c.tag == 'match']))
self.assertEqual(3,len(children)) d1, d2 = [c for c in g2 if c.tag == 'file']
self.assertEqual(2,len([c for c in children if c.nodeName == 'file'])) self.assertEqual(op.join('basepath','ibabtu'),d1.get('path'))
self.assertEqual(1,len([c for c in children if c.nodeName == 'match'])) self.assertEqual(op.join('basepath','ibabtu'),d2.get('path'))
d1,d2 = [c for c in children if c.nodeName == 'file'] self.assertEqual('n',d1.get('is_ref'))
self.assertEqual(op.join('basepath','ibabtu'),d1.getAttributeNode('path').nodeValue) self.assertEqual('n',d2.get('is_ref'))
self.assertEqual(op.join('basepath','ibabtu'),d2.getAttributeNode('path').nodeValue) self.assertEqual('ibabtu',d1.get('words'))
self.assertEqual('n',d1.getAttributeNode('is_ref').nodeValue) self.assertEqual('ibabtu',d2.get('words'))
self.assertEqual('n',d2.getAttributeNode('is_ref').nodeValue)
self.assertEqual('ibabtu',d1.getAttributeNode('words').nodeValue)
self.assertEqual('ibabtu',d2.getAttributeNode('words').nodeValue)
def test_LoadXML(self): def test_LoadXML(self):
def get_file(path): def get_file(path):
@@ -460,41 +456,41 @@ class TCResultsXML(TestCase):
def get_file(path): def get_file(path):
return [f for f in self.objects if str(f.path) == path][0] return [f for f in self.objects if str(f.path) == path][0]
doc = xml.dom.minidom.Document() root = etree.Element('foobar') #The root element shouldn't matter, really.
root = doc.appendChild(doc.createElement('foobar')) #The root element shouldn't matter, really. group_node = etree.SubElement(root, 'group')
group_node = root.appendChild(doc.createElement('group')) dupe_node = etree.SubElement(group_node, 'file') #Perfectly correct file
dupe_node = group_node.appendChild(doc.createElement('file')) #Perfectly correct file dupe_node.set('path', op.join('basepath','foo bar'))
dupe_node.setAttribute('path',op.join('basepath','foo bar')) dupe_node.set('is_ref', 'y')
dupe_node.setAttribute('is_ref','y') dupe_node.set('words', 'foo,bar')
dupe_node.setAttribute('words','foo,bar') dupe_node = etree.SubElement(group_node, 'file') #is_ref missing, default to 'n'
dupe_node = group_node.appendChild(doc.createElement('file')) #is_ref missing, default to 'n' dupe_node.set('path',op.join('basepath','foo bleh'))
dupe_node.setAttribute('path',op.join('basepath','foo bleh')) dupe_node.set('words','foo,bleh')
dupe_node.setAttribute('words','foo,bleh') dupe_node = etree.SubElement(group_node, 'file') #words are missing, valid.
dupe_node = group_node.appendChild(doc.createElement('file')) #words are missing, invalid. dupe_node.set('path',op.join('basepath','bar bleh'))
dupe_node.setAttribute('path',op.join('basepath','bar bleh')) dupe_node = etree.SubElement(group_node, 'file') #path is missing, invalid.
dupe_node = group_node.appendChild(doc.createElement('file')) #path is missing, invalid. dupe_node.set('words','foo,bleh')
dupe_node.setAttribute('words','foo,bleh') dupe_node = etree.SubElement(group_node, 'foobar') #Invalid element name
dupe_node = group_node.appendChild(doc.createElement('foobar')) #Invalid element name dupe_node.set('path',op.join('basepath','bar bleh'))
dupe_node.setAttribute('path',op.join('basepath','bar bleh')) dupe_node.set('is_ref','y')
dupe_node.setAttribute('is_ref','y') dupe_node.set('words','bar,bleh')
dupe_node.setAttribute('words','bar,bleh') match_node = etree.SubElement(group_node, 'match') # match pointing to a bad index
match_node = group_node.appendChild(doc.createElement('match')) # match pointing to a bad index match_node.set('first', '42')
match_node.setAttribute('first', '42') match_node.set('second', '45')
match_node.setAttribute('second', '45') match_node = etree.SubElement(group_node, 'match') # match with missing attrs
match_node = group_node.appendChild(doc.createElement('match')) # match with missing attrs match_node = etree.SubElement(group_node, 'match') # match with non-int values
match_node = group_node.appendChild(doc.createElement('match')) # match with non-int values match_node.set('first', 'foo')
match_node.setAttribute('first', 'foo') match_node.set('second', 'bar')
match_node.setAttribute('second', 'bar') match_node.set('percentage', 'baz')
match_node.setAttribute('percentage', 'baz') group_node = etree.SubElement(root, 'foobar') #invalid group
group_node = root.appendChild(doc.createElement('foobar')) #invalid group group_node = etree.SubElement(root, 'group') #empty group
group_node = root.appendChild(doc.createElement('group')) #empty group
f = StringIO.StringIO() f = StringIO.StringIO()
doc.writexml(f,'\t','\t','\n',encoding='utf-8') tree = etree.ElementTree(root)
tree.write(f, encoding='utf-8')
f.seek(0) f.seek(0)
r = Results(data) r = Results(data)
r.load_from_xml(f, get_file) r.load_from_xml(f, get_file)
self.assertEqual(1,len(r.groups)) self.assertEqual(1,len(r.groups))
self.assertEqual(2,len(r.groups[0])) self.assertEqual(3,len(r.groups[0]))
def test_xml_non_ascii(self): def test_xml_non_ascii(self):
def get_file(path): def get_file(path):

View File

@@ -11,6 +11,7 @@ import logging
import plistlib import plistlib
import re import re
from lxml import etree
from appscript import app, k, CommandError from appscript import app, k, CommandError
from hsutil import io from hsutil import io
@@ -68,15 +69,10 @@ def get_iphoto_database_path():
def get_iphoto_pictures(plistpath): def get_iphoto_pictures(plistpath):
if not io.exists(plistpath): if not io.exists(plistpath):
return [] return []
s = io.open(plistpath).read() # We make the xml go through lxml so that it can fix broken xml which iPhoto sometimes produces.
# There was a case where a guy had 0x10 chars in his plist, causing expat errors on loading parser = etree.XMLParser(recover=True)
s = s.replace('\x10', '') root = etree.parse(io.open(plistpath), parser=parser).getroot()
# It seems that iPhoto sometimes doesn't properly escape & chars. The regexp below is to find s = etree.tostring(root)
# any & char that is not a &-based entity (&amp;, &quot;, etc.). based on TextMate's XML
# bundle's regexp
s, count = re.subn(r'&(?![a-zA-Z0-9_-]+|#[0-9]+|#x[0-9a-fA-F]+;)', '', s)
if count:
logging.warning("%d invalid XML entities replacement made", count)
plist = plistlib.readPlistFromString(s) plist = plistlib.readPlistFromString(s)
result = [] result = []
for photo_data in plist['Master Image List'].values(): for photo_data in plist['Master Image List'].values():

View File

@@ -111,8 +111,13 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
others = [pic for pic in others if not pic.is_ref] others = [pic for pic in others if not pic.is_ref]
if others: if others:
cache_ids = [f.cache_id for f in others] cache_ids = [f.cache_id for f in others]
args = (ref.cache_id, cache_ids, cache_path, threshold) # We limit the number of cache_ids we send for multi-processing because otherwise, we
# might get an error saying "String or BLOB exceeded size limit"
ARG_LIMIT = 1000
while cache_ids:
args = (ref.cache_id, cache_ids[:ARG_LIMIT], cache_path, threshold)
async_results.append(pool.apply_async(async_compare, args)) async_results.append(pool.apply_async(async_compare, args))
cache_ids = cache_ids[ARG_LIMIT:]
if len(async_results) > RESULTS_QUEUE_LIMIT: if len(async_results) > RESULTS_QUEUE_LIMIT:
result = async_results.pop(0) result = async_results.pop(0)
matches.extend(result.get()) matches.extend(result.get())

12
debian_me/control Normal file
View File

@@ -0,0 +1,12 @@
Source: dupeguru-me
Section: devel
Priority: extra
Maintainer: Virgil Dupras <hsoft@hardcoded.net>
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage: http://www.hardcoded.net
Package: dupeguru-me
Architecture: any
Depends: python (>= 2.6), python-qt4 (>= 4.6), python-lxml (>= 2.1)
Description: dupeGuru Music Edition

11
debian_me/copyright Normal file
View File

@@ -0,0 +1,11 @@
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.

3
debian_me/dirs Normal file
View File

@@ -0,0 +1,3 @@
usr/local/bin
usr/local/share
usr/share/applications

View File

@@ -0,0 +1,10 @@
[Desktop Entry]
Encoding=UTF-8
Name=dupeGuru Music Edition
Comment=Find duplicate songs in your collection.
Exec=dupeguru_me
Icon=/usr/local/share/dupeguru_me/dgme_logo_128.png
Terminal=false
Type=Application
Categories=Utility

86
debian_me/rules Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
chmod +x src/start.py
cp -R src/ $(CURDIR)/debian/tmp/usr/local/share/dupeguru_me
cp $(CURDIR)/debian/dupeguru_me.desktop $(CURDIR)/debian/tmp/usr/share/applications
ln -s /usr/local/share/dupeguru_me/start.py $(CURDIR)/debian/tmp/usr/local/bin/dupeguru_me
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_install
dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

12
debian_pe/control Normal file
View File

@@ -0,0 +1,12 @@
Source: dupeguru-pe
Section: devel
Priority: extra
Maintainer: Virgil Dupras <hsoft@hardcoded.net>
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage: http://www.hardcoded.net
Package: dupeguru-pe
Architecture: any
Depends: python (>= 2.6), python-qt4 (>= 4.6), python-lxml (>= 2.1), python-imaging (>= 1.1.6)
Description: dupeGuru Picture Edition

11
debian_pe/copyright Normal file
View File

@@ -0,0 +1,11 @@
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.

3
debian_pe/dirs Normal file
View File

@@ -0,0 +1,3 @@
usr/local/bin
usr/local/share
usr/share/applications

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Name=dupeGuru Picture Edition
Comment=Find duplicate pictures in your library.
Exec=dupeguru_pe
Icon=/usr/local/share/dupeguru_pe/dgpe_logo_128.png
Terminal=false
Type=Application
Categories=Utility

86
debian_pe/rules Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
chmod +x src/start.py
cp -R src/ $(CURDIR)/debian/tmp/usr/local/share/dupeguru_pe
cp $(CURDIR)/debian/dupeguru_pe.desktop $(CURDIR)/debian/tmp/usr/share/applications
ln -s /usr/local/share/dupeguru_pe/start.py $(CURDIR)/debian/tmp/usr/local/bin/dupeguru_pe
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_install
dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

12
debian_se/control Normal file
View File

@@ -0,0 +1,12 @@
Source: dupeguru-se
Section: devel
Priority: extra
Maintainer: Virgil Dupras <hsoft@hardcoded.net>
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage: http://www.hardcoded.net
Package: dupeguru-se
Architecture: any
Depends: python (>= 2.6), python-qt4 (>= 4.6), python-lxml (>= 2.1)
Description: dupeGuru

11
debian_se/copyright Normal file
View File

@@ -0,0 +1,11 @@
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.

3
debian_se/dirs Normal file
View File

@@ -0,0 +1,3 @@
usr/local/bin
usr/local/share
usr/share/applications

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Name=dupeGuru
Comment=Find duplicate files.
Exec=dupeguru_se
Icon=/usr/local/share/dupeguru_se/dgse_logo_128.png
Terminal=false
Type=Application
Categories=Utility

86
debian_se/rules Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
chmod +x src/start.py
cp -R src/ $(CURDIR)/debian/tmp/usr/local/share/dupeguru_se
cp $(CURDIR)/debian/dupeguru_se.desktop $(CURDIR)/debian/tmp/usr/share/applications
ln -s /usr/local/share/dupeguru_se/start.py $(CURDIR)/debian/tmp/usr/local/bin/dupeguru_se
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_install
dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

View File

@@ -1,3 +1,17 @@
- date: 2010-04-08
version: 1.8.6
description: |
* Fixed a crash when performing very big scans.
* Fixed a rare crash during results loading. (#90)
- date: 2010-03-01
version: 1.8.5
description: |
* Fixed a bug preventing some iPhoto Libraries to be read. [Mac OS X]
* Improved results loading and saving speed.
- date: 2010-02-18
version: 1.8.4
description: |
* Fixed a glitch in the details panel causing it to sometimes show the wrong pictures.
- date: 2010-02-11 - date: 2010-02-11
version: 1.8.3 version: 1.8.3
description: | description: |

View File

@@ -10,11 +10,13 @@
import sys import sys
import os import os
import os.path as op import os.path as op
import compileall
import shutil import shutil
import yaml import yaml
from hsutil.build import build_dmg, add_to_pythonpath, print_and_do from hsutil.build import (build_dmg, add_to_pythonpath, print_and_do, copy_packages,
build_debian_changelog, copy_qt_plugins)
def package_cocoa(edition): def package_cocoa(edition):
app_path = { app_path = {
@@ -24,7 +26,7 @@ def package_cocoa(edition):
}[edition] }[edition]
build_dmg(app_path, '.') build_dmg(app_path, '.')
def package_qt(edition): def package_windows(edition, dev):
# On Windows, PyInstaller is used to build an exe (py2exe creates a very bad looking icon) # On Windows, PyInstaller is used to build an exe (py2exe creates a very bad looking icon)
# The release version is outdated. Use at least r672 on http://svn.pyinstaller.org/trunk # The release version is outdated. Use at least r672 on http://svn.pyinstaller.org/trunk
if sys.platform != "win32": if sys.platform != "win32":
@@ -36,47 +38,84 @@ def package_qt(edition):
os.chdir(op.join('qt', edition)) os.chdir(op.join('qt', edition))
from app import DupeGuru from app import DupeGuru
# Removing build and dist
if op.exists('build'):
shutil.rmtree('build')
if op.exists('dist'): if op.exists('dist'):
shutil.rmtree('dist') shutil.rmtree('dist')
version = DupeGuru.VERSION
versioncomma = version.replace('.', ', ') + ', 0'
verinfo = open('verinfo').read()
verinfo = verinfo.replace('$versioncomma', versioncomma).replace('$version', version)
fp = open('verinfo_tmp', 'w')
fp.write(verinfo)
fp.close()
print_and_do("python C:\\Python26\\pyinstaller\\Build.py dg{0}.spec".format(edition))
os.remove('verinfo_tmp')
print_and_do("del dist\\*90.dll") # They're in vcredist, no need to include them cmd = 'cxfreeze --base-name Win32GUI --target-name "{0}.exe" --icon {1} start.py'
print_and_do("del dist\\POWRPROF.dll") # no need of that crap target_name = {'se': 'dupeGuru', 'me': 'dupeGuru ME', 'pe': 'dupeGuru PE'}[edition]
print_and_do("del dist\\SHLWAPI.dll") # no need of that crap icon_path = '..\\..\\images\\dg{0}_logo.ico'.format(edition)
print_and_do("xcopy /Y /S /I ..\\..\\help_me\\dupeguru_me_help dist\\help") print_and_do(cmd.format(target_name, icon_path))
if not dev:
# Copy qt plugins
plugin_dest = op.join('dist', 'qt4_plugins')
plugin_names = ['accessible', 'codecs', 'iconengines', 'imageformats']
copy_qt_plugins(plugin_names, plugin_dest)
# Compress with UPX
libs = [name for name in os.listdir('dist') if op.splitext(name)[1] in ('.pyd', '.dll', '.exe')]
for lib in libs:
print_and_do("upx --best \"dist\\{0}\"".format(lib))
print_and_do("xcopy /Y /S /I ..\\..\\help_{0}\\dupeguru_{0}_help dist\\help".format(edition))
# AdvancedInstaller.com has to be in your PATH # AdvancedInstaller.com has to be in your PATH
# this is so we don'a have to re-commit installer.aip at every version change # this is so we don'a have to re-commit installer.aip at every version change
shutil.copy('installer.aip', 'installer_tmp.aip') shutil.copy('installer.aip', 'installer_tmp.aip')
print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion %s' % version) print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion %s' % DupeGuru.VERSION)
print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force') print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force')
os.remove('installer_tmp.aip') os.remove('installer_tmp.aip')
os.chdir(op.join('..', '..')) os.chdir(op.join('..', '..'))
def package_debian(edition):
add_to_pythonpath('qt')
add_to_pythonpath(op.join('qt', edition))
from app import DupeGuru
if op.exists('build'):
shutil.rmtree('build')
ed = lambda s: s.format(edition)
destpath = op.join('build', 'dupeguru-{0}-{1}'.format(edition, DupeGuru.VERSION))
srcpath = op.join(destpath, 'src')
help_src = ed('help_{0}')
os.makedirs(destpath)
shutil.copytree(ed('qt/{0}'), srcpath)
packages = ['hsutil', 'hsgui', 'core', ed('core_{0}'), 'qtlib', 'qt/base']
if edition == 'me':
packages.append('hsmedia')
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')
project_name = ed('dupeguru-{0}')
from_version = {'se': '2.9.2', 'me': '5.7.2', 'pe': '1.8.5'}[edition]
build_debian_changelog(yaml_path, changelog_dest, project_name, from_version=from_version)
help_name = {'se': 'dupeguru_help', 'me': 'dupeguru_me_help', 'pe': 'dupeguru_pe_help'}[edition]
shutil.copytree(op.join(help_src, help_name), op.join(srcpath, 'help'))
shutil.copy(op.join('images', ed('dg{0}_logo_128.png')), srcpath)
compileall.compile_dir(srcpath)
os.chdir(destpath)
os.system("dpkg-buildpackage")
def main(): def main():
conf = yaml.load(open('conf.yaml')) conf = yaml.load(open('conf.yaml'))
edition = conf['edition'] edition = conf['edition']
ui = conf['ui'] ui = conf['ui']
dev = conf['dev'] dev = conf['dev']
if dev:
print "You can't package in dev mode"
return
print "Packaging dupeGuru {0} with UI {1}".format(edition.upper(), ui) print "Packaging dupeGuru {0} with UI {1}".format(edition.upper(), ui)
if ui == 'cocoa': if ui == 'cocoa':
package_cocoa(edition) package_cocoa(edition)
elif ui == 'qt': elif ui == 'qt':
package_qt(edition) if sys.platform == "win32":
package_windows(edition, dev)
elif sys.platform == "linux2":
package_debian(edition)
else:
print "Qt packaging only works under Windows or Linux."
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -121,10 +121,6 @@ class DupeGuru(DupeGuruBase, QObject):
url = QUrl.fromLocalFile(unicode(path)) url = QUrl.fromLocalFile(unicode(path))
QDesktopServices.openUrl(url) QDesktopServices.openUrl(url)
@staticmethod
def _recycle_dupe(dupe):
platform.recycle_file(dupe.path)
@staticmethod @staticmethod
def _reveal_path(path): def _reveal_path(path):
DupeGuru._open_path(path[:-1]) DupeGuru._open_path(path[:-1])
@@ -187,7 +183,8 @@ class DupeGuru(DupeGuruBase, QObject):
self.directories_dialog.show() self.directories_dialog.show()
def show_help(self): def show_help(self):
url = QUrl.fromLocalFile(op.abspath('help/intro.htm')) base_path = platform.HELP_PATH.format(self.EDITION)
url = QUrl.fromLocalFile(op.abspath(op.join(base_path, 'intro.htm')))
QDesktopServices.openUrl(url) QDesktopServices.openUrl(url)
def show_preferences(self): def show_preferences(self):

9
qt/base/cxfreeze_fix.py Normal file
View File

@@ -0,0 +1,9 @@
# cxfreeze has some problems detecting all dependencies.
# This modules explicitly import those problematic modules.
import lxml._elementpath
import gzip
import os
os.environ['QT_PLUGIN_PATH'] = 'qt4_plugins'

View File

@@ -6,6 +6,8 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
import sys
from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView, from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView,
QMessageBox, QInputDialog, QLineEdit, QDesktopServices) QMessageBox, QInputDialog, QLineEdit, QDesktopServices)
@@ -86,6 +88,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.statusLabel = QLabel(self) self.statusLabel = QLabel(self)
self.statusbar.addPermanentWidget(self.statusLabel, 1) self.statusbar.addPermanentWidget(self.statusLabel, 1)
# Linux setup
if sys.platform == 'linux2':
self.actionCheckForUpdate.setVisible(False) # This only works on Windows
#--- Private #--- Private
def _confirm(self, title, msg, default_button=QMessageBox.Yes): def _confirm(self, title, msg, default_button=QMessageBox.Yes):
buttons = QMessageBox.Yes | QMessageBox.No buttons = QMessageBox.Yes | QMessageBox.No

View File

@@ -14,5 +14,7 @@ if sys.platform == 'win32':
from platform_win import * from platform_win import *
elif sys.platform == 'darwin': elif sys.platform == 'darwin':
from platform_osx import * from platform_osx import *
elif sys.platform == 'linux2':
from platform_lnx import *
else: else:
pass # unsupported platform pass # unsupported platform

11
qt/base/platform_lnx.py Normal file
View File

@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-02-13
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "HS" 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/hs_license
INITIAL_FOLDER_IN_DIALOGS = u'/'
HELP_PATH = '/usr/local/share/dupeguru_{0}/help'

View File

@@ -9,7 +9,5 @@
# dummy unit to allow the app to run under OSX during development # dummy unit to allow the app to run under OSX during development
INITIAL_FOLDER_IN_DIALOGS = '/' INITIAL_FOLDER_IN_DIALOGS = u'/'
HELP_PATH = ''
def recycle_file(path):
pass

View File

@@ -7,16 +7,5 @@
# which should be included with this package. The terms are also available at # which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license # http://www.hardcoded.net/licenses/hs_license
from __future__ import unicode_literals INITIAL_FOLDER_IN_DIALOGS = u'C:\\'
HELP_PATH = 'help'
import logging
import winshell
INITIAL_FOLDER_IN_DIALOGS = 'C:\\'
def recycle_file(path):
try:
winshell.delete_file(unicode(path), no_confirm=True, silent=True)
except winshell.x_winshell as e:
logging.warning("winshell error: %s", e)

View File

@@ -14,6 +14,7 @@ from preferences import Preferences
from preferences_dialog import PreferencesDialog from preferences_dialog import PreferencesDialog
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
EDITION = 'me'
LOGO_NAME = 'logo_me' LOGO_NAME = 'logo_me'
NAME = 'dupeGuru Music Edition' NAME = 'dupeGuru Music Edition'
VERSION = '5.7.2' VERSION = '5.7.2'

View File

@@ -1,19 +0,0 @@
# -*- mode: python -*-
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'start.py'],
pathex=[])
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
exclude_binaries=1,
name=os.path.join('build\\pyi.win32\\dupeGuru ME', 'dupeGuru ME.exe'),
debug=False,
strip=False,
upx=True,
console=False , icon='..\\..\\images\\dgme_logo.ico', version='verinfo_tmp')
coll = COLLECT( exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name=os.path.join('dist'))

View File

@@ -1,30 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="4.9.2" modules="professional" RootPath="." Language="en"> <DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5" modules="professional" RootPath="." Language="en">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_DESKTOP_SH" Value="1" Type="4"/> <ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_QUICKLAUNCH_SH" Value="1" Type="4"/>
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/> <ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
<ROW Property="AI_STARTMENU_SH" Value="1" Type="4"/>
<ROW Property="AI_STARTUP_SH" Value="1" Type="4"/>
<ROW Property="ALLUSERS" Value="2"/> <ROW Property="ALLUSERS" Value="2"/>
<ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/> <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/>
<ROW Property="ARPCONTACT" Value="support@hardcoded.net"/> <ROW Property="ARPCONTACT" Value="support@hardcoded.net"/>
<ROW Property="ARPHELPLINK" Value="http://www.hardcoded.net/support/"/> <ROW Property="ARPHELPLINK" Value="http://www.hardcoded.net/support/"/>
<ROW Property="ARPURLINFOABOUT" Value="http://www.hardcoded.net/dupeguru_me/"/> <ROW Property="ARPURLINFOABOUT" Value="http://www.hardcoded.net/dupeguru_me/"/>
<ROW Property="ARPURLUPDATEINFO" Value="http://www.hardcoded.net/dupeguru_me/"/> <ROW Property="ARPURLUPDATEINFO" Value="http://www.hardcoded.net/dupeguru_me/"/>
<ROW Property="BannerBitmap" Value="default_banner.bmp" Type="1"/> <ROW Property="BannerBitmap" MultiBuildValue="DefaultBuild:banner_image.jpg" Type="1"/>
<ROW Property="CTRLS" Value="2"/> <ROW Property="CTRLS" Value="2"/>
<ROW Property="DialogBitmap" Value="default_dialog.bmp" Type="1"/> <ROW Property="DialogBitmap" MultiBuildValue="DefaultBuild:dialog_image.jpg" Type="1"/>
<ROW Property="Manufacturer" Value="Hardcoded Software" ValueLocId="*"/> <ROW Property="Manufacturer" Value="Hardcoded Software" ValueLocId="*"/>
<ROW Property="ProductCode" Value="1033:{A7037226-389C-4704-81C3-E2CA17D11058} "/> <ROW Property="ProductCode" Value="1033:{A7037226-389C-4704-81C3-E2CA17D11058} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/> <ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="dupeGuru Music Edition" ValueLocId="*"/> <ROW Property="ProductName" Value="dupeGuru Music Edition" ValueLocId="*"/>
<ROW Property="ProductVersion" Value="5.6.0"/> <ROW Property="ProductVersion" Value="5.6.0"/>
<ROW Property="RUNAPPLICATION" Value="1" Type="4"/> <ROW Property="RUNAPPLICATION" Value="1" Type="4"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/> <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
<ROW Property="UpgradeCode" Value="{E11BFC48-7639-44BD-BB5B-A6AC934BC12D}"/> <ROW Property="UpgradeCode" Value="{E11BFC48-7639-44BD-BB5B-A6AC934BC12D}"/>
<ROW Property="WindowsFamily9X" Value="Windows 9x/ME"/> <ROW Property="WindowsFamily9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsTypeNT" Value="Windows 2000"/> <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/> <ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
@@ -33,121 +30,134 @@
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/> <ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/> <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="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="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="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"/> <ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AIShRegAnswer" ComponentId="{7DB5C163-2978-436F-A47D-54F1C76F1D64}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer" FullKeyPath="HK_UM\Software\Caphyon\Advanced Installer\Installs\[ProductCode]\AIShRegAnswer"/> <ROW Component="AIShRegAnswer" ComponentId="{7DB5C163-2978-436F-A47D-54F1C76F1D64}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
<ROW Component="MSVCP90.dll" ComponentId="{9CD64E9F-44D0-4EB9-9FB2-B2F1AB1551CE}" Directory_="APPDIR" Attributes="0" KeyPath="MSVCP90.dll" FullKeyPath="APPDIR\MSVCP90.dll"/> <ROW Component="AI_ExePath" ComponentId="{AB8EF793-B4A4-4A5C-A343-8095FFE16175}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="MSVCR90.dll" ComponentId="{2D77BB4F-0B6B-452A-A7D1-2DB8CDC3BC0B}" Directory_="APPDIR" Attributes="0" KeyPath="MSVCR90.dll" FullKeyPath="APPDIR\MSVCR90.dll"/> <ROW Component="PyWinTypes26.dll" ComponentId="{E7DC87D7-F396-46F0-8132-D4F582709AA2}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
<ROW Component="POWRPROF.dll" ComponentId="{12B8FFB0-6FEB-49A9-8A09-5B4B26379034}" Directory_="APPDIR" Attributes="0" KeyPath="POWRPROF.dll" FullKeyPath="APPDIR\POWRPROF.dll"/> <ROW Component="QtCore4.dll" ComponentId="{731F12A4-0DB0-4484-8BA1-399560578D68}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
<ROW Component="PyWinTypes26.dll" ComponentId="{E7DC87D7-F396-46F0-8132-D4F582709AA2}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll" FullKeyPath="APPDIR\PyWinTypes26.dll"/> <ROW Component="QtGui4.dll" ComponentId="{3D4FDAFA-EE5E-43C5-A4F5-125F7FA6A550}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
<ROW Component="QtCore4.dll" ComponentId="{731F12A4-0DB0-4484-8BA1-399560578D68}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll" FullKeyPath="APPDIR\QtCore4.dll"/> <ROW Component="bz2.pyd_1" ComponentId="{E34B2912-4B50-4EEA-B1EF-B56FA625FCC7}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
<ROW Component="QtGui4.dll" ComponentId="{3D4FDAFA-EE5E-43C5-A4F5-125F7FA6A550}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll" FullKeyPath="APPDIR\QtGui4.dll"/> <ROW Component="credits.htm" ComponentId="{4C0F14CD-BD35-44FE-B307-4834264AB347}" Directory_="help_DIR" Attributes="0" KeyPath="credits.htm" Type="0"/>
<ROW Component="SHLWAPI.dll" ComponentId="{FF064632-83EE-43F6-8AE2-7982EFF81216}" Directory_="APPDIR" Attributes="0" KeyPath="SHLWAPI.dll" FullKeyPath="APPDIR\SHLWAPI.dll"/> <ROW Component="dupeGuru_ME.exe" ComponentId="{14F7B73A-FA85-4C10-AA92-10BE05FE103B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_ME.exe"/>
<ROW Component="bz2.pyd_1" ComponentId="{E34B2912-4B50-4EEA-B1EF-B56FA625FCC7}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" FullKeyPath="APPDIR"/> <ROW Component="hs_title.png" ComponentId="{A292ADA8-FEC0-49B9-81A5-6C7F837290D4}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
<ROW Component="dupeGuru_ME.exe" ComponentId="{14F7B73A-FA85-4C10-AA92-10BE05FE103B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_ME.exe" FullKeyPath="APPDIR\dupeGuru ME.exe"/> <ROW Component="python26.dll" ComponentId="{20E0EA31-C5CF-4278-B7C6-5FCA0C691B7F}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
<ROW Component="iertutil.dll" ComponentId="{C4907490-FE25-4CD9-B31A-583DFF8A4359}" Directory_="APPDIR" Attributes="0" KeyPath="iertutil.dll" FullKeyPath="APPDIR\iertutil.dll"/> <ROW Component="pythoncom26.dll" ComponentId="{C0489561-2362-48C1-86E8-D5F1A08DE4DE}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
<ROW Component="mfc90.dll" ComponentId="{B206C255-03A4-4A40-92F2-5565830FEB14}" Directory_="APPDIR" Attributes="0" KeyPath="mfc90.dll" FullKeyPath="APPDIR\mfc90.dll"/> <ROW Component="qcncodecs4.dll" ComponentId="{03C97279-4453-48E0-A40D-D28E6F3E701F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
<ROW Component="msvcm90.dll" ComponentId="{B86025F0-23B8-45B6-B870-459DF292E17D}" Directory_="APPDIR" Attributes="0" KeyPath="msvcm90.dll" FullKeyPath="APPDIR\msvcm90.dll"/> <ROW Component="qgif4.dll" ComponentId="{5D6E676F-18BC-49C8-BBD2-E6BA1F3CA043}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
<ROW Component="python26.dll" ComponentId="{20E0EA31-C5CF-4278-B7C6-5FCA0C691B7F}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll" FullKeyPath="APPDIR\python26.dll"/> <ROW Component="qico4.dll" ComponentId="{C23E13E3-0E14-46E8-AA73-5D592CDBB725}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
<ROW Component="pythoncom26.dll" ComponentId="{C0489561-2362-48C1-86E8-D5F1A08DE4DE}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll" FullKeyPath="APPDIR\pythoncom26.dll"/> <ROW Component="qjpcodecs4.dll" ComponentId="{E6649370-16BB-449A-8668-9995B5C1CEB5}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll"/>
<ROW Component="qcncodecs4.dll" ComponentId="{03C97279-4453-48E0-A40D-D28E6F3E701F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll" FullKeyPath="APPDIR\qt4_plugins\codecs\qcncodecs4.dll"/> <ROW Component="qjpeg4.dll" ComponentId="{1D084E38-4A03-4C3C-87F7-3C68FEB41B4C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll"/>
<ROW Component="qgif4.dll" ComponentId="{5D6E676F-18BC-49C8-BBD2-E6BA1F3CA043}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qgif4.dll"/> <ROW Component="qkrcodecs4.dll" ComponentId="{18F32B38-7D3F-4F3C-AB80-3778634C8676}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll"/>
<ROW Component="qico4.dll" ComponentId="{C23E13E3-0E14-46E8-AA73-5D592CDBB725}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qico4.dll"/> <ROW Component="qmng4.dll" ComponentId="{D7E0BF84-EB34-4E4B-81CD-93B47B31503C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
<ROW Component="qjpcodecs4.dll" ComponentId="{E6649370-16BB-449A-8668-9995B5C1CEB5}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll" FullKeyPath="APPDIR\qt4_plugins\codecs\qjpcodecs4.dll"/> <ROW Component="qsvg4.dll" ComponentId="{3920BD4C-9A56-4CE4-A321-E649652D3D8A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
<ROW Component="qjpeg4.dll" ComponentId="{1D084E38-4A03-4C3C-87F7-3C68FEB41B4C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qjpeg4.dll"/> <ROW Component="qsvgicon4.dll" ComponentId="{F5D7A7C3-6320-4274-90DF-9F42C94FCDED}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
<ROW Component="qkrcodecs4.dll" ComponentId="{18F32B38-7D3F-4F3C-AB80-3778634C8676}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll" FullKeyPath="APPDIR\qt4_plugins\codecs\qkrcodecs4.dll"/> <ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{990608A3-AD85-439A-B46A-764DF560FA3A}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
<ROW Component="qmng4.dll" ComponentId="{D7E0BF84-EB34-4E4B-81CD-93B47B31503C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qmng4.dll"/> <ROW Component="qtaccessiblewidgets4.dll" ComponentId="{1F04BD2B-42BD-412D-B101-806B130CD1B8}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
<ROW Component="qsvg4.dll" ComponentId="{3920BD4C-9A56-4CE4-A321-E649652D3D8A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qsvg4.dll"/> <ROW Component="qtiff4.dll" ComponentId="{D5B4A7B8-7D9B-4A5C-9DD5-2048690EEE11}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
<ROW Component="qsvgicon4.dll" ComponentId="{F5D7A7C3-6320-4274-90DF-9F42C94FCDED}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll" FullKeyPath="APPDIR\qt4_plugins\iconengines\qsvgicon4.dll"/> <ROW Component="qtwcodecs4.dll" ComponentId="{E6C5E92F-D193-4A75-88E2-5058F069C224}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
<ROW Component="qt4_plugins" ComponentId="{5711E103-B078-4868-94BC-A50DC4CA2EE6}" Directory_="qt4_plugins_DIR" Attributes="0"/> <ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{990608A3-AD85-439A-B46A-764DF560FA3A}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll" FullKeyPath="APPDIR\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll"/>
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{1F04BD2B-42BD-412D-B101-806B130CD1B8}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll" FullKeyPath="APPDIR\qt4_plugins\accessible\qtaccessiblewidgets4.dll"/>
<ROW Component="qtiff4.dll" ComponentId="{D5B4A7B8-7D9B-4A5C-9DD5-2048690EEE11}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll" FullKeyPath="APPDIR\qt4_plugins\imageformats\qtiff4.dll"/>
<ROW Component="qtwcodecs4.dll" ComponentId="{E6C5E92F-D193-4A75-88E2-5058F069C224}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll" FullKeyPath="APPDIR\qt4_plugins\codecs\qtwcodecs4.dll"/>
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe" FullKeyPath="APPDIR\updater.exe"/>
<ROW Component="urlmon.dll" ComponentId="{BAD794CE-427A-4BB0-9C23-E4BBCDE988C3}" Directory_="APPDIR" Attributes="0" KeyPath="urlmon.dll" FullKeyPath="APPDIR\urlmon.dll"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent"> <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 iertutil.dll mfc90.dll MSVCP90.dll MSVCR90.dll POWRPROF.dll 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 qt4_plugins QtCore4.dll QtGui4.dll SHLWAPI.dll urlmon.dll msvcm90.dll"/> <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"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/> <ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="MSVCP90.dll" Component_="MSVCP90.dll" FileName="MSVCP90.dll" Attributes="0" SourcePath="dist\MSVCP90.dll" SelfReg="false" Sequence="6"/> <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="MSVCR90.dll" Component_="MSVCR90.dll" FileName="MSVCR90.dll" Attributes="0" SourcePath="dist\MSVCR90.dll" SelfReg="false" Sequence="7"/> <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="Microsoft.VC90.CRT.manifest" Component_="bz2.pyd_1" FileName="Micros~1.man|Microsoft.VC90.CRT.manifest" Attributes="0" SourcePath="dist\Microsoft.VC90.CRT.manifest" SelfReg="false" Sequence="45"/> <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="POWRPROF.dll" Component_="POWRPROF.dll" FileName="POWRPROF.dll" Attributes="0" SourcePath="dist\POWRPROF.dll" SelfReg="false" Sequence="8"/> <ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="23"/>
<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="10"/> <ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="24"/>
<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="11"/>
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="14"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="28"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="29"/>
<ROW File="SHLWAPI.dll" Component_="SHLWAPI.dll" FileName="SHLWAPI.dll" Attributes="0" SourcePath="dist\SHLWAPI.dll" SelfReg="false" Sequence="31"/>
<ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/> <ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
<ROW File="ctypes.pyd" Component_="bz2.pyd_1" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" SelfReg="false" Sequence="39"/> <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="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="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="40"/> <ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="38"/>
<ROW File="iertutil.dll" Component_="iertutil.dll" FileName="iertutil.dll" Attributes="0" SourcePath="dist\iertutil.dll" SelfReg="false" Sequence="4"/> <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="mfc90.dll" Component_="mfc90.dll" FileName="mfc90.dll" Attributes="0" SourcePath="dist\mfc90.dll" SelfReg="false" Sequence="5"/> <ROW File="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="32"/>
<ROW File="msvcm90.dll" Component_="msvcm90.dll" FileName="msvcm90.dll" Attributes="0" SourcePath="dist\msvcm90.dll" SelfReg="false" Sequence="46"/> <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="multiprocessing.pyd" Component_="bz2.pyd_1" FileName="_multi~1.pyd|_multiprocessing.pyd" Attributes="0" SourcePath="dist\_multiprocessing.pyd" SelfReg="false" Sequence="41"/> <ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="41"/>
<ROW File="pyexpat.pyd" Component_="bz2.pyd_1" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="9"/> <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="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="12"/> <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="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" SelfReg="false" Sequence="13"/> <ROW File="pyexpat.pyd" Component_="bz2.pyd_1" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="4"/>
<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="17"/> <ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="7"/>
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="22"/> <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="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="23"/> <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="qjpcodecs4.dll" Component_="qjpcodecs4.dll" FileName="qjpcod~1.dll|qjpcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qjpcodecs4.dll" SelfReg="false" Sequence="18"/> <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="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="24"/> <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="qkrcodecs4.dll" Component_="qkrcodecs4.dll" FileName="qkrcod~1.dll|qkrcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qkrcodecs4.dll" SelfReg="false" Sequence="19"/> <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="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="25"/> <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="qsvg4.dll" Component_="qsvg4.dll" FileName="qsvg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qsvg4.dll" SelfReg="false" Sequence="26"/> <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="qsvgicon4.dll" Component_="qsvgicon4.dll" FileName="qsvgic~1.dll|qsvgicon4.dll" Attributes="0" SourcePath="dist\qt4_plugins\iconengines\qsvgicon4.dll" SelfReg="false" Sequence="21"/> <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="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="15"/> <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="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="16"/> <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="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="27"/> <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="qtwcodecs4.dll" Component_="qtwcodecs4.dll" FileName="qtwcod~1.dll|qtwcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qtwcodecs4.dll" SelfReg="false" Sequence="20"/> <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="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="30"/> <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="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="32"/> <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="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="42"/> <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="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="43"/> <ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="45"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="33"/> <ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="25"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;updater.exe&gt;" SelfReg="false" Sequence="1" DigSign="true"/> <ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="26"/>
<ROW File="urlmon.dll" Component_="urlmon.dll" FileName="urlmon.dll" Attributes="0" SourcePath="dist\urlmon.dll" SelfReg="false" Sequence="34"/> <ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="33"/>
<ROW File="win32api.pyd" Component_="bz2.pyd_1" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="35"/> <ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="34"/>
<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="36"/> <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="win32sysloader.pyd" Component_="bz2.pyd_1" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="44"/> <ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;AI_HOME&gt;updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
<ROW File="win32trace.pyd" Component_="bz2.pyd_1" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="37"/> <ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="46"/>
<ROW File="win32ui.pyd" Component_="bz2.pyd_1" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="38"/> <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"/>
</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"/>
<ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent"> <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;ui.ail&gt;"/> <ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;ui_en.ail&gt;"/> <ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent"> <COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="FolderDlg.aip" Path="&lt;FolderDlg.aip&gt;"/> <ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
<ROW Fragment="ShortcutsDlg.aip" Path="&lt;ShortcutsDlg.aip&gt;"/> <ROW Fragment="FolderDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\FolderDlg.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;StaticUIStrings.aip&gt;"/> <ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
<ROW Fragment="UI.aip" Path="&lt;UI.aip&gt;"/> <ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
<ROW Fragment="ShortcutsDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\ShortcutsDlg.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
<ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
<ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
<ROW Action="AI_DeleteLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
<ROW Action="AI_DeleteRLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
<ROW Action="AI_ExtractLzma" Description="Extracting files from archive" DescriptionLocId="ActionText.Description.AI_ExtractLzma" TemplateLocId="-"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiAppSearchComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiAppSearchComponent">
<ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_CU" Builds="DefaultBuild"/>
<ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_LM" Builds="DefaultBuild"/>
<ROW Property="AI_SHORTCUTSREG" Signature_="AI_ShRegOptionMachine"/> <ROW Property="AI_SHORTCUTSREG" Signature_="AI_ShRegOptionMachine"/>
<ROW Property="AI_SHORTCUTSREG" Signature_="AI_ShRegOptionUser"/> <ROW Property="AI_SHORTCUTSREG" Signature_="AI_ShRegOptionUser"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="aicustact.dll" SourcePath="&lt;aicustact.dll&gt;"/> <ROW Name="Prereq.dll" SourcePath="&lt;AI_CUSTACTS&gt;Prereq.dll"/>
<ROW Name="default_banner.bmp" SourcePath="&lt;default-banner.bmp&gt;"/> <ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
<ROW Name="default_dialog.bmp" SourcePath="&lt;default-dialog.bmp&gt;"/> <ROW Name="banner_image.jpg" SourcePath="&lt;AI_THEMES&gt;classic\resources\banner-image.jpg"/>
<ROW Name="dialog_image.jpg" SourcePath="&lt;AI_THEMES&gt;classic\resources\dialog-image.jpg"/>
<ROW Name="lzmaextractor.dll" SourcePath="&lt;AI_CUSTACTS&gt;lzmaextractor.dll"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
<ATTRIBUTE name="FixedSizeBitmaps" value="0"/> <ATTRIBUTE name="FixedSizeBitmaps" value="0"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlConditionComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiControlConditionComponent">
<ROW Dialog_="ShortcutsDlg" Control_="QuickLaunchShorcutsCheckBox" Action="Hide" Condition="(Not Installed)"/> <ROW Dialog_="ShortcutsDlg" Control_="QuickLaunchShorcutsCheckBox" Action="Hide" Condition="(Not Installed) AND (VersionNT&lt;&quot;601&quot;)"/>
<ROW Dialog_="ShortcutsDlg" Control_="StartupShorcutsCheckBox" Action="Hide" Condition="(Not Installed)"/> <ROW Dialog_="ShortcutsDlg" Control_="StartupShorcutsCheckBox" Action="Hide" Condition="(Not Installed)"/>
<ATTRIBUTE name="DeletedRows" value="ShortcutsDlg#QuickLaunchShorcutsCheckBox#Show#(Not Installed)@ShortcutsDlg#StartupShorcutsCheckBox#Show#(Not Installed)"/> <ATTRIBUTE name="DeletedRows" value="ShortcutsDlg#QuickLaunchShorcutsCheckBox#Show#(Not Installed) AND (VersionNT&lt;&quot;601&quot;)@ShortcutsDlg#StartupShorcutsCheckBox#Show#(Not Installed)@ShortcutsDlg#QuickLaunchShorcutsCheckBox#Show#(Not Installed)"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
<ROW Dialog_="FolderDlg" Control_="Back" Event="NewDialog" Argument="ShortcutsDlg" Condition="AI_INSTALL" Ordering="1"/> <ROW Dialog_="FolderDlg" Control_="Back" Event="NewDialog" Argument="ShortcutsDlg" Condition="AI_INSTALL" Ordering="1"/>
@@ -161,15 +171,21 @@
<ROW Dialog_="ShortcutsDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="1"/> <ROW Dialog_="ShortcutsDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="ShortcutsDlg" Control_="Next" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL" Ordering="1"/> <ROW Dialog_="ShortcutsDlg" Control_="Next" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL" Ordering="1"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
<ROW Directory_="qt4_plugins_DIR" Component_="qt4_plugins"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
<ROW Action="AI_DELETE_SHORTCUTS" Type="1" Source="aicustact.dll" Target="DeleteShortcuts"/> <ROW Action="AI_DELETE_SHORTCUTS" Type="1" Source="aicustact.dll" Target="DeleteShortcuts"/>
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/> <ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DeleteCadLzma" Type="51" Source="AI_DeleteLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DeleteLzma" Type="1025" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
<ROW Action="AI_DeleteRCadLzma" Type="51" Source="AI_DeleteRLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DeleteRLzma" Type="1281" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
<ROW Action="AI_ExtractCadLzma" Type="51" Source="AI_ExtractLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_ExtractLzma" Type="1025" Source="lzmaextractor.dll" Target="ExtractLZMAFiles"/>
<ROW Action="AI_FindExeLzma" Type="1" Source="lzmaextractor.dll" Target="FindEXE"/>
<ROW Action="AI_LaunchApp" Type="1" Source="aicustact.dll" Target="[#dupeGuru_ME.exe]"/> <ROW Action="AI_LaunchApp" Type="1" Source="aicustact.dll" Target="[#dupeGuru_ME.exe]"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="1" Source="aicustact.dll" Target="PrepareUpgrade"/> <ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_RESTORE_LOCATION" Type="1" Source="aicustact.dll" Target="RestoreLocation"/> <ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/> <ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
<ROW Action="AI_UPDATER_UNINSTALL" Type="18" Source="updater.exe" Target="/clean silent"/> <ROW Action="AI_UPDATER_UNINSTALL" Type="18" Source="updater.exe" Target="/clean silent"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/> <ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/>
@@ -177,7 +193,7 @@
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/> <ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="SystemFolder_msiexec.exe" SourcePath="&lt;uninstall.ico&gt;" Index="0"/> <ROW Name="SystemFolder_msiexec.exe" SourcePath="&lt;AI_RES&gt;uninstall.ico" Index="0"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIniFileComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiIniFileComponent">
<ROW IniFile="AppDir" FileName="updater.ini" DirProperty="APPDIR" Section="General" Key="AppDir" Value="[APPDIR]" Action="0" Component_="updater.exe"/> <ROW IniFile="AppDir" FileName="updater.ini" DirProperty="APPDIR" Section="General" Key="AppDir" Value="[APPDIR]" Action="0" Component_="updater.exe"/>
@@ -193,31 +209,36 @@
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/> <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/>
<ROW Action="AI_STORE_LOCATION" Condition="Not Installed" Sequence="1545"/> <ROW Action="AI_STORE_LOCATION" Condition="Not Installed" Sequence="1545"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1300"/> <ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1300"/>
<ROW Action="AI_UPDATER_UNINSTALL" Condition="($updater.exe = 2) AND (?updater.exe = 3) AND NOT (UPGRADINGPRODUCTCODE)" Sequence="1549"/> <ROW Action="AI_UPDATER_UNINSTALL" Condition="($updater.exe = 2) AND (?updater.exe = 3) AND NOT (UPGRADINGPRODUCTCODE)" Sequence="1547"/>
<ROW Action="AI_DELETE_SHORTCUTS" Condition="NOT (REMOVE=&quot;ALL&quot;)" Sequence="1449"/> <ROW Action="AI_DELETE_SHORTCUTS" Condition="NOT (REMOVE=&quot;ALL&quot;)" Sequence="1449"/>
<ROW Action="AI_AppSearchEx" Sequence="101"/>
<ROW Action="AI_DeleteCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="199" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteRCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="198" Builds="DefaultBuild"/>
<ROW Action="AI_ExtractCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="197" Builds="DefaultBuild"/>
<ROW Action="AI_FindExeLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="196" Builds="DefaultBuild"/>
<ROW Action="AI_ExtractLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="1549" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteRLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="1548" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (NOT PATCH)" Sequence="6599" Builds="DefaultBuild"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="51"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/> <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/>
<ROW Action="AI_AppSearchEx" Sequence="101"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="51"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="Version9X OR VersionNT64 OR (VersionNT &gt;= 500 )" Description="[ProductName] can not be installed on systems earlier than [WindowsTypeNT]"/> <ROW Condition="Version9X OR VersionNT64 OR (VersionNT &gt;= 500 )" Description="[ProductName] cannot be installed on systems earlier than [WindowsTypeNT]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="VersionNT" Description="[ProductName] can not be installed on [WindowsFamily9X]"/> <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsFamily9X]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiMediaComponent">
<ATTRIBUTE name="CabsLocation" value="1"/>
<ATTRIBUTE name="Compress" value="1"/>
<ATTRIBUTE name="CreateMd5" value="true"/>
<ATTRIBUTE name="InstallationType" value="4"/>
<ATTRIBUTE name="Package" value="6"/>
<ATTRIBUTE name="PackageName" value="install\dupeguru_me_win_[|ProductVersion]"/>
<ATTRIBUTE name="UseLargeSchema" value="true"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent">
<ROW Signature_="AI_EXE_PATH_CU" Root="1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
<ROW Signature_="AI_EXE_PATH_LM" Root="2" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
<ROW Signature_="AI_ShRegOptionMachine" Root="2" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Type="2"/> <ROW Signature_="AI_ShRegOptionMachine" Root="2" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Type="2"/>
<ROW Signature_="AI_ShRegOptionUser" Root="1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Type="2"/> <ROW Signature_="AI_ShRegOptionUser" Root="1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Type="2"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent"> <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="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"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent"> <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="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"/>
@@ -225,19 +246,22 @@
<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" 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"/> <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> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
<ATTRIBUTE name="UsedTheme" value="classic"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
<ROW UpgradeCode="[|UpgradeCode]" VersionMax="[|ProductVersion]" Attributes="1025" ActionProperty="OLDPRODUCTS"/> <ROW UpgradeCode="[|UpgradeCode]" VersionMax="[|ProductVersion]" Attributes="1025" ActionProperty="OLDPRODUCTS"/>
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/> <ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqComponent"> <COMPONENT cid="caphyon.advinst.msicomp.PreReqComponent">
<ROW PrereqKey="0" DisplayName="Visual C++ 2008 SP1 Redistributable" SetupFileUrl="http://download.hardcoded.net/vcredist_90sp1_x86.exe" Location="1" ExactSize="4216840" MinWin9xVer="37" MinWinNTVer="17" Operator="1" ComLine="/q" Sequence="1" MD5="5689d43c3b201dd3810fa3bba4a6476a"/> <ROW PrereqKey="0" DisplayName="Visual C++ 2008 SP1 Redistributable" SetupFileUrl="http://download.hardcoded.net/vcredist_90sp1_x86.exe" Location="1" ExactSize="4216840" MinWin9xVer="37" MinWinNTVer="17" Operator="1" ComLine="/q" MD5="5689d43c3b201dd3810fa3bba4a6476a"/>
<ATTRIBUTE name="ExtractionFolder" value="[AppDataFolder][|Manufacturer]\[|ProductName]\install"/> <ATTRIBUTE name="PrereqsOrder" value="0"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent"> <COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent">
<ROW Prereq="0" SearchType="9" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\9.0\RED\1033\SP" RefContent="M1" Order="1"/> <ROW SearchKey="SP" Prereq="0" SearchType="9" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\9.0\RED\1033\SP" RefContent="M1" Order="1" Property="PreReqSearch"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.SynchronizedFolderComponent"> <COMPONENT cid="caphyon.advinst.msicomp.SynchronizedFolderComponent">
<ROW Directory_="APPDIR" SourcePath="dist" ExcludePattern="*~|#*#|%*%|._|CVS|.cvsignore|SCCS|vssver.scc|mssccprj.scc|vssver2.scc|.svn|.DS_Store|*.pdb|*.vshost.*" ExcludeFlags="6"/> <ROW Directory_="APPDIR" SourcePath="dist" Feature="MainFeature" ExcludePattern="*~|#*#|%*%|._|CVS|.cvsignore|SCCS|vssver.scc|mssccprj.scc|vssver2.scc|.svn|.DS_Store|*.pdb|*.vshost.*" ExcludeFlags="6"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.UpdaterComponent"> <COMPONENT cid="caphyon.advinst.msicomp.UpdaterComponent">
<ROW Updater="updater.exe" URL="URL" SearchFreq="CheckFrequency" DownloadsFolder="DownloadsFolder" ID="ID" TargetDir="AppDir" AppName="ApplicationName" CompanyName="CompanyName" UnistallCASeq="AI_UPDATER_UNINSTALL"/> <ROW Updater="updater.exe" URL="URL" SearchFreq="CheckFrequency" DownloadsFolder="DownloadsFolder" ID="ID" TargetDir="AppDir" AppName="ApplicationName" CompanyName="CompanyName" UnistallCASeq="AI_UPDATER_UNINSTALL"/>

View File

@@ -1,28 +0,0 @@
VSVersionInfo(
ffi=FixedFileInfo(
filevers=($versioncomma),
prodvers=($versioncomma),
mask=0x17,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904b0',
[StringStruct('CompanyName', 'Hardcoded Software'),
StringStruct('FileDescription', 'dupeGuru Music Edition'),
StringStruct('FileVersion', '$version'),
StringStruct('InternalName', 'dupeGuru ME.exe'),
StringStruct('LegalCopyright', '(c) Hardcoded Software. All rights reserved.'),
StringStruct('OriginalFilename', 'dupeGuru ME.exe'),
StringStruct('ProductName', 'dupeGuru Music Edition'),
StringStruct('ProductVersion', '$versioncomma')])
]),
VarFileInfo([VarStruct('Translation', [1033])])
]
)

View File

@@ -54,9 +54,10 @@ class File(fs.File):
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
EDITION = 'pe'
LOGO_NAME = 'logo_pe' LOGO_NAME = 'logo_pe'
NAME = 'dupeGuru Picture Edition' NAME = 'dupeGuru Picture Edition'
VERSION = '1.8.3' VERSION = '1.8.6'
DELTA_COLUMNS = frozenset([2, 5, 6]) DELTA_COLUMNS = frozenset([2, 5, 6])
def __init__(self): def __init__(self):

View File

@@ -85,7 +85,7 @@
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>188</height> <height>190</height>
</size> </size>
</property> </property>
<property name="alternatingRowColors"> <property name="alternatingRowColors">

View File

@@ -1,19 +0,0 @@
# -*- mode: python -*-
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'start.py'],
pathex=[])
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
exclude_binaries=1,
name=os.path.join('build\\pyi.win32\\dupeGuru PE', 'dupeGuru PE.exe'),
debug=False,
strip=False,
upx=True,
console=False , icon='..\\..\\images\\dgpe_logo.ico', version='verinfo_tmp')
coll = COLLECT( exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name=os.path.join('dist'))

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?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.5.2" modules="professional" RootPath="." Language="en">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent"> <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_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/> <ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
@@ -28,110 +28,65 @@
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/> <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="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/> <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="gen_py_DIR" Directory_Parent="support_DIR" DefaultDir="gen_py"/>
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/> <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="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
<ROW Directory="support_DIR" Directory_Parent="APPDIR" DefaultDir="support"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AIShRegAnswer" ComponentId="{F315B3C7-7C86-41EB-BE7D-2A6A8E3073B4}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/> <ROW Component="AIShRegAnswer" ComponentId="{F315B3C7-7C86-41EB-BE7D-2A6A8E3073B4}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
<ROW Component="AI_ExePath" ComponentId="{8D009995-D5B9-4E68-A969-45A06F69ACB8}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/> <ROW Component="AI_ExePath" ComponentId="{8D009995-D5B9-4E68-A969-45A06F69ACB8}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="POWRPROF.dll" ComponentId="{65828A9D-101E-433C-82E5-11290FDB7054}" Directory_="APPDIR" Attributes="0" KeyPath="POWRPROF.dll"/> <ROW Component="CurrentVersion" ComponentId="{1A0BFEFD-F9D9-4861-93AC-D9717B7A635E}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
<ROW Component="PyWinTypes26.dll" ComponentId="{51E80B3A-C753-48CB-B7A4-65610CC49E1F}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
<ROW Component="QtCore4.dll" ComponentId="{5BB6B87D-BE40-4240-B529-23A303942E18}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/> <ROW Component="QtCore4.dll" ComponentId="{5BB6B87D-BE40-4240-B529-23A303942E18}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
<ROW Component="QtGui4.dll" ComponentId="{EF519048-F252-4FA0-9875-A6B45C7F3020}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/> <ROW Component="QtGui4.dll" ComponentId="{EF519048-F252-4FA0-9875-A6B45C7F3020}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
<ROW Component="SHLWAPI.dll" ComponentId="{11CA10DE-F6AF-4EC7-B5B9-EE1E9D08A7B0}" Directory_="APPDIR" Attributes="0" KeyPath="SHLWAPI.dll"/>
<ROW Component="SHORTCUTDIR" ComponentId="{29E7E841-7820-418B-8542-7F8CCC9777A8}" Directory_="SHORTCUTDIR" Attributes="0"/> <ROW Component="SHORTCUTDIR" ComponentId="{29E7E841-7820-418B-8542-7F8CCC9777A8}" Directory_="SHORTCUTDIR" Attributes="0"/>
<ROW Component="bz2.pyd" ComponentId="{F7FDAE87-233A-45B0-8976-021B8264E176}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/> <ROW Component="bz2.pyd" ComponentId="{F7FDAE87-233A-45B0-8976-021B8264E176}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
<ROW Component="credits.htm" ComponentId="{CF738E4F-8E05-4B2D-99FD-A035FC25D710}" Directory_="help_DIR" Attributes="0" KeyPath="credits.htm" Type="0"/> <ROW Component="credits.htm" ComponentId="{CF738E4F-8E05-4B2D-99FD-A035FC25D710}" Directory_="help_DIR" Attributes="0" KeyPath="credits.htm" Type="0"/>
<ROW Component="dupeGuru_PE.exe" ComponentId="{4A31F2AE-F42E-4B0F-BC4D-A09F312D469B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_PE.exe"/> <ROW Component="dupeGuru_PE.exe" ComponentId="{4A31F2AE-F42E-4B0F-BC4D-A09F312D469B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_PE.exe"/>
<ROW Component="hs_title.png" ComponentId="{ACCD16EE-68BE-4EDA-AE6B-013621EAB3B2}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/> <ROW Component="hs_title.png" ComponentId="{ACCD16EE-68BE-4EDA-AE6B-013621EAB3B2}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
<ROW Component="init_.py" ComponentId="{DBD0E45F-6773-431E-A716-5518A0B8C54E}" Directory_="gen_py_DIR" Attributes="0" KeyPath="init_.py" Type="0"/>
<ROW Component="python26.dll" ComponentId="{20529423-B717-4C53-AE3A-B82E53207A62}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/> <ROW Component="python26.dll" ComponentId="{20529423-B717-4C53-AE3A-B82E53207A62}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
<ROW Component="pythoncom26.dll" ComponentId="{46CE0516-582F-44F0-86D7-7F2F5F7458C3}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
<ROW Component="qcncodecs4.dll" ComponentId="{629EB310-99C7-4304-91DB-9134E521A83F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
<ROW Component="qgif4.dll" ComponentId="{788DB84F-6216-4334-B92E-9992FD02A31A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
<ROW Component="qico4.dll" ComponentId="{CED777C8-E8F6-421F-B533-91A7B5310BCF}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
<ROW Component="qjpcodecs4.dll" ComponentId="{9A112855-BA4A-4C41-BCA0-20D564A2A7C2}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll"/>
<ROW Component="qjpeg4.dll" ComponentId="{0FC6A53E-6DDC-4833-944B-00944A45FB62}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll"/>
<ROW Component="qkrcodecs4.dll" ComponentId="{5EE53027-96D1-4ABA-A2F6-507A7D85EA44}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll"/>
<ROW Component="qmng4.dll" ComponentId="{5E3A9C7B-F545-4EF5-B083-2A29E54784BE}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
<ROW Component="qsvg4.dll" ComponentId="{590998F6-2A55-48DC-A83A-AABC75EF7F99}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
<ROW Component="qsvgicon4.dll" ComponentId="{0440300E-1BAE-49C5-8575-AF43C2557271}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{217EE5AA-868E-4DDA-B374-E1007D54C1CF}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{74F17E1E-D2BC-4C85-A5B9-A093D4AFC840}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
<ROW Component="qtiff4.dll" ComponentId="{545FB567-9E3A-4E44-85A0-74446ABB8FC8}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
<ROW Component="qtwcodecs4.dll" ComponentId="{59FB6978-93A0-4DD6-A617-FE6460CDE4DB}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
<ROW Component="sqlite3.dll" ComponentId="{B5D4B746-A65D-4F4A-B31A-D1C3C7F59952}" Directory_="APPDIR" Attributes="0" KeyPath="sqlite3.dll"/> <ROW Component="sqlite3.dll" ComponentId="{B5D4B746-A65D-4F4A-B31A-D1C3C7F59952}" Directory_="APPDIR" Attributes="0" KeyPath="sqlite3.dll"/>
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/> <ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent"> <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_PE.exe AIShRegAnswer SHORTCUTDIR bz2.pyd POWRPROF.dll python26.dll pythoncom26.dll PyWinTypes26.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 SHLWAPI.dll sqlite3.dll AI_ExePath credits.htm hs_title.png init_.py qtaccessiblecompatwidgets4.dll"/> <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_PE.exe AIShRegAnswer SHORTCUTDIR bz2.pyd python26.dll QtCore4.dll QtGui4.dll sqlite3.dll AI_ExePath credits.htm hs_title.png CurrentVersion"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/> <ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="PIL._imaging.pyd" Component_="bz2.pyd" FileName="PIL_im~1.pyd|PIL._imaging.pyd" Attributes="0" SourcePath="dist\PIL._imaging.pyd" SelfReg="false" Sequence="4"/> <ROW File="PIL._imaging.pyd" Component_="bz2.pyd" FileName="PIL_im~1.pyd|PIL._imaging.pyd" Attributes="0" SourcePath="dist\PIL._imaging.pyd" SelfReg="false" Sequence="4"/>
<ROW File="POWRPROF.dll" Component_="POWRPROF.dll" FileName="POWRPROF.dll" Attributes="0" SourcePath="dist\POWRPROF.dll" SelfReg="false" Sequence="5"/> <ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="6"/>
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="7"/> <ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="7"/>
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="8"/> <ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="9"/>
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="11"/> <ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="10"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="24"/> <ROW File="block.pyd" Component_="bz2.pyd" FileName="_block.pyd" Attributes="0" SourcePath="dist\_block.pyd" SelfReg="false" Sequence="15"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="25"/>
<ROW File="SHLWAPI.dll" Component_="SHLWAPI.dll" FileName="SHLWAPI.dll" Attributes="0" SourcePath="dist\SHLWAPI.dll" SelfReg="false" Sequence="27"/>
<ROW File="block.pyd" Component_="bz2.pyd" FileName="_block.pyd" Attributes="0" SourcePath="dist\_block.pyd" SelfReg="false" Sequence="35"/>
<ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/> <ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
<ROW File="core_pe._block.pyd" Component_="bz2.pyd" FileName="core_p~1.pyd|core_pe._block.pyd" Attributes="0" SourcePath="dist\core_pe._block.pyd" SelfReg="false" Sequence="43"/> <ROW File="core_pe._block.pyd" Component_="bz2.pyd" FileName="core_p~1.pyd|core_pe._block.pyd" Attributes="0" SourcePath="dist\core_pe._block.pyd" SelfReg="false" Sequence="22"/>
<ROW File="core_pe._cache.pyd" Component_="bz2.pyd" FileName="core_p~2.pyd|core_pe._cache.pyd" Attributes="0" SourcePath="dist\core_pe._cache.pyd" SelfReg="false" Sequence="44"/> <ROW File="core_pe._cache.pyd" Component_="bz2.pyd" FileName="core_p~2.pyd|core_pe._cache.pyd" Attributes="0" SourcePath="dist\core_pe._cache.pyd" SelfReg="false" Sequence="23"/>
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="45"/> <ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="24"/>
<ROW File="ctypes.pyd" Component_="bz2.pyd" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" SelfReg="false" Sequence="36"/> <ROW File="ctypes.pyd" Component_="bz2.pyd" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" SelfReg="false" Sequence="16"/>
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="46"/> <ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="25"/>
<ROW File="dupeGuru_PE.exe" Component_="dupeGuru_PE.exe" FileName="dupeGu~2.exe|dupeGuru PE.exe" Attributes="0" SourcePath="dist\dupeGuru PE.exe" SelfReg="false" Sequence="2"/> <ROW File="dupeGuru_PE.exe" Component_="dupeGuru_PE.exe" FileName="dupeGu~2.exe|dupeGuru PE.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru PE.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="47"/> <ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="26"/>
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="48"/> <ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="27"/>
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="37"/> <ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="17"/>
<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="49"/> <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="28"/>
<ROW File="init_.py" Component_="init_.py" FileName="__init__.py" Attributes="0" SourcePath="dist\support\gen_py\__init__.py" SelfReg="false" Sequence="56"/> <ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="29"/>
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="50"/> <ROW File="lxml.etree.pyd" Component_="bz2.pyd" FileName="lxmlet~1.pyd|lxml.etree.pyd" Attributes="0" SourcePath="dist\lxml.etree.pyd" SelfReg="false" Sequence="35"/>
<ROW File="multiprocessing.pyd" Component_="bz2.pyd" FileName="_multi~1.pyd|_multiprocessing.pyd" Attributes="0" SourcePath="dist\_multiprocessing.pyd" SelfReg="false" Sequence="38"/> <ROW File="multiprocessing.pyd" Component_="bz2.pyd" FileName="_multi~1.pyd|_multiprocessing.pyd" Attributes="0" SourcePath="dist\_multiprocessing.pyd" SelfReg="false" Sequence="18"/>
<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="51"/> <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="30"/>
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="52"/> <ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="31"/>
<ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="6"/> <ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="5"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="9"/> <ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="8"/>
<ROW File="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" SelfReg="false" Sequence="10"/> <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="32"/>
<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="13"/> <ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="33"/>
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="18"/> <ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="11"/>
<ROW File="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="19"/> <ROW File="send2trash_win.pyd" Component_="bz2.pyd" FileName="_send2~1.pyd|_send2trash_win.pyd" Attributes="0" SourcePath="dist\_send2trash_win.pyd" SelfReg="false" Sequence="36"/>
<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="14"/> <ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="12"/>
<ROW File="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="20"/> <ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" 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="15"/> <ROW File="sqlite3.dll" Component_="sqlite3.dll" FileName="sqlite3.dll" Attributes="0" SourcePath="dist\sqlite3.dll" SelfReg="false" Sequence="13"/>
<ROW File="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="21"/> <ROW File="sqlite3.pyd" Component_="bz2.pyd" FileName="_sqlite3.pyd" Attributes="0" SourcePath="dist\_sqlite3.pyd" 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="22"/> <ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" 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="17"/> <ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="14"/>
<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="57"/>
<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="12"/>
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="23"/>
<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="16"/>
<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="53"/>
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="54"/>
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="26"/>
<ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="28"/>
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="39"/>
<ROW File="sqlite3.dll" Component_="sqlite3.dll" FileName="sqlite3.dll" Attributes="0" SourcePath="dist\sqlite3.dll" SelfReg="false" Sequence="29"/>
<ROW File="sqlite3.pyd" Component_="bz2.pyd" FileName="_sqlite3.pyd" Attributes="0" SourcePath="dist\_sqlite3.pyd" SelfReg="false" Sequence="40"/>
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="41"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="30"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;AI_HOME&gt;updater.exe" SelfReg="false" Sequence="1" DigSign="true"/> <ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;AI_HOME&gt;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="55"/> <ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="34"/>
<ROW File="win32api.pyd" Component_="bz2.pyd" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="31"/>
<ROW File="win32com.shell.shell.pyd" Component_="bz2.pyd" FileName="win32c~1.pyd|win32com.shell.shell.pyd" Attributes="0" SourcePath="dist\win32com.shell.shell.pyd" SelfReg="false" Sequence="32"/>
<ROW File="win32sysloader.pyd" Component_="bz2.pyd" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="42"/>
<ROW File="win32trace.pyd" Component_="bz2.pyd" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="33"/>
<ROW File="win32ui.pyd" Component_="bz2.pyd" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="34"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent"> <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_pe_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" PackageName="install\dupeguru_pe_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
@@ -261,6 +216,7 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent"> <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="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="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>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent"> <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="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"/>

View File

@@ -14,7 +14,9 @@ import base.dg_rc
from app import DupeGuru from app import DupeGuru
# This is a workaround for a pyinstaller problem where compiled dupeguru can't read tiff files if sys.platform == 'win32':
import base.cxfreeze_fix
# This is a workaround for a cxfreeze problem where compiled dupeguru can't read tiff files
from PIL import TiffImagePlugin, TiffTags from PIL import TiffImagePlugin, TiffTags
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -1,28 +0,0 @@
VSVersionInfo(
ffi=FixedFileInfo(
filevers=($versioncomma),
prodvers=($versioncomma),
mask=0x17,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904b0',
[StringStruct('CompanyName', 'Hardcoded Software'),
StringStruct('FileDescription', 'dupeGuru Picture Edition'),
StringStruct('FileVersion', '$version'),
StringStruct('InternalName', 'dupeGuru PE.exe'),
StringStruct('LegalCopyright', '(c) Hardcoded Software. All rights reserved.'),
StringStruct('OriginalFilename', 'dupeGuru PE.exe'),
StringStruct('ProductName', 'dupeGuru Picture Edition'),
StringStruct('ProductVersion', '$versioncomma')])
]),
VarFileInfo([VarStruct('Translation', [1033])])
]
)

View File

@@ -24,6 +24,7 @@ class Directories(DirectoriesBase):
return STATE_EXCLUDED return STATE_EXCLUDED
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
EDITION = 'se'
LOGO_NAME = 'logo_se' LOGO_NAME = 'logo_se'
NAME = 'dupeGuru' NAME = 'dupeGuru'
VERSION = '2.9.2' VERSION = '2.9.2'

View File

@@ -1,21 +0,0 @@
# -*- mode: python -*-
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'start.py'],
pathex=[])
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
exclude_binaries=1,
name=os.path.join('build\\pyi.win32\\dupeGuru', 'dupeGuru.exe'),
debug=False,
strip=False,
upx=True,
console=False,
icon='..\\..\\images\\dgse_logo.ico',
version='verinfo_tmp')
coll = COLLECT( exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name=os.path.join('dist'))

View File

@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>294</width> <width>449</width>
<height>296</height> <height>312</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -170,110 +170,105 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>134</height> <height>136</height>
</size> </size>
</property> </property>
<widget class="QCheckBox" name="wordWeightingBox"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="geometry"> <property name="spacing">
<rect> <number>0</number>
<x>0</x>
<y>0</y>
<width>350</width>
<height>21</height>
</rect>
</property> </property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="wordWeightingBox">
<property name="text"> <property name="text">
<string>Word weighting</string> <string>Word weighting</string>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QCheckBox" name="matchSimilarBox"> <widget class="QCheckBox" name="matchSimilarBox">
<property name="geometry">
<rect>
<x>0</x>
<y>22</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="text"> <property name="text">
<string>Match similar words</string> <string>Match similar words</string>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QCheckBox" name="mixFileKindBox"> <widget class="QCheckBox" name="mixFileKindBox">
<property name="geometry">
<rect>
<x>0</x>
<y>44</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="text"> <property name="text">
<string>Can mix file kind</string> <string>Can mix file kind</string>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QCheckBox" name="useRegexpBox"> <widget class="QCheckBox" name="useRegexpBox">
<property name="geometry">
<rect>
<x>0</x>
<y>66</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="text"> <property name="text">
<string>Use regular expressions when filtering</string> <string>Use regular expressions when filtering</string>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QCheckBox" name="removeEmptyFoldersBox"> <widget class="QCheckBox" name="removeEmptyFoldersBox">
<property name="geometry">
<rect>
<x>0</x>
<y>88</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="text"> <property name="text">
<string>Remove empty folders on delete or move</string> <string>Remove empty folders on delete or move</string>
</property> </property>
</widget> </widget>
<widget class="QCheckBox" name="ignoreSmallFilesBox"> </item>
<property name="geometry"> <item>
<rect> <layout class="QHBoxLayout" name="horizontalLayout_2">
<x>0</x> <property name="spacing">
<y>110</y> <number>0</number>
<width>171</width>
<height>21</height>
</rect>
</property> </property>
<item>
<widget class="QCheckBox" name="ignoreSmallFilesBox">
<property name="text"> <property name="text">
<string>Ignore files smaller than</string> <string>Ignore files smaller than</string>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QLineEdit" name="sizeThresholdEdit"> <widget class="QLineEdit" name="sizeThresholdEdit">
<property name="geometry"> <property name="sizePolicy">
<rect> <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<x>170</x> <horstretch>0</horstretch>
<y>110</y> <verstretch>0</verstretch>
<width>51</width> </sizepolicy>
<height>22</height> </property>
</rect> <property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property> </property>
</widget> </widget>
</item>
<item>
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>230</x>
<y>110</y>
<width>21</width>
<height>17</height>
</rect>
</property>
<property name="text"> <property name="text">
<string>KB</string> <string>KB</string>
</property> </property>
</widget> </widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>

View File

@@ -1,28 +0,0 @@
VSVersionInfo(
ffi=FixedFileInfo(
filevers=($versioncomma),
prodvers=($versioncomma),
mask=0x17,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904b0',
[StringStruct('CompanyName', 'Hardcoded Software'),
StringStruct('FileDescription', 'dupeGuru'),
StringStruct('FileVersion', '$version'),
StringStruct('InternalName', 'dupeGuru.exe'),
StringStruct('LegalCopyright', '(c) Hardcoded Software. All rights reserved.'),
StringStruct('OriginalFilename', 'dupeGuru.exe'),
StringStruct('ProductName', 'dupeGuru'),
StringStruct('ProductVersion', '$versioncomma')])
]),
VarFileInfo([VarStruct('Translation', [1033])])
]
)