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

Compare commits

...

48 Commits

Author SHA1 Message Date
Virgil Dupras
378589a473 Brought dgpe qt up to speed for the 1.9.0 release. 2010-04-15 10:05:33 +01:00
Virgil Dupras
fa264972a4 pe v1.9.0 2010-04-15 10:41:36 +02:00
Virgil Dupras
6b10e01c03 Updated dgpe help to include custom command description. 2010-04-15 10:40:34 +02:00
Virgil Dupras
5a6d74ab37 Brought dgpe cocoa up to speed for the 1.9 release. 2010-04-15 10:38:53 +02:00
Virgil Dupras
73f1bb6968 Tweaked dgpe's matching to work better with huge scans. 2010-04-15 10:38:30 +02:00
Virgil Dupras
d1a7f51859 Added tag me5.8.0 for changeset 388a7e5aef63 2010-04-14 14:08:24 +02:00
Virgil Dupras
2ae16396a6 Updated dgme installer project to cope with cxFreeze inability to add version information to the exe. 2010-04-14 09:22:16 +01:00
Virgil Dupras
ef090a5dc5 Updated the dgme Qt pref dialog to include the custom command field and added cxFreeze workaround in dgme qt start script. 2010-04-14 09:10:57 +01:00
Virgil Dupras
5c0799e82b me v5.8.0 2010-04-14 09:37:36 +02:00
Virgil Dupras
fa2ee01d3f Updated the project file to include newly added units for 5.8, updated the preferences XIB to add the Custom Command field and updated the help file to include custom commands. 2010-04-14 09:33:42 +02:00
Virgil Dupras
d6ba80bd3f Added tag se2.10.0 for changeset 914902428395 2010-04-13 17:31:36 +02:00
Virgil Dupras
ee96d5f88c Fixed Windows packaging for dgse. 2010-04-13 14:04:15 +01:00
Virgil Dupras
e96a917bef Fixed the problem dialog under cocoa, which was visible at launch. 2010-04-13 14:22:24 +02:00
Virgil Dupras
769b816998 se v2.10.0 2010-04-13 11:58:53 +02:00
Virgil Dupras
ff891c210c [#4 state:fixed] Filters are now applied on the whole file path. 2010-04-13 11:40:20 +02:00
Virgil Dupras
3ed5e1bf95 [#12 state:fixed] Added custom command help. 2010-04-13 11:05:42 +02:00
Virgil Dupras
5bc8581389 [#12] Tweaked the custom command feature under Cocoa. 2010-04-13 10:52:44 +02:00
Virgil Dupras
7346b422d5 [#12] Added the Custom Command preference on the Qt side. 2010-04-13 09:02:09 +01:00
Virgil Dupras
5c80ac1c74 [#12] dgse cocoa: Added custom command invocation. 2010-04-12 17:43:24 +02:00
Virgil Dupras
699023992c Added the problem dialog to the Qt side. 2010-04-12 15:29:56 +02:00
Virgil Dupras
454ce604ad Merged hsgui heads. 2010-04-12 12:22:18 +02:00
Virgil Dupras
1e0f6bfecb Added a dialog giving more information about the causes of problems during operations. 2010-04-12 12:21:01 +02:00
Virgil Dupras
7f10aa3de2 Merged heads. 2010-04-08 07:07:45 -07:00
Virgil Dupras
f8764ab85e dgme qt: Fixed visual glitch in preference panel under Linux. 2010-04-08 07:06:32 -07:00
Virgil Dupras
aa8544308e Added tag pe1.8.6 for changeset 556baf4a4107 2010-04-08 15:01:27 +02:00
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
88 changed files with 5516 additions and 2974 deletions

View File

@@ -13,3 +13,7 @@ cbcf9c80fee4c908ef2efbf1c143c9e47676c9b2 pe1.8.0
1cef6d39855f85d4be728646bc78b860e6d4e398 pe1.8.3
90ed56ee602666db2f267f73eac6f824347039b5 me5.7.2
4c3cb1e671a333eabde1151c7c6ffb3609cab025 pe1.8.4
0a71306434bca51bea9a5d5ae54fe1bf0e4900d8 pe1.8.5
556baf4a410779e9bbf43129de133e4c4b26d679 pe1.8.6
9149024283959a50fe9a47a5f175b905d1672c19 se2.10.0
388a7e5aef6385e515189f4a15b4c4fed3ae2fcf me5.8.0

3
README
View File

@@ -27,6 +27,7 @@ General dependencies
-----
- 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/)
- PyYaml, for help files and the build system. (http://pyyaml.org/)
@@ -46,7 +47,7 @@ Windows prerequisites
- 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)
- 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/)
Building dupeGuru

View File

@@ -0,0 +1,25 @@
/*
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
*/
#import <Cocoa/Cocoa.h>
#import "HSWindowController.h"
#import "PyApp.h"
#import "PyProblemDialog.h"
#import "HSTable.h"
@interface ProblemDialog : HSWindowController
{
IBOutlet NSTableView *problemTableView;
HSTable *problemTable;
}
- (id)initWithPy:(PyApp *)aPy;
- (PyProblemDialog *)py;
- (IBAction)revealSelected:(id)sender;
@end

View File

@@ -0,0 +1,40 @@
/*
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
*/
#import "ProblemDialog.h"
#import "Utils.h"
@implementation ProblemDialog
- (id)initWithPy:(PyApp *)aPy
{
self = [super initWithNibName:@"ProblemDialog" pyClassName:@"PyProblemDialog" pyParent:aPy];
[self window]; //So the detailsTable is initialized.
problemTable = [[HSTable alloc] initWithPyClassName:@"PyProblemTable" pyParent:[self py] view:problemTableView];
[self connect];
[problemTable connect];
return self;
}
- (void)dealloc
{
[problemTable disconnect];
[self disconnect];
[problemTable release];
[super dealloc];
}
- (PyProblemDialog *)py
{
return (PyProblemDialog *)py;
}
- (IBAction)revealSelected:(id)sender
{
[[self py] revealSelected];
}
@end

View File

@@ -20,6 +20,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)clearIgnoreList;
- (void)purgeIgnoreList;
- (NSString *)exportToXHTMLwithColumns:(NSArray *)aColIds;
- (void)invokeCommand:(NSString *)cmd;
- (NSNumber *)doScan;
@@ -41,7 +42,7 @@ http://www.hardcoded.net/licenses/hs_license
//Data
- (NSNumber *)getIgnoreListCount;
- (NSNumber *)getMarkCount;
- (NSNumber *)getOperationalErrorCount;
- (BOOL)scanWasProblematic;
//Scanning options
- (void)setMinMatchPercentage:(NSNumber *)percentage;

View File

@@ -0,0 +1,14 @@
/*
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
*/
#import <Cocoa/Cocoa.h>
#import "PyGUI.h"
@interface PyProblemDialog : PyGUI
- (void)revealSelected;
@end

View File

@@ -10,6 +10,7 @@ http://www.hardcoded.net/licenses/hs_license
#import "HSOutlineView.h"
#import "StatsLabel.h"
#import "ResultOutline.h"
#import "ProblemDialog.h"
#import "PyDupeGuru.h"
@interface ResultWindowBase : NSWindowController
@@ -28,6 +29,7 @@ http://www.hardcoded.net/licenses/hs_license
NSWindowController *preferencesPanel;
ResultOutline *outline;
StatsLabel *statsLabel;
ProblemDialog *problemDialog;
}
/* Helpers */
- (void)fillColumnsMenu;
@@ -46,6 +48,7 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)exportToXHTML:(id)sender;
- (IBAction)filter:(id)sender;
- (IBAction)ignoreSelected:(id)sender;
- (IBAction)invokeCustomCommand:(id)sender;
- (IBAction)markAll:(id)sender;
- (IBAction)markInvert:(id)sender;
- (IBAction)markNone:(id)sender;

View File

@@ -21,6 +21,7 @@ http://www.hardcoded.net/licenses/hs_license
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
outline = [[ResultOutline alloc] initWithPyParent:py view:matches];
statsLabel = [[StatsLabel alloc] initWithPyParent:py labelView:stats];
problemDialog = [[ProblemDialog alloc] initWithPy:py];
[self initResultColumns];
[self fillColumnsMenu];
[deltaSwitch setSelectedSegment:0];
@@ -38,6 +39,8 @@ http://www.hardcoded.net/licenses/hs_license
{
[outline release];
[preferencesPanel release];
[statsLabel release];
[problemDialog release];
[super dealloc];
}
@@ -197,6 +200,18 @@ http://www.hardcoded.net/licenses/hs_license
[py addSelectedToIgnoreList];
}
- (IBAction)invokeCustomCommand:(id)sender
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSString *cmd = [ud stringForKey:@"CustomCommand"];
if ((cmd != nil) && ([cmd length] > 0)) {
[py invokeCommand:cmd];
}
else {
[Dialogs showMessage:@"You have no custom command set up. Set it up in your preferences."];
}
}
- (IBAction)markAll:(id)sender
{
[py markAll];
@@ -349,28 +364,30 @@ http://www.hardcoded.net/licenses/hs_license
- (void)jobCompleted:(NSNotification *)aNotification
{
NSInteger r = n2i([py getOperationalErrorCount]);
id lastAction = [[ProgressController mainProgressController] jobId];
if ([lastAction isEqualTo:jobCopy]) {
if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be copied.",r]];
else
if ([py scanWasProblematic]) {
[problemDialog showWindow:self];
}
else {
[Dialogs showMessage:@"All marked files were copied sucessfully."];
}
}
else if ([lastAction isEqualTo:jobMove]) {
if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be moved. They were kept in the results, and still are marked.",r]];
else
if ([py scanWasProblematic]) {
[problemDialog showWindow:self];
}
else {
[Dialogs showMessage:@"All marked files were moved sucessfully."];
}
}
else if ([lastAction isEqualTo:jobDelete]) {
if (r > 0) {
NSString *msg = @"%d file(s) couldn't be sent to Trash. They were kept in the results, "\
"and still are marked. See the F.A.Q. section in the help file for details.";
[Dialogs showMessage:[NSString stringWithFormat:msg,r]];
if ([py scanWasProblematic]) {
[problemDialog showWindow:self];
}
else
else {
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
}
}
else if ([lastAction isEqualTo:jobScan]) {
NSInteger groupCount = [outline intProperty:@"children_count" valueAtPath:nil];

View File

@@ -2,18 +2,18 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10C540</string>
<string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.AppKitVersion">1038.25</string>
<string key="IBDocument.HIToolboxVersion">458.00</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="598"/>
<integer value="219"/>
<integer value="29"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -1146,7 +1146,7 @@
<object class="NSMenuItem" id="578499792">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Clear Ignore List</string>
<string key="NSKeyEquiv">I</string>
<string key="NSKeyEquiv">G</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852972005"/>
@@ -1231,7 +1231,7 @@
<object class="NSMenuItem" id="904423169">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Add Selected to Ignore List</string>
<string key="NSKeyEquiv">i</string>
<string key="NSKeyEquiv">g</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852972005"/>
@@ -1275,6 +1275,15 @@
<reference key="NSOnImage" ref="852972005"/>
<reference key="NSMixedImage" ref="218295580"/>
</object>
<object class="NSMenuItem" id="517397504">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Invoke Custom Command</string>
<string key="NSKeyEquiv">i</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852972005"/>
<reference key="NSMixedImage" ref="218295580"/>
</object>
<object class="NSMenuItem" id="564101661">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Rename Selected</string>
@@ -2204,6 +2213,14 @@
</object>
<int key="connectionID">1176</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">invokeCustomCommand:</string>
<reference key="source" ref="339936126"/>
<reference key="destination" ref="517397504"/>
</object>
<int key="connectionID">1178</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -2530,6 +2547,7 @@
<reference ref="564101661"/>
<reference ref="630362403"/>
<reference ref="747820446"/>
<reference ref="517397504"/>
</object>
<reference key="parent" ref="528113253"/>
</object>
@@ -3066,6 +3084,11 @@
<reference key="object" ref="747820446"/>
<reference key="parent" ref="600111647"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1177</int>
<reference key="object" ref="517397504"/>
<reference key="parent" ref="600111647"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -3117,6 +3140,7 @@
<string>1171.IBPluginDependency</string>
<string>1172.IBPluginDependency</string>
<string>1173.IBPluginDependency</string>
<string>1177.IBPluginDependency</string>
<string>134.IBPluginDependency</string>
<string>134.ImportedFromIB2</string>
<string>136.IBPluginDependency</string>
@@ -3355,6 +3379,7 @@
<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"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -3374,9 +3399,9 @@
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{{109, 366}, {557, 400}}</string>
<string>{{439, 345}, {557, 400}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{109, 366}, {557, 400}}</string>
<string>{{439, 345}, {557, 400}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
@@ -3423,7 +3448,7 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{286, 475}, {361, 293}}</string>
<string>{{286, 455}, {361, 313}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3561,7 +3586,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">1176</int>
<int key="maxID">1178</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -3776,8 +3801,17 @@
<string key="className">ResultWindow</string>
<string key="superclassName">ResultWindowBase</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">removeDeadTracks:</string>
<string key="NS.object.0">id</string>
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>resetColumnsToDefault:</string>
<string>startDuplicateScan:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
@@ -3799,6 +3833,7 @@
<string>exportToXHTML:</string>
<string>filter:</string>
<string>ignoreSelected:</string>
<string>invokeCustomCommand:</string>
<string>markAll:</string>
<string>markInvert:</string>
<string>markNone:</string>
@@ -3848,6 +3883,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="outlets">
@@ -4500,7 +4536,7 @@
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../../me/dupeguru.xcodeproj</string>
<string key="IBDocument.LastKnownRelativeProjectPath">../../se/dupeguru.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -30,6 +30,9 @@
CE003CCC11242D00004B0AA7 /* NSTableViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CC511242D00004B0AA7 /* NSTableViewAdditions.m */; };
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CCE11242D2C004B0AA7 /* DirectoryOutline.m */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_me_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */; };
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */; };
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */; };
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */; };
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B3D6611243F83009A7A30 /* ResultOutline.m */; };
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
CE14259F0AFB719300BD5167 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
@@ -108,6 +111,13 @@
CE003CCE11242D2C004B0AA7 /* DirectoryOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DirectoryOutline.m; path = ../base/DirectoryOutline.m; sourceTree = SOURCE_ROOT; };
CE003CCF11242D2C004B0AA7 /* PyDirectoryOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDirectoryOutline.h; path = ../base/PyDirectoryOutline.h; sourceTree = SOURCE_ROOT; };
CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_me_help; path = ../../help_me/dupeguru_me_help; sourceTree = "<group>"; };
CE0A0BFE1175A1C000DCA3C6 /* HSTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSTable.h; sourceTree = "<group>"; };
CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE0A0C011175A1DE00DCA3C6 /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE0A0C131175A28100DCA3C6 /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE0B3D6411243F83009A7A30 /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE0B3D6511243F83009A7A30 /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE0B3D6611243F83009A7A30 /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
@@ -155,8 +165,6 @@
CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE900AD1109B238600754048 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
CE900AD6109B2A9B00754048 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; sourceTree = "<group>"; };
CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = "<group>"; };
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CEDF07A1112493B200EE5BC0 /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
@@ -181,21 +189,19 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
080E96DDFE201D6D7F000001 /* Classes */ = {
080E96DDFE201D6D7F000001 /* DGME */ = {
isa = PBXGroup;
children = (
CE381C9509914ACE003581CE /* AppDelegate.h */,
CE381C9409914ACE003581CE /* AppDelegate.m */,
CE848A1809DD85810004CB44 /* Consts.h */,
CECA899A09DB132E00A3D774 /* DetailsPanel.h */,
CECA899B09DB132E00A3D774 /* DetailsPanel.m */,
CE68EE6509ABC48000971085 /* DirectoryPanel.h */,
CE68EE6609ABC48000971085 /* DirectoryPanel.m */,
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */,
CE381C9B09914ADF003581CE /* ResultWindow.h */,
CE381C9A09914ADF003581CE /* ResultWindow.m */,
);
name = Classes;
name = DGME;
sourceTree = "<group>";
};
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
@@ -228,7 +234,7 @@
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
isa = PBXGroup;
children = (
080E96DDFE201D6D7F000001 /* Classes */,
080E96DDFE201D6D7F000001 /* DGME */,
CE515E140FC6C17900EC695D /* dgbase */,
CE515DDD0FC6C09400EC695D /* cocoalib */,
29B97315FDCFA39411CA2CEA /* Other Sources */,
@@ -277,6 +283,8 @@
CE003CB411242D00004B0AA7 /* HSGUIController.m */,
CE003CB511242D00004B0AA7 /* HSOutline.h */,
CE003CB611242D00004B0AA7 /* HSOutline.m */,
CE0A0BFE1175A1C000DCA3C6 /* HSTable.h */,
CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */,
CE003CB711242D00004B0AA7 /* HSWindowController.h */,
CE003CB811242D00004B0AA7 /* HSWindowController.m */,
);
@@ -289,6 +297,7 @@
children = (
CE003CBC11242D00004B0AA7 /* PyGUI.h */,
CE003CBD11242D00004B0AA7 /* PyOutline.h */,
CE0A0C131175A28100DCA3C6 /* PyTable.h */,
);
name = proxies;
path = ../../cocoalib/proxies;
@@ -315,6 +324,7 @@
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
CE900AD1109B238600754048 /* Preferences.xib */,
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */,
);
path = xib;
sourceTree = "<group>";
@@ -383,6 +393,8 @@
CE6032BF0FE6784C007E33FF /* DetailsPanel.m */,
CE515E180FC6C19300EC695D /* DirectoryPanel.h */,
CE515E190FC6C19300EC695D /* DirectoryPanel.m */,
CE0A0C011175A1DE00DCA3C6 /* ProblemDialog.h */,
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */,
CE515E1B0FC6C19300EC695D /* ResultWindow.h */,
CE515E1C0FC6C19300EC695D /* ResultWindow.m */,
CE0B3D6511243F83009A7A30 /* ResultOutline.h */,
@@ -391,6 +403,7 @@
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */,
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */,
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */,
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */,
CE0B3D6411243F83009A7A30 /* PyResultTree.h */,
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */,
);
@@ -466,6 +479,7 @@
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */,
CE4B59C91119919700C06C9E /* progress.xib in Resources */,
CE4B59CA1119919700C06C9E /* registration.xib in Resources */,
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -502,6 +516,8 @@
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */,
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */,
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */,
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */,
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -12,6 +12,9 @@
CE031751109B340A00517EE6 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031750109B340A00517EE6 /* Preferences.xib */; };
CE031754109B345200517EE6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031753109B345200517EE6 /* MainMenu.xib */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */; };
CE0C2AB61177011000BC749F /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C2AB51177011000BC749F /* HSTable.m */; };
CE0C2ABD1177014200BC749F /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C2ABB1177014200BC749F /* ProblemDialog.m */; };
CE0C2AC81177021600BC749F /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0C2AC71177021600BC749F /* ProblemDialog.xib */; };
CE15C8A80ADEB8B50061D4A5 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; };
CE15C8C00ADEB8D40061D4A5 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; };
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
@@ -84,6 +87,13 @@
CE031750109B340A00517EE6 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
CE031753109B345200517EE6 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_pe_help; path = ../../help_pe/dupeguru_pe_help; sourceTree = SOURCE_ROOT; };
CE0C2AAA117700E700BC749F /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE0C2AB41177011000BC749F /* HSTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSTable.h; sourceTree = "<group>"; };
CE0C2AB51177011000BC749F /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE0C2ABA1177014200BC749F /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0C2ABB1177014200BC749F /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE0C2ABC1177014200BC749F /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0C2AC71177021600BC749F /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
@@ -180,7 +190,7 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
080E96DDFE201D6D7F000001 /* Classes */ = {
080E96DDFE201D6D7F000001 /* DGPE */ = {
isa = PBXGroup;
children = (
CE381C9509914ACE003581CE /* AppDelegate.h */,
@@ -194,7 +204,7 @@
CE381C9B09914ADF003581CE /* ResultWindow.h */,
CE381C9A09914ADF003581CE /* ResultWindow.m */,
);
name = Classes;
name = DGPE;
sourceTree = "<group>";
};
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
@@ -227,7 +237,7 @@
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
isa = PBXGroup;
children = (
080E96DDFE201D6D7F000001 /* Classes */,
080E96DDFE201D6D7F000001 /* DGPE */,
CE80DB1A0FC192AB0086DCA6 /* cocoalib */,
CE80DB810FC194BD0086DCA6 /* dgbase */,
29B97315FDCFA39411CA2CEA /* Other Sources */,
@@ -276,6 +286,7 @@
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */,
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */,
CE031750109B340A00517EE6 /* Preferences.xib */,
CE0C2AC71177021600BC749F /* ProblemDialog.xib */,
);
path = xib;
sourceTree = "<group>";
@@ -335,19 +346,22 @@
CE6044EB0FE6796200B71262 /* DetailsPanel.m */,
CE80DB850FC1951C0086DCA6 /* DirectoryPanel.h */,
CE80DB860FC1951C0086DCA6 /* DirectoryPanel.m */,
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
CE9EA76F1122CA0B008CD2BC /* DirectoryOutline.h */,
CE9EA7701122CA0B008CD2BC /* DirectoryOutline.m */,
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */,
CE0C2ABA1177014200BC749F /* ProblemDialog.h */,
CE0C2ABB1177014200BC749F /* ProblemDialog.m */,
CE80DB880FC1951C0086DCA6 /* ResultWindow.h */,
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */,
CE958658112C516400F95FD2 /* PyResultTree.h */,
CE95865A112C516400F95FD2 /* ResultOutline.h */,
CE95865B112C516400F95FD2 /* ResultOutline.m */,
CE958659112C516400F95FD2 /* PyStatsLabel.h */,
CE95865C112C516400F95FD2 /* StatsLabel.h */,
CE95865D112C516400F95FD2 /* StatsLabel.m */,
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
CE18126F111C9D5100E49FCE /* PyDetailsPanel.h */,
CE9EA7711122CA0B008CD2BC /* PyDirectoryOutline.h */,
CE0C2ABC1177014200BC749F /* PyProblemDialog.h */,
CE958659112C516400F95FD2 /* PyStatsLabel.h */,
);
name = dgbase;
sourceTree = "<group>";
@@ -359,6 +373,8 @@
CE9EA7441122C96C008CD2BC /* HSGUIController.m */,
CE9EA7451122C96C008CD2BC /* HSOutline.h */,
CE9EA7461122C96C008CD2BC /* HSOutline.m */,
CE0C2AB41177011000BC749F /* HSTable.h */,
CE0C2AB51177011000BC749F /* HSTable.m */,
CE9EA7471122C96C008CD2BC /* HSWindowController.h */,
CE9EA7481122C96C008CD2BC /* HSWindowController.m */,
);
@@ -371,6 +387,7 @@
children = (
CE9EA74C1122C96C008CD2BC /* PyGUI.h */,
CE9EA74D1122C96C008CD2BC /* PyOutline.h */,
CE0C2AAA117700E700BC749F /* PyTable.h */,
);
name = proxies;
path = ../../cocoalib/proxies;
@@ -470,6 +487,7 @@
CE7AC9181119911200D02F6C /* ErrorReportWindow.xib in Resources */,
CE7AC9191119911200D02F6C /* progress.xib in Resources */,
CE7AC91A1119911200D02F6C /* registration.xib in Resources */,
CE0C2AC81177021600BC749F /* ProblemDialog.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -509,6 +527,8 @@
CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */,
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */,
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */,
CE0C2AB61177011000BC749F /* HSTable.m in Sources */,
CE0C2ABD1177014200BC749F /* ProblemDialog.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -57,8 +57,6 @@ http://www.hardcoded.net/licenses/hs_license
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
[_py setSizeThreshold:sizeThreshold];
int r = n2i([py doScan]);
[matches reloadData];
[self refreshStats];
if (r != 0)
[[ProgressController mainProgressController] hide];
if (r == 1)

View File

@@ -19,6 +19,8 @@
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3A46F9109B212E002ABFD5 /* MainMenu.xib */; };
CE45579B0AE3BC2B005A9546 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE647E551173024A006D28BA /* ProblemDialog.m */; };
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE647E581173026F006D28BA /* ProblemDialog.xib */; };
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */; };
CE76FDC4111EE37C006618EA /* HSOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDBF111EE37C006618EA /* HSOutlineView.m */; };
CE76FDC5111EE37C006618EA /* NSIndexPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDC1111EE37C006618EA /* NSIndexPathAdditions.m */; };
@@ -27,6 +29,7 @@
CE76FDD4111EE3A7006618EA /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */; };
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; };
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE8C53BB117324CE0011B41F /* HSTable.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 */; };
@@ -83,6 +86,10 @@
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CE45579A0AE3BC2B005A9546 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE647E541173024A006D28BA /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E551173024A006D28BA /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE647E561173024A006D28BA /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E581173026F006D28BA /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = ../base/dsa_pub.pem; sourceTree = "<group>"; };
CE6E7407111C997500C350E3 /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE76FDBE111EE37C006618EA /* HSOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSOutlineView.h; sourceTree = "<group>"; };
@@ -102,6 +109,8 @@
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; };
CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; };
CE8C53B61173248F0011B41F /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE8C53BB117324CE0011B41F /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
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; };
@@ -271,6 +280,7 @@
CE76FDDE111EE42F006618EA /* HSOutline.m */,
CE76FDC8111EE38E006618EA /* HSGUIController.h */,
CE76FDC9111EE38E006618EA /* HSGUIController.m */,
CE8C53BB117324CE0011B41F /* HSTable.m */,
);
name = controllers;
path = ../../cocoalib/controllers;
@@ -281,6 +291,7 @@
children = (
CE76FDCD111EE38E006618EA /* PyGUI.h */,
CE76FDCE111EE38E006618EA /* PyOutline.h */,
CE8C53B61173248F0011B41F /* PyTable.h */,
);
name = proxies;
path = ../../cocoalib/proxies;
@@ -299,6 +310,7 @@
CEEFC0CA10943849001F3A39 /* xib */ = {
isa = PBXGroup;
children = (
CE647E581173026F006D28BA /* ProblemDialog.xib */,
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */,
CEAC6810109B0B7E00B43C85 /* Preferences.xib */,
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */,
@@ -370,6 +382,9 @@
CE6E7407111C997500C350E3 /* PyDetailsPanel.h */,
CEFC7FB70FC951A700CD5728 /* ResultWindow.h */,
CEFC7FB80FC951A700CD5728 /* ResultWindow.m */,
CE647E541173024A006D28BA /* ProblemDialog.h */,
CE647E551173024A006D28BA /* ProblemDialog.m */,
CE647E561173024A006D28BA /* PyProblemDialog.h */,
);
name = dgbase;
sourceTree = "<group>";
@@ -435,6 +450,7 @@
CE19BC6311199231007CCEB0 /* ErrorReportWindow.xib in Resources */,
CE19BC6411199231007CCEB0 /* progress.xib in Resources */,
CE19BC6511199231007CCEB0 /* registration.xib in Resources */,
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -470,6 +486,8 @@
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */,
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */,
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */,
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */,
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Created By: Virgil Dupras
# Created On: 2006/11/11
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
@@ -12,7 +11,10 @@ from __future__ import unicode_literals
import os
import os.path as op
import logging
import subprocess
import re
from send2trash import send2trash
from hsutil import io, files
from hsutil.path import Path
from hsutil.reg import RegistrableApplication, RegistrationRequired
@@ -48,7 +50,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.results = results.Results(data_module)
self.scanner = scanner.Scanner()
self.action_count = 0
self.last_op_error_count = 0
self.options = {
'escape_filter_regexp': True,
'clean_empty_dirs': False,
@@ -70,17 +71,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
return self._do_delete_dupe(dupe)
j.start_job(self.results.mark_count)
self.last_op_error_count = self.results.perform_on_marked(op, True)
self.results.perform_on_marked(op, True)
def _do_delete_dupe(self, dupe):
if not io.exists(dupe.path):
return True
self._recycle_dupe(dupe)
return
send2trash(unicode(dupe.path)) # Raises OSError when there's a problem
self.clean_empty_dirs(dupe.path[:-1])
if not io.exists(dupe.path):
return True
logging.warning("Could not send {0} to trash.".format(unicode(dupe.path)))
return False
def _do_load(self, j):
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
@@ -88,8 +85,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
j = j.start_subjob([1, 9])
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)
for file in j.iter_with_progress(files, 'Reading metadata %d/%d'):
file._read_all_info(attrnames=self.data.METADATA_TO_READ)
try:
for file in j.iter_with_progress(files, 'Reading metadata %d/%d'):
file._read_all_info(attrnames=self.data.METADATA_TO_READ)
except OSError:
# 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):
if (dupe is None) or (group is None):
@@ -106,17 +109,16 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def _job_completed(self, jobid):
# Must be called by subclasses when they detect that an async job is completed.
if jobid in (JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_DELETE):
if jobid == JOB_SCAN:
self.notify('results_changed')
elif jobid in (JOB_LOAD, JOB_MOVE, JOB_DELETE):
self.notify('results_changed')
self.notify('problems_changed')
@staticmethod
def _open_path(path):
raise NotImplementedError()
@staticmethod
def _recycle_dupe(dupe):
raise NotImplementedError()
@staticmethod
def _reveal_path(path):
raise NotImplementedError()
@@ -178,28 +180,23 @@ class DupeGuru(RegistrableApplication, Broadcaster):
dest_path = dest_path + source_path[1:-1] #Remove drive letter and filename
elif dest_type == 1:
dest_path = dest_path + source_path[location_path:-1]
try:
if not io.exists(dest_path):
io.makedirs(dest_path)
if copy:
files.copy(source_path, dest_path)
else:
files.move(source_path, dest_path)
self.clean_empty_dirs(source_path[:-1])
except EnvironmentError as e:
operation = 'Copy' if copy else 'Move'
logging.warning('%s operation failed on %s. Error: %s' % (operation, unicode(dupe.path), unicode(e)))
return False
return True
if not io.exists(dest_path):
io.makedirs(dest_path)
# Raises an EnvironmentError if there's a problem
if copy:
files.copy(source_path, dest_path)
else:
files.move(source_path, dest_path)
self.clean_empty_dirs(source_path[:-1])
def copy_or_move_marked(self, copy, destination, recreate_path):
def do(j):
def op(dupe):
j.add_progress()
return self.copy_or_move(dupe, copy, destination, recreate_path)
self.copy_or_move(dupe, copy, destination, recreate_path)
j.start_job(self.results.mark_count)
self.last_op_error_count = self.results.perform_on_marked(op, not copy)
self.results.perform_on_marked(op, not copy)
self._demo_check()
jobid = JOB_COPY if copy else JOB_MOVE
@@ -223,6 +220,31 @@ class DupeGuru(RegistrableApplication, Broadcaster):
rows.append(row)
return export.export_to_xhtml(colnames, rows)
def invoke_command(self, cmd):
"""Calls command `cmd` with %d and %r placeholders replaced.
Using the current selection, %d is replaced with the currently selected dupe and %r is
replaced with that dupe's ref file. If there's no selection, the command is not invoked.
If the dupe is a ref, %d and %r will be the same.
"""
if not self.selected_dupes:
return
dupe = self.selected_dupes[0]
group = self.results.get_group_of_duplicate(dupe)
ref = group.ref
cmd = cmd.replace('%d', unicode(dupe.path))
cmd = cmd.replace('%r', unicode(ref.path))
match = re.match(r'"([^"]+)"(.*)', cmd)
if match is not None:
# This code here is because subprocess. Popen doesn't seem to accept, under Windows,
# executable paths with spaces in it, *even* when they're enclosed in "". So this is
# a workaround to make the damn thing work.
exepath, args = match.groups()
path, exename = op.split(exepath)
subprocess.Popen(exename + args, shell=True, cwd=path)
else:
subprocess.Popen(cmd, shell=True)
def load(self):
self._start_job(JOB_LOAD, self._do_load)
self.load_ignore_list()
@@ -279,7 +301,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.notify('results_changed_but_keep_selection')
def remove_marked(self):
self.results.perform_on_marked(lambda x:True, True)
self.results.perform_on_marked(lambda x:None, True)
self.notify('results_changed')
def remove_selected(self):

View File

@@ -13,10 +13,10 @@ from hsutil import cocoa, job
from hsutil.cocoa import install_exception_hook
from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
NSWorkspace, NSWorkspaceRecycleOperation)
NSWorkspace)
from hsutil.reg import RegistrationRequired
from . import app, fs
from . import app
JOBID2TITLE = {
app.JOB_SCAN: "Scanning for duplicates",
@@ -51,14 +51,6 @@ class DupeGuru(app.DupeGuru):
def _open_path(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
def _reveal_path(path):
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(unicode(path), '')

View File

@@ -9,10 +9,12 @@
# Common interface for all editions' dg_cocoa unit.
from hsutil.cocoa.inter import signature, PyOutline, PyGUIObject, PyRegistrable
from hsutil.cocoa.inter import signature, PyTable, PyOutline, PyGUIObject, PyRegistrable
from .gui.details_panel import DetailsPanel
from .gui.directory_tree import DirectoryTree
from .gui.problem_dialog import ProblemDialog
from .gui.problem_table import ProblemTable
from .gui.result_tree import ResultTree
from .gui.stats_label import StatsLabel
@@ -93,6 +95,9 @@ class PyDupeGuruBase(PyRegistrable):
def revealSelected(self):
self.py.reveal_selected()
def invokeCommand_(self, cmd):
self.py.invoke_command(cmd)
#---Information
def getIgnoreListCount(self):
return len(self.py.scanner.ignore_list)
@@ -100,8 +105,9 @@ class PyDupeGuruBase(PyRegistrable):
def getMarkCount(self):
return self.py.results.mark_count
def getOperationalErrorCount(self):
return self.py.last_op_error_count
@signature('i@:')
def scanWasProblematic(self):
return bool(self.py.results.problems)
#---Properties
def setMixFileKind_(self, mix_file_kind):
@@ -196,3 +202,13 @@ class PyStatsLabel(PyGUIObject):
def display(self):
return self.py.display
class PyProblemDialog(PyGUIObject):
py_class = ProblemDialog
def revealSelected(self):
self.py.reveal_selected_dupe()
class PyProblemTable(PyTable):
py_class = ProblemTable

View File

@@ -24,6 +24,9 @@ class GUIObject(Listener):
def marking_changed(self):
pass
def problems_changed(self):
pass
def results_changed(self):
pass

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-04-12
# 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
from hsutil.notify import Broadcaster
from .base import GUIObject
class ProblemDialog(GUIObject, Broadcaster):
def __init__(self, view, app):
GUIObject.__init__(self, view, app)
Broadcaster.__init__(self)
self._selected_dupe = None
def reveal_selected_dupe(self):
if self._selected_dupe is not None:
self.app._reveal_path(self._selected_dupe.path)
def select_dupe(self, dupe):
self._selected_dupe = dupe
#--- Event Handlers
def problems_changed(self):
self._selected_dupe = None
self.notify('problems_changed')

43
core/gui/problem_table.py Normal file
View File

@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-04-12
# 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
from hsutil.notify import Listener
from hsgui.table import GUITable, Row
class ProblemTable(GUITable, Listener):
def __init__(self, view, problem_dialog):
GUITable.__init__(self)
Listener.__init__(self, problem_dialog)
self.view = view
self.dialog = problem_dialog
#--- Override
def _update_selection(self):
row = self.selected_row
dupe = row.dupe if row is not None else None
self.dialog.select_dupe(dupe)
def _fill(self):
problems = self.dialog.app.results.problems
for dupe, msg in problems:
self.append(ProblemRow(self, dupe, msg))
#--- Event handlers
def problems_changed(self):
self.refresh()
self.view.refresh()
class ProblemRow(Row):
def __init__(self, table, dupe, msg):
Row.__init__(self, table)
self.dupe = dupe
self.msg = msg
self.path = unicode(dupe.path)

View File

@@ -32,6 +32,7 @@ class Results(Markable):
self.__recalculate_stats()
self.__marked_size = 0
self.data = data_module
self.problems = [] # (dupe, error_msg)
def _did_mark(self, dupe):
self.__marked_size += dupe.size
@@ -146,7 +147,7 @@ class Results(Markable):
self.__filters.append(filter_str)
if self.__filtered_dupes is None:
self.__filtered_dupes = flatten(g[:] for g in self.groups)
self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(dupe.name))
self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(unicode(dupe.path)))
filtered_groups = set()
for dupe in self.__filtered_dupes:
filtered_groups.add(self.get_group_of_duplicate(dupe))
@@ -230,17 +231,22 @@ class Results(Markable):
self.__dupes = None
def perform_on_marked(self, func, remove_from_results):
problems = []
for d in self.dupes:
if self.is_marked(d) and (not func(d)):
problems.append(d)
# Performs `func` on all marked dupes. If an EnvironmentError is raised during the call,
# the problematic dupe is added to self.problems.
self.problems = []
to_remove = []
marked = (dupe for dupe in self.dupes if self.is_marked(dupe))
for dupe in marked:
try:
func(dupe)
to_remove.append(dupe)
except EnvironmentError as e:
self.problems.append((dupe, unicode(e)))
if remove_from_results:
to_remove = [d for d in self.dupes if self.is_marked(d) and (d not in problems)]
self.remove_duplicates(to_remove)
self.mark_none()
for d in problems:
self.mark(d)
return len(problems)
for dupe, _ in self.problems:
self.mark(dupe)
def remove_duplicates(self, dupes):
'''Remove 'dupes' from their respective group, and remove the group is it ends up empty.

View File

@@ -9,7 +9,9 @@
import StringIO
import os.path as op
from lxml import etree
from nose.tools import eq_
from hsutil.path import Path
from hsutil.testcase import TestCase
@@ -252,18 +254,23 @@ class TCResultsMarkings(TestCase):
def test_perform_on_marked_with_problems(self):
def log_object(o):
log.append(o)
return o is not self.objects[1]
if o is self.objects[1]:
raise EnvironmentError('foobar')
log = []
self.results.mark_all()
self.assert_(self.results.is_marked(self.objects[1]))
self.assertEqual(1,self.results.perform_on_marked(log_object, True))
self.assertEqual(3,len(log))
self.assertEqual(1,len(self.results.groups))
self.assertEqual(2,len(self.results.groups[0]))
self.assert_(self.objects[1] in self.results.groups[0])
self.assert_(not self.results.is_marked(self.objects[2]))
self.assert_(self.results.is_marked(self.objects[1]))
assert self.results.is_marked(self.objects[1])
self.results.perform_on_marked(log_object, True)
eq_(len(log), 3)
eq_(len(self.results.groups), 1)
eq_(len(self.results.groups[0]), 2)
assert self.objects[1] in self.results.groups[0]
assert not self.results.is_marked(self.objects[2])
assert self.results.is_marked(self.objects[1])
eq_(len(self.results.problems), 1)
dupe, msg = self.results.problems[0]
assert dupe is self.objects[1]
eq_(msg, 'foobar')
def test_perform_on_marked_with_ref(self):
def log_object(o):
@@ -563,6 +570,10 @@ class TCResultsXML(TestCase):
self.results.load_from_xml(f, self.get_file)
first(self.results.groups[0].matches).percentage
def test_apply_filter_works_on_paths(self):
# apply_filter() searches on the whole path, not just on the filename.
self.results.apply_filter(u'basepath')
eq_(len(self.results.groups), 2)
class TCResultsFilter(TestCase):
def setUp(self):

View File

@@ -7,9 +7,7 @@
# http://www.hardcoded.net/licenses/hs_license
import os.path as op
import logging
import plistlib
import re
from lxml import etree
from appscript import app, k, CommandError
@@ -148,7 +146,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
except (CommandError, RuntimeError):
pass
j.start_job(self.results.mark_count, "Sending dupes to the Trash")
self.last_op_error_count = self.results.perform_on_marked(op, True)
self.results.perform_on_marked(op, True)
del self.path2iphoto
def _do_delete_dupe(self, dupe):
@@ -158,14 +156,13 @@ class DupeGuruPE(app_cocoa.DupeGuru):
try:
a = app('iPhoto')
a.remove(photo, timeout=0)
return True
except (CommandError, RuntimeError):
return False
except (CommandError, RuntimeError) as e:
raise EnvironmentError(unicode(e))
else:
logging.warning(u"Could not find photo %s in iPhoto Library", unicode(dupe.path))
return False
msg = u"Could not find photo %s in iPhoto Library" % unicode(dupe.path)
raise EnvironmentError(msg)
else:
return app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
def _do_load(self, j):
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))

View File

@@ -8,11 +8,9 @@
import logging
import multiprocessing
from Queue import Empty
from collections import defaultdict
from collections import defaultdict, deque
from hsutil import job
from hsutil.misc import dedupe
from core.engine import Match
from .block import avgdiff, DifferentBlockCountError, NoBlocksError
@@ -76,13 +74,6 @@ def async_compare(ref_id, other_ids, dbname, threshold):
return results
def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nulljob):
def empty_out_queue(queue, into):
try:
while True:
into.append(queue.get(block=False))
except Empty:
pass
j = j.start_subjob([3, 7])
pictures = prepare_pictures(pictures, cache_path, j)
j = j.start_subjob([9, 1], 'Preparing for matching')
@@ -100,7 +91,7 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
cache.close()
pictures = [p for p in pictures if hasattr(p, 'cache_id')]
pool = multiprocessing.Pool()
async_results = []
async_results = deque()
matches = []
pictures_copy = set(pictures)
for ref in j.iter_with_progress(pictures, 'Matched %d/%d pictures'):
@@ -111,10 +102,17 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
others = [pic for pic in others if not pic.is_ref]
if others:
cache_ids = [f.cache_id for f in others]
args = (ref.cache_id, cache_ids, cache_path, threshold)
async_results.append(pool.apply_async(async_compare, args))
if len(async_results) > RESULTS_QUEUE_LIMIT:
result = async_results.pop(0)
# 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))
cache_ids = cache_ids[ARG_LIMIT:]
# We use a while here because it's possible that more than one result has been added if
# ARG_LIMIT has been reached.
while len(async_results) > RESULTS_QUEUE_LIMIT:
result = async_results.popleft()
matches.extend(result.get())
for result in async_results: # process the rest of the results
matches.extend(result.get())

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,9 @@
- date: 2010-04-14
version: 5.8.0
description: |
* Improved error messages when files can't be sent to trash, moved or copied.
* Added a custom command invocation action. (#12)
* Filters are now applied on whole paths. (#4)
- date: 2010-02-13
version: 5.7.2
description: |

View File

@@ -34,3 +34,11 @@
* **Recreate absolute path:** The source file's path will be re-created in the destination directory in it's entirety. For example, if you move "/Users/foobar/Music/Artist/Album/the_song.mp3" to the destination "/Users/foobar/MyDestination", the final destination for the file will be "/Users/foobar/MyDestination/Users/foobar/Music/Artist/Album".
In all cases, dupeGuru nicely handles naming conflicts by prepending a number to the destination filename if the filename already exists in the destination.
**Custom Command:** This preference determines the command that will be invoked by the "Invoke Custom Command" action. You can invoke any external application through this action. This can be useful if, for example, you have a nice diffing application installed.
The format of the command is the same as what you would write in the command line, except that there are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the selected dupe (%d) and the path of the selected dupe's reference file (%r).
If the path to your executable contains space characters, you should enclose it in "" quotes. You should also enclose placeholders in quotes because it's very possible that paths to dupes and refs will contain spaces. Here's an example custom command:
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"

View File

@@ -70,4 +70,5 @@ Action Menu
* **Add Selected to Ignore List:** This first removes all selected duplicates from results, and then add the match of that duplicate and the current reference in the ignore list. This match will not come up again in further scan. The duplicate itself might come back, but it will be matched with another reference file. You can clear the ignore list with the Clear Ignore List command.
* **Open Selected with Default Application:** Open the file with the application associated with selected file's type.
* **Reveal Selected in Finder:** Open the folder containing selected file.
* **Invoke Custom Command:** Invokes the external application you've set up in your preferences using the current selection as arguments in the invocation.
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.

View File

@@ -1,7 +1,18 @@
- date: 2010-04-15
version: 1.9.0
description: |
* Improved error messages when files can't be sent to trash, moved or copied.
* Added a custom command invocation action. (#12)
* Filters are now applied on whole paths. (#4)
- date: 2010-04-08
version: 1.8.6
description: |
* 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)
* 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

View File

@@ -21,3 +21,11 @@
* **Recreate absolute path:** The source file's path will be re-created in the destination directory in it's entirety. For example, if you move "/Users/foobar/Picture/2006/06/photo.jpg" to the destination "/Users/foobar/MyDestination", the final destination for the file will be "/Users/foobar/MyDestination/Users/foobar/Picture/2006/06".
In all cases, dupeGuru PE nicely handles naming conflicts by prepending a number to the destination filename if the filename already exists in the destination.
**Custom Command:** This preference determines the command that will be invoked by the "Invoke Custom Command" action. You can invoke any external application through this action. This can be useful if, for example, you have a nice diffing application installed.
The format of the command is the same as what you would write in the command line, except that there are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the selected dupe (%d) and the path of the selected dupe's reference file (%r).
If the path to your executable contains space characters, you should enclose it in "" quotes. You should also enclose placeholders in quotes because it's very possible that paths to dupes and refs will contain spaces. Here's an example custom command:
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"

View File

@@ -70,4 +70,5 @@ Action Menu
* **Add Selected to Ignore List:** This first removes all selected duplicates from results, and then add the match of that duplicate and the current reference in the ignore list. This match will not come up again in further scan. The duplicate itself might come back, but it will be matched with another reference file. You can clear the ignore list with the Clear Ignore List command.
* **Open Selected with Default Application:** Open the file with the application associated with selected file's type.
* **Reveal Selected in Finder:** Open the folder containing selected file.
* **Invoke Custom Command:** Invokes the external application you've set up in your preferences using the current selection as arguments in the invocation.
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.

View File

@@ -1,3 +1,9 @@
- date: 2010-04-13
version: 2.10.0
description: |
* Improved error messages when files can't be sent to trash, moved or copied.
* Added a custom command invocation action. (#12)
* Filters are now applied on whole paths. (#4)
- date: 2010-02-10
version: 2.9.2
description: |

View File

@@ -25,3 +25,11 @@
* **Recreate absolute path:** The source file's path will be re-created in the destination directory in it's entirety. For example, if you move "/Users/foobar/Music/Artist/Album/the_song.mp3" to the destination "/Users/foobar/MyDestination", the final destination for the file will be "/Users/foobar/MyDestination/Users/foobar/Music/Artist/Album".
In all cases, dupeGuru nicely handles naming conflicts by prepending a number to the destination filename if the filename already exists in the destination.
**Custom Command:** This preference determines the command that will be invoked by the "Invoke Custom Command" action. You can invoke any external application through this action. This can be useful if, for example, you have a nice diffing application installed.
The format of the command is the same as what you would write in the command line, except that there are 2 placeholders: **%d** and **%r**. These placeholders will be replaced by the path of the selected dupe (%d) and the path of the selected dupe's reference file (%r).
If the path to your executable contains space characters, you should enclose it in "" quotes. You should also enclose placeholders in quotes because it's very possible that paths to dupes and refs will contain spaces. Here's an example custom command:
"C:\Program Files\SuperDiffProg\SuperDiffProg.exe" "%d" "%r"

View File

@@ -70,4 +70,5 @@ Action Menu
* **Add Selected to Ignore List:** This first removes all selected duplicates from results, and then add the match of that duplicate and the current reference in the ignore list. This match will not come up again in further scan. The duplicate itself might come back, but it will be matched with another reference file. You can clear the ignore list with the Clear Ignore List command.
* **Open Selected with Default Application:** Open the file with the application associated with selected file's type.
* **Reveal Selected in Finder:** Open the folder containing selected file.
* **Invoke Custom Command:** Invokes the external application you've set up in your preferences using the current selection as arguments in the invocation.
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.

View File

@@ -10,11 +10,13 @@
import sys
import os
import os.path as op
import compileall
import shutil
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):
app_path = {
@@ -24,7 +26,7 @@ def package_cocoa(edition):
}[edition]
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)
# The release version is outdated. Use at least r672 on http://svn.pyinstaller.org/trunk
if sys.platform != "win32":
@@ -36,47 +38,88 @@ def package_qt(edition):
os.chdir(op.join('qt', edition))
from app import DupeGuru
# Removing build and dist
if op.exists('build'):
shutil.rmtree('build')
if op.exists('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
print_and_do("del dist\\POWRPROF.dll") # no need of that crap
print_and_do("del dist\\SHLWAPI.dll") # no need of that crap
print_and_do("xcopy /Y /S /I ..\\..\\help_me\\dupeguru_me_help dist\\help")
cmd = 'cxfreeze --base-name Win32GUI --target-name "{0}.exe" --icon {1} start.py'
target_name = {'se': 'dupeGuru', 'me': 'dupeGuru ME', 'pe': 'dupeGuru PE'}[edition]
icon_path = '..\\..\\images\\dg{0}_logo.ico'.format(edition)
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))
help_basedir = '..\\..\\help_{0}'.format(edition)
help_dir = 'dupeguru_{0}_help'.format(edition) if edition != 'se' else 'dupeguru_help'
help_path = op.join(help_basedir, help_dir)
print "Copying {0} to dist\\help".format(help_path)
shutil.copytree(help_path, 'dist\\help')
# AdvancedInstaller.com has to be in your PATH
# this is so we don'a have to re-commit installer.aip at every version change
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')
os.remove('installer_tmp.aip')
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():
conf = yaml.load(open('conf.yaml'))
edition = conf['edition']
ui = conf['ui']
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)
if ui == 'cocoa':
package_cocoa(edition)
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__':
main()

View File

@@ -28,6 +28,7 @@ from . import platform
from .main_window import MainWindow
from .directories_dialog import DirectoriesDialog
from .problem_dialog import ProblemDialog
JOBID2TITLE = {
JOB_SCAN: "Scanning for duplicates",
@@ -71,6 +72,7 @@ class DupeGuru(DupeGuruBase, QObject):
self._progress = Progress(self.main_window)
self.directories_dialog = DirectoriesDialog(self.main_window, self)
self.details_dialog = self._create_details_dialog(self.main_window)
self.problemDialog = ProblemDialog(parent=self.main_window, app=self)
self.preferences_dialog = self._create_preferences_dialog(self.main_window)
self.about_box = AboutBox(self.main_window, self)
@@ -121,10 +123,6 @@ class DupeGuru(DupeGuruBase, QObject):
url = QUrl.fromLocalFile(unicode(path))
QDesktopServices.openUrl(url)
@staticmethod
def _recycle_dupe(dupe):
platform.recycle_file(dupe.path)
@staticmethod
def _reveal_path(path):
DupeGuru._open_path(path[:-1])
@@ -173,6 +171,14 @@ class DupeGuru(DupeGuruBase, QObject):
def askForRegCode(self):
self.reg.ask_for_code()
def invokeCustomCommand(self):
cmd = self.prefs.custom_command
if cmd:
self.invoke_command(cmd)
else:
msg = "You have no custom command set up. Please, set it up in your preferences."
QMessageBox.warning(self.main_window, 'Custom Command', msg)
def openDebugLog(self):
debugLogPath = op.join(self.appdata, 'debug.log')
self._open_path(debugLogPath)
@@ -187,7 +193,8 @@ class DupeGuru(DupeGuruBase, QObject):
self.directories_dialog.show()
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)
def show_preferences(self):
@@ -209,9 +216,12 @@ class DupeGuru(DupeGuruBase, QObject):
def job_finished(self, jobid):
self._job_completed(jobid)
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE) and self.last_op_error_count > 0:
msg = "{0} files could not be processed.".format(self.results.mark_count)
QMessageBox.warning(self.main_window, 'Warning', msg)
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE):
if self.results.problems:
self.problemDialog.show()
else:
msg = "All files were processed successfully."
QMessageBox.information(self.main_window, 'Operation Complete', msg)
elif jobid == JOB_SCAN:
if not self.results.groups:
title = "Scanning complete"

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
# http://www.hardcoded.net/licenses/hs_license
import sys
from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView,
QMessageBox, QInputDialog, QLineEdit, QDesktopServices)
@@ -35,6 +37,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
self.connect(self.resultsView, SIGNAL('doubleClicked()'), self.resultsDoubleClicked)
self.connect(self.resultsView, SIGNAL('spacePressed()'), self.resultsSpacePressed)
self.actionInvokeCustomCommand.triggered.connect(self.app.invokeCustomCommand)
def _setupUi(self):
self.setupUi(self)
@@ -74,6 +77,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
actionMenu.addSeparator()
actionMenu.addAction(self.actionOpenSelected)
actionMenu.addAction(self.actionRevealSelected)
actionMenu.addAction(self.actionInvokeCustomCommand)
actionMenu.addAction(self.actionRenameSelected)
self.actionActions.setMenu(actionMenu)
button = QToolButton(self.toolBar)
@@ -86,6 +90,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.statusLabel = QLabel(self)
self.statusbar.addPermanentWidget(self.statusLabel, 1)
# Linux setup
if sys.platform == 'linux2':
self.actionCheckForUpdate.setVisible(False) # This only works on Windows
#--- Private
def _confirm(self, title, msg, default_button=QMessageBox.Yes):
buttons = QMessageBox.Yes | QMessageBox.No

View File

@@ -44,6 +44,9 @@
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
@@ -54,7 +57,7 @@
<x>0</x>
<y>0</y>
<width>630</width>
<height>22</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuColumns">
@@ -77,6 +80,7 @@
<addaction name="separator"/>
<addaction name="actionOpenSelected"/>
<addaction name="actionRevealSelected"/>
<addaction name="actionInvokeCustomCommand"/>
<addaction name="actionRenameSelected"/>
<addaction name="separator"/>
<addaction name="actionApplyFilter"/>
@@ -428,6 +432,14 @@
<string>Open Debug Log</string>
</property>
</action>
<action name="actionInvokeCustomCommand">
<property name="text">
<string>Invoke Custom Command</string>
</property>
<property name="shortcut">
<string>Ctrl+I</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@@ -7,7 +7,5 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
INITIAL_FOLDER_IN_DIALOGS = '/'
def recycle_file(path):
pass
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
INITIAL_FOLDER_IN_DIALOGS = '/'
def recycle_file(path):
pass
INITIAL_FOLDER_IN_DIALOGS = u'/'
HELP_PATH = ''

View File

@@ -7,16 +7,5 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
from __future__ import unicode_literals
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)
INITIAL_FOLDER_IN_DIALOGS = u'C:\\'
HELP_PATH = 'help'

View File

@@ -26,6 +26,7 @@ class Preferences(PreferencesBase):
self.use_regexp = get('UseRegexp', self.use_regexp)
self.remove_empty_folders = get('RemoveEmptyFolders', self.remove_empty_folders)
self.destination_type = get('DestinationType', self.destination_type)
self.custom_command = get('CustomCommand', self.custom_command)
widths = get('ColumnsWidth', self.columns_width)
# only set nonzero values
for index, width in enumerate(widths[:len(self.columns_width)]):
@@ -46,6 +47,7 @@ class Preferences(PreferencesBase):
self.use_regexp = False
self.remove_empty_folders = False
self.destination_type = 1
self.custom_command = ''
self.registration_code = ''
self.registration_email = ''
self._reset_specific()
@@ -64,6 +66,7 @@ class Preferences(PreferencesBase):
set_('UseRegexp', self.use_regexp)
set_('RemoveEmptyFolders', self.remove_empty_folders)
set_('DestinationType', self.destination_type)
set_('CustomCommand', self.custom_command)
set_('ColumnsWidth', self.columns_width)
set_('ColumnsVisible', self.columns_visible)
set_('RegistrationCode', self.registration_code)

32
qt/base/problem_dialog.py Normal file
View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-04-12
# 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
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QDialog
from core.gui.problem_dialog import ProblemDialog as ProblemDialogModel
from .problem_table import ProblemTable
from .problem_dialog_ui import Ui_ProblemDialog
class ProblemDialog(QDialog, Ui_ProblemDialog):
def __init__(self, parent, app):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QDialog.__init__(self, parent, flags)
self.app = app
self._setupUi()
self.model = ProblemDialogModel(view=self, app=app)
self.table = ProblemTable(problem_dialog=self, view=self.tableView)
self.model.connect()
self.table.model.connect()
self.revealButton.clicked.connect(self.model.reveal_selected_dupe)
def _setupUi(self):
self.setupUi(self)

116
qt/base/problem_dialog.ui Normal file
View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProblemDialog</class>
<widget class="QDialog" name="ProblemDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>413</width>
<height>323</height>
</rect>
</property>
<property name="windowTitle">
<string>Problems!</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>There were problems processing some (or all) of the files. The cause of these problems are described in the table below. Those files were not removed from your results.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="tableView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>18</number>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>18</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="revealButton">
<property name="text">
<string>Reveal Selected</string>
</property>
</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>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Close</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>closeButton</sender>
<signal>clicked()</signal>
<receiver>ProblemDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>367</x>
<y>301</y>
</hint>
<hint type="destinationlabel">
<x>272</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
</ui>

25
qt/base/problem_table.py Normal file
View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2010-04-12
# 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
from qtlib.column import Column
from qtlib.table import Table
from core.gui.problem_table import ProblemTable as ProblemTableModel
class ProblemTable(Table):
COLUMNS = [
Column('path', 'File Path', 150),
Column('msg', 'Error Message', 150),
]
def __init__(self, problem_dialog, view):
model = ProblemTableModel(view=self, problem_dialog=problem_dialog.model)
Table.__init__(self, model, view)
# we have to prevent Return from initiating editing.
# self.view.editSelected = lambda: None

View File

@@ -14,9 +14,10 @@ from preferences import Preferences
from preferences_dialog import PreferencesDialog
class DupeGuru(DupeGuruBase):
EDITION = 'me'
LOGO_NAME = 'logo_me'
NAME = 'dupeGuru Music Edition'
VERSION = '5.7.2'
VERSION = '5.8.0'
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8])
def __init__(self):

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,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5" modules="professional" RootPath="." Language="en">
<DOCUMENT Type="Advanced Installer" CreateVersion="4.7.2" version="7.6" Modules="professional" RootPath="." Language="en">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
@@ -28,18 +28,13 @@
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
<ROW Directory="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AIShRegAnswer" ComponentId="{7DB5C163-2978-436F-A47D-54F1C76F1D64}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
<ROW Component="AI_ExePath" ComponentId="{AB8EF793-B4A4-4A5C-A343-8095FFE16175}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="PyWinTypes26.dll" ComponentId="{E7DC87D7-F396-46F0-8132-D4F582709AA2}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
<ROW Component="CurrentVersion" ComponentId="{1EF88868-DCB1-4F7D-83F6-CC17C9F65740}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
<ROW Component="QtCore4.dll" ComponentId="{731F12A4-0DB0-4484-8BA1-399560578D68}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
<ROW Component="QtGui4.dll" ComponentId="{3D4FDAFA-EE5E-43C5-A4F5-125F7FA6A550}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
<ROW Component="bz2.pyd_1" ComponentId="{E34B2912-4B50-4EEA-B1EF-B56FA625FCC7}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
@@ -47,78 +42,48 @@
<ROW Component="dupeGuru_ME.exe" ComponentId="{14F7B73A-FA85-4C10-AA92-10BE05FE103B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_ME.exe"/>
<ROW Component="hs_title.png" ComponentId="{A292ADA8-FEC0-49B9-81A5-6C7F837290D4}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
<ROW Component="python26.dll" ComponentId="{20E0EA31-C5CF-4278-B7C6-5FCA0C691B7F}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
<ROW Component="pythoncom26.dll" ComponentId="{C0489561-2362-48C1-86E8-D5F1A08DE4DE}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
<ROW Component="qcncodecs4.dll" ComponentId="{03C97279-4453-48E0-A40D-D28E6F3E701F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
<ROW Component="qgif4.dll" ComponentId="{5D6E676F-18BC-49C8-BBD2-E6BA1F3CA043}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
<ROW Component="qico4.dll" ComponentId="{C23E13E3-0E14-46E8-AA73-5D592CDBB725}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
<ROW Component="qjpcodecs4.dll" ComponentId="{E6649370-16BB-449A-8668-9995B5C1CEB5}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll"/>
<ROW Component="qjpeg4.dll" ComponentId="{1D084E38-4A03-4C3C-87F7-3C68FEB41B4C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll"/>
<ROW Component="qkrcodecs4.dll" ComponentId="{18F32B38-7D3F-4F3C-AB80-3778634C8676}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll"/>
<ROW Component="qmng4.dll" ComponentId="{D7E0BF84-EB34-4E4B-81CD-93B47B31503C}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
<ROW Component="qsvg4.dll" ComponentId="{3920BD4C-9A56-4CE4-A321-E649652D3D8A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
<ROW Component="qsvgicon4.dll" ComponentId="{F5D7A7C3-6320-4274-90DF-9F42C94FCDED}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{990608A3-AD85-439A-B46A-764DF560FA3A}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{1F04BD2B-42BD-412D-B101-806B130CD1B8}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
<ROW Component="qtiff4.dll" ComponentId="{D5B4A7B8-7D9B-4A5C-9DD5-2048690EEE11}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
<ROW Component="qtwcodecs4.dll" ComponentId="{E6C5E92F-D193-4A75-88E2-5058F069C224}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_ME.exe AIShRegAnswer bz2.pyd_1 python26.dll pythoncom26.dll PyWinTypes26.dll qtaccessiblecompatwidgets4.dll qtaccessiblewidgets4.dll qcncodecs4.dll qjpcodecs4.dll qkrcodecs4.dll qtwcodecs4.dll qsvgicon4.dll qgif4.dll qico4.dll qjpeg4.dll qmng4.dll qsvg4.dll qtiff4.dll QtCore4.dll QtGui4.dll AI_ExePath credits.htm hs_title.png"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_ME.exe AIShRegAnswer bz2.pyd_1 python26.dll QtCore4.dll QtGui4.dll AI_ExePath credits.htm hs_title.png CurrentVersion"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="5"/>
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="6"/>
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="9"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="23"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="24"/>
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="4"/>
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd_1" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="5"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="7"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="8"/>
<ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="36"/>
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="37"/>
<ROW File="dupeGuru_ME.exe" Component_="dupeGuru_ME.exe" FileName="dupeGu~1.exe|dupeGuru ME.exe" Attributes="0" SourcePath="dist\dupeGuru ME.exe" SelfReg="false" Sequence="2"/>
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="38"/>
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="39"/>
<ROW File="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="32"/>
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="40"/>
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="41"/>
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="42"/>
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="43"/>
<ROW File="pyexpat.pyd" Component_="bz2.pyd_1" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="4"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="7"/>
<ROW File="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" SelfReg="false" Sequence="8"/>
<ROW File="qcncodecs4.dll" Component_="qcncodecs4.dll" FileName="qcncod~1.dll|qcncodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qcncodecs4.dll" SelfReg="false" Sequence="12"/>
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="17"/>
<ROW File="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="18"/>
<ROW File="qjpcodecs4.dll" Component_="qjpcodecs4.dll" FileName="qjpcod~1.dll|qjpcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qjpcodecs4.dll" SelfReg="false" Sequence="13"/>
<ROW File="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="19"/>
<ROW File="qkrcodecs4.dll" Component_="qkrcodecs4.dll" FileName="qkrcod~1.dll|qkrcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qkrcodecs4.dll" SelfReg="false" Sequence="14"/>
<ROW File="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="20"/>
<ROW File="qsvg4.dll" Component_="qsvg4.dll" FileName="qsvg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qsvg4.dll" SelfReg="false" Sequence="21"/>
<ROW File="qsvgicon4.dll" Component_="qsvgicon4.dll" FileName="qsvgic~1.dll|qsvgicon4.dll" Attributes="0" SourcePath="dist\qt4_plugins\iconengines\qsvgicon4.dll" SelfReg="false" Sequence="16"/>
<ROW File="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="10"/>
<ROW File="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="11"/>
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="22"/>
<ROW File="qtwcodecs4.dll" Component_="qtwcodecs4.dll" FileName="qtwcod~1.dll|qtwcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qtwcodecs4.dll" SelfReg="false" Sequence="15"/>
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="44"/>
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="45"/>
<ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="25"/>
<ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="26"/>
<ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="33"/>
<ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="34"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="27"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&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="46"/>
<ROW File="win32api.pyd" Component_="bz2.pyd_1" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="28"/>
<ROW File="win32com.shell.shell.pyd" Component_="bz2.pyd_1" FileName="win32c~1.pyd|win32com.shell.shell.pyd" Attributes="0" SourcePath="dist\win32com.shell.shell.pyd" SelfReg="false" Sequence="29"/>
<ROW File="win32sysloader.pyd" Component_="bz2.pyd_1" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="35"/>
<ROW File="win32trace.pyd" Component_="bz2.pyd_1" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="30"/>
<ROW File="win32ui.pyd" Component_="bz2.pyd_1" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="31"/>
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="15"/>
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="16"/>
<ROW File="dupeGuru_ME.exe" Component_="dupeGuru_ME.exe" FileName="dupeGu~1.exe|dupeGuru ME.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru ME.exe" SelfReg="false" Sequence="2"/>
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="17"/>
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="18"/>
<ROW File="hashlib.pyd" Component_="bz2.pyd_1" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="12"/>
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="19"/>
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="20"/>
<ROW File="lxml.etree.pyd" Component_="bz2.pyd_1" FileName="lxmlet~1.pyd|lxml.etree.pyd" Attributes="0" SourcePath="dist\lxml.etree.pyd" SelfReg="false" Sequence="26"/>
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="21"/>
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="22"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="6"/>
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="23"/>
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="24"/>
<ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="9"/>
<ROW File="send2trash_win.pyd" Component_="bz2.pyd_1" FileName="_send2~1.pyd|_send2trash_win.pyd" Attributes="0" SourcePath="dist\_send2trash_win.pyd" SelfReg="false" Sequence="27"/>
<ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="10"/>
<ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="13"/>
<ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="14"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="11"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;AI_STUBS&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="25"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_me_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="install" PackageFileName="dupeguru_me_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
<ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
<ATTRIBUTE name="Enable" value="false"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
@@ -239,10 +204,11 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="Uninstall_dupeGuru_ME" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru ME" Component_="qtwcodecs4.dll" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Uninstall_dupeGuru_ME" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru ME" Component_="AIShRegAnswer" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="dupeGuru_ME" Directory_="SHORTCUTDIR" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="dupeGuru_ME_1" Directory_="DesktopFolder" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
</COMPONENT>

View File

@@ -57,6 +57,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
setchecked(self.useRegexpBox, prefs.use_regexp)
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
self.customCommandEdit.setText(prefs.custom_command)
def save(self):
prefs = self.app.prefs
@@ -75,6 +76,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
prefs.custom_command = unicode(self.customCommandEdit.text())
def resetToDefaults(self):
self.load(preferences.Preferences())

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>322</height>
<width>325</width>
<height>360</height>
</rect>
</property>
<property name="windowTitle">
@@ -19,9 +19,9 @@
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,0,0,0,1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -193,97 +193,86 @@
<height>40</height>
</size>
</property>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>91</width>
<height>17</height>
</rect>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="text">
<string>Tags to scan:</string>
<property name="margin">
<number>0</number>
</property>
</widget>
<widget class="QCheckBox" name="tagTrackBox">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Track</string>
</property>
</widget>
<widget class="QCheckBox" name="tagArtistBox">
<property name="geometry">
<rect>
<x>60</x>
<y>20</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Artist</string>
</property>
</widget>
<widget class="QCheckBox" name="tagAlbumBox">
<property name="geometry">
<rect>
<x>110</x>
<y>20</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Album</string>
</property>
</widget>
<widget class="QCheckBox" name="tagTitleBox">
<property name="geometry">
<rect>
<x>170</x>
<y>20</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Title</string>
</property>
</widget>
<widget class="QCheckBox" name="tagGenreBox">
<property name="geometry">
<rect>
<x>220</x>
<y>20</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Genre</string>
</property>
</widget>
<widget class="QCheckBox" name="tagYearBox">
<property name="geometry">
<rect>
<x>280</x>
<y>20</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Year</string>
</property>
</widget>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Tags to scan:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>15</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="tagTrackBox">
<property name="text">
<string>Track</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="tagArtistBox">
<property name="text">
<string>Artist</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="tagAlbumBox">
<property name="text">
<string>Album</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="tagTitleBox">
<property name="text">
<string>Title</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="tagGenreBox">
<property name="text">
<string>Genre</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="tagYearBox">
<property name="text">
<string>Year</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
@@ -369,6 +358,16 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Custom Command (arguments: %d for dupe, %r for ref):</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="customCommandEdit"/>
</item>
</layout>
</item>
<item>

View File

@@ -14,6 +14,9 @@ import base.dg_rc
from app import DupeGuru
if sys.platform == 'win32':
import base.cxfreeze_fix
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon(QPixmap(":/logo_me")))

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):
EDITION = 'pe'
LOGO_NAME = 'logo_pe'
NAME = 'dupeGuru Picture Edition'
VERSION = '1.8.5'
VERSION = '1.9.0'
DELTA_COLUMNS = frozenset([2, 5, 6])
def __init__(self):

View File

@@ -85,7 +85,7 @@
<property name="maximumSize">
<size>
<width>16777215</width>
<height>188</height>
<height>190</height>
</size>
</property>
<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"?>
<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">
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
@@ -28,110 +28,65 @@
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
<ROW Directory="gen_py_DIR" Directory_Parent="support_DIR" DefaultDir="gen_py"/>
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
<ROW Directory="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
<ROW Directory="support_DIR" Directory_Parent="APPDIR" DefaultDir="support"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<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="POWRPROF.dll" ComponentId="{65828A9D-101E-433C-82E5-11290FDB7054}" Directory_="APPDIR" Attributes="0" KeyPath="POWRPROF.dll"/>
<ROW Component="PyWinTypes26.dll" ComponentId="{51E80B3A-C753-48CB-B7A4-65610CC49E1F}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
<ROW Component="CurrentVersion" ComponentId="{1A0BFEFD-F9D9-4861-93AC-D9717B7A635E}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
<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="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="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="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="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="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="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_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"/>
</COMPONENT>
<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="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="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="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="11"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="24"/>
<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="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.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="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="9"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="10"/>
<ROW File="block.pyd" Component_="bz2.pyd" FileName="_block.pyd" Attributes="0" SourcePath="dist\_block.pyd" SelfReg="false" Sequence="15"/>
<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._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="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="45"/>
<ROW File="ctypes.pyd" Component_="bz2.pyd" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" 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="46"/>
<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="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="47"/>
<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="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="37"/>
<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="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="50"/>
<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="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="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="52"/>
<ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="6"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="9"/>
<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="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="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="18"/>
<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="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="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="20"/>
<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="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="21"/>
<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="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="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="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="23"/>
<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="16"/>
<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" 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="26"/>
<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="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="28"/>
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="29"/>
<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="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="30"/>
<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="5"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="8"/>
<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="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="33"/>
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="11"/>
<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="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="12"/>
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="19"/>
<ROW File="sqlite3.dll" Component_="sqlite3.dll" FileName="sqlite3.dll" Attributes="0" SourcePath="dist\sqlite3.dll" SelfReg="false" Sequence="13"/>
<ROW File="sqlite3.pyd" Component_="bz2.pyd" FileName="_sqlite3.pyd" Attributes="0" SourcePath="dist\_sqlite3.pyd" SelfReg="false" Sequence="20"/>
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="21"/>
<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="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="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"/>
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="34"/>
</COMPONENT>
<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"/>
@@ -261,6 +216,7 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>

View File

@@ -35,6 +35,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
setchecked(self.useRegexpBox, prefs.use_regexp)
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
self.customCommandEdit.setText(prefs.custom_command)
def save(self):
prefs = self.app.prefs
@@ -45,6 +46,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
prefs.custom_command = unicode(self.customCommandEdit.text())
def resetToDefaults(self):
self.load(preferences.Preferences())

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>366</width>
<height>249</height>
<width>304</width>
<height>263</height>
</rect>
</property>
<property name="windowTitle">
@@ -19,9 +19,9 @@
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
@@ -192,6 +192,16 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Custom Command (arguments: %d for dupe %r for ref):</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="customCommandEdit"/>
</item>
</layout>
</item>
<item>

View File

@@ -14,8 +14,10 @@ import base.dg_rc
from app import DupeGuru
# This is a workaround for a pyinstaller problem where compiled dupeguru can't read tiff files
from PIL import TiffImagePlugin, TiffTags
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
if __name__ == "__main__":
app = QApplication(sys.argv)

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,9 +24,10 @@ class Directories(DirectoriesBase):
return STATE_EXCLUDED
class DupeGuru(DupeGuruBase):
EDITION = 'se'
LOGO_NAME = 'logo_se'
NAME = 'dupeGuru'
VERSION = '2.9.2'
VERSION = '2.10.0'
DELTA_COLUMNS = frozenset([2, 4, 5])
def __init__(self):

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

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT type="Advanced Installer" CreateVersion="4.4.1" version="7.5" modules="professional" RootPath="." Language="en">
<DOCUMENT type="Advanced Installer" CreateVersion="4.4.1" version="7.5.2" modules="professional" RootPath="." Language="en">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
@@ -30,23 +30,19 @@
<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="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="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
<ROW Directory="support_DIR" Directory_Parent="APPDIR" DefaultDir="support"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AIShRegAnswer" ComponentId="{775090B3-2E56-40F5-9DD8-24A2F82DA601}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
<ROW Component="AI_ExePath" ComponentId="{56EC90C1-F906-4F6E-95B2-1876CAA651C2}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="PyWinTypes26.dll" ComponentId="{B664FF8C-C60F-423C-9AC4-26144896E583}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
<ROW Component="CurrentVersion" ComponentId="{398CD484-F093-4CEC-BE84-1BD0DD461942}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
<ROW Component="QtCore4.dll" ComponentId="{F517476C-BC6D-40B6-A063-5A10680ECA05}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
<ROW Component="QtGui4.dll" ComponentId="{4915BAC4-AFB0-42E1-BF2E-D4C3E58D4BEE}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
<ROW Component="bz2.pyd" ComponentId="{E03E8F51-0E8D-40A2-9ED0-A8EA0ED4CD19}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
<ROW Component="dupeGuru.exe" ComponentId="{A8FFC84F-B54B-4883-B9FD-5C545AF0E51C}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru.exe"/>
<ROW Component="init_.py" ComponentId="{7B86D715-9C99-4021-8A3C-437BEA4986BC}" Directory_="gen_py_DIR" Attributes="0" KeyPath="init_.py" Type="0"/>
<ROW Component="python26.dll" ComponentId="{C47E3AEB-FCE1-4A7D-90AF-26D52100756F}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
<ROW Component="pythoncom26.dll" ComponentId="{474C48BA-8C13-428C-B932-49C65A1619FC}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
<ROW Component="qcncodecs4.dll" ComponentId="{1FA15E05-79B4-490E-8BE7-2915DAFECDA0}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
<ROW Component="qgif4.dll" ComponentId="{12390BD7-63E5-4BAE-A760-84D6E47387F3}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
<ROW Component="qico4.dll" ComponentId="{7EC94828-5141-4383-BB9C-89C6AE543237}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
@@ -56,53 +52,45 @@
<ROW Component="qmng4.dll" ComponentId="{11B243B6-A6E5-4282-A58B-5A4F5A2CB253}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
<ROW Component="qsvg4.dll" ComponentId="{D689DDEB-D4E9-4DE0-B32B-85FD25C40726}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
<ROW Component="qsvgicon4.dll" ComponentId="{6EF94FDD-3E92-4886-925F-B264C962E7EF}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{D0CC18F8-1B1D-40E6-BFB3-14F2DE96B6ED}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{0DB9EE4C-922F-42AC-80CC-4EA3CBBB1629}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
<ROW Component="qtiff4.dll" ComponentId="{660F482B-9508-4A26-BC1A-610E84829CA4}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
<ROW Component="qtwcodecs4.dll" ComponentId="{68610953-B652-4340-BBB9-B1EEB3A6AF7A}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
<ROW Component="updater.exe" ComponentId="{CB63C33D-EB1B-420A-8BAA-CD380923F12B}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru.exe AIShRegAnswer python26.dll pythoncom26.dll PyWinTypes26.dll QtCore4.dll QtGui4.dll bz2.pyd qtaccessiblewidgets4.dll qcncodecs4.dll qjpcodecs4.dll qkrcodecs4.dll qtwcodecs4.dll qsvgicon4.dll qgif4.dll qico4.dll qjpeg4.dll qmng4.dll qsvg4.dll qtiff4.dll AI_ExePath qtaccessiblecompatwidgets4.dll init_.py"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru.exe AIShRegAnswer python26.dll QtCore4.dll QtGui4.dll bz2.pyd qtaccessiblewidgets4.dll qcncodecs4.dll qjpcodecs4.dll qkrcodecs4.dll qtwcodecs4.dll qsvgicon4.dll qgif4.dll qico4.dll qjpeg4.dll qmng4.dll qsvg4.dll qtiff4.dll AI_ExePath CurrentVersion"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<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="10"/>
<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="11"/>
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="5"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="6"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="7"/>
<ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="8"/>
<ROW File="dupeGuru.exe" Component_="dupeGuru.exe" FileName="dupeGuru.exe" Attributes="0" SourcePath="dist\dupeGuru.exe" SelfReg="false" Sequence="2"/>
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="31"/>
<ROW File="init_.py" Component_="init_.py" FileName="__init__.py" Attributes="0" SourcePath="dist\support\gen_py\__init__.py" SelfReg="false" Sequence="36"/>
<ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="9"/>
<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="8"/>
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="4"/>
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="5"/>
<ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="6"/>
<ROW File="dupeGuru.exe" Component_="dupeGuru.exe" FileName="dupeGuru.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru.exe" SelfReg="false" Sequence="2"/>
<ROW File="dupeGuru.upx" Component_="bz2.pyd" FileName="dupeGuru.upx" Attributes="0" SourcePath="dist\dupeGuru.upx" SelfReg="false" Sequence="27"/>
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="24"/>
<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="28"/>
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="3"/>
<ROW File="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" 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="13"/>
<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="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.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="14"/>
<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="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="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="21"/>
<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="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="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="35"/>
<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="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="24"/>
<ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="25"/>
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="32"/>
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="33"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="26"/>
<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="10"/>
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="15"/>
<ROW File="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="16"/>
<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="11"/>
<ROW File="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="17"/>
<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="12"/>
<ROW File="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="18"/>
<ROW File="qsvg4.dll" Component_="qsvg4.dll" FileName="qsvg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qsvg4.dll" SelfReg="false" Sequence="19"/>
<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="14"/>
<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="9"/>
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="20"/>
<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="13"/>
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="21"/>
<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="29"/>
<ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="22"/>
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="25"/>
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="26"/>
<ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="23"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="&lt;AI_HOME&gt;updater.exe" SelfReg="false" Sequence="1"/>
<ROW File="win32api.pyd" Component_="bz2.pyd" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="27"/>
<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="28"/>
<ROW File="win32sysloader.pyd" Component_="bz2.pyd" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="34"/>
<ROW File="win32trace.pyd" Component_="bz2.pyd" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="29"/>
<ROW File="win32ui.pyd" Component_="bz2.pyd" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="30"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true" ExeName="dupeguru_win_[|ProductVersion]"/>
@@ -229,10 +217,11 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="Check_for_updates" Directory_="SHORTCUTDIR" Name="Checkf~1|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="Uninstall_dupeGuru" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru" Component_="PyWinTypes26.dll" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Uninstall_dupeGuru" Directory_="SHORTCUTDIR" Name="Uninst~1|Uninstall dupeGuru" Component_="AIShRegAnswer" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="SystemFolder_msiexec.exe" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="dupeGuru" Directory_="DesktopFolder" Name="dupeGuru" Component_="dupeGuru.exe" Target="[#dupeGuru.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="dupeGuru_1" Directory_="SHORTCUTDIR" Name="dupeGuru" Component_="dupeGuru.exe" Target="[#dupeGuru.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
</COMPONENT>

View File

@@ -50,6 +50,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
setchecked(self.ignoreSmallFilesBox, prefs.ignore_small_files)
self.sizeThresholdEdit.setText(unicode(prefs.small_file_threshold))
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
self.customCommandEdit.setText(prefs.custom_command)
def save(self):
prefs = self.app.prefs
@@ -64,6 +65,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
prefs.ignore_small_files = ischecked(self.ignoreSmallFilesBox)
prefs.small_file_threshold = tryint(self.sizeThresholdEdit.text())
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
prefs.custom_command = unicode(self.customCommandEdit.text())
def resetToDefaults(self):
self.load(preferences.Preferences())

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>294</width>
<height>296</height>
<width>308</width>
<height>361</height>
</rect>
</property>
<property name="windowTitle">
@@ -19,9 +19,9 @@
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -170,110 +170,93 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>134</height>
<height>136</height>
</size>
</property>
<widget class="QCheckBox" name="wordWeightingBox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Word weighting</string>
</property>
</widget>
<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">
<string>Match similar words</string>
</property>
</widget>
<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">
<string>Can mix file kind</string>
</property>
</widget>
<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">
<string>Use regular expressions when filtering</string>
</property>
</widget>
<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">
<string>Remove empty folders on delete or move</string>
</property>
</widget>
<widget class="QCheckBox" name="ignoreSmallFilesBox">
<property name="geometry">
<rect>
<x>0</x>
<y>110</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Ignore files smaller than</string>
</property>
</widget>
<widget class="QLineEdit" name="sizeThresholdEdit">
<property name="geometry">
<rect>
<x>170</x>
<y>110</y>
<width>51</width>
<height>22</height>
</rect>
</property>
</widget>
<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">
<string>KB</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="wordWeightingBox">
<property name="text">
<string>Word weighting</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="matchSimilarBox">
<property name="text">
<string>Match similar words</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mixFileKindBox">
<property name="text">
<string>Can mix file kind</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useRegexpBox">
<property name="text">
<string>Use regular expressions when filtering</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="removeEmptyFoldersBox">
<property name="text">
<string>Remove empty folders on delete or move</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="ignoreSmallFilesBox">
<property name="text">
<string>Ignore files smaller than</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="sizeThresholdEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>KB</string>
</property>
</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>
</item>
<item>
@@ -324,6 +307,16 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Custom Command (arguments: %d for dupe, %r for ref):</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="customCommandEdit"/>
</item>
</layout>
</item>
<item>

View File

@@ -14,6 +14,10 @@ import base.dg_rc
from app import DupeGuru
if sys.platform == 'win32':
import base.cxfreeze_fix
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon(QPixmap(":/logo_se")))

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