mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-25 16:11:39 +00:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ae16396a6 | ||
|
|
ef090a5dc5 | ||
|
|
5c0799e82b | ||
|
|
fa2ee01d3f | ||
|
|
d6ba80bd3f | ||
|
|
ee96d5f88c | ||
|
|
e96a917bef | ||
|
|
769b816998 | ||
|
|
ff891c210c | ||
|
|
3ed5e1bf95 | ||
|
|
5bc8581389 | ||
|
|
7346b422d5 | ||
|
|
5c80ac1c74 | ||
|
|
699023992c | ||
|
|
454ce604ad | ||
|
|
1e0f6bfecb | ||
|
|
7f10aa3de2 | ||
|
|
f8764ab85e | ||
|
|
aa8544308e | ||
|
|
31fc70e0f8 | ||
|
|
a16af4560b | ||
|
|
0782ba0dab | ||
|
|
83725667a4 | ||
|
|
f4b3163b04 | ||
|
|
6cd745f429 | ||
|
|
6131f7f6bf | ||
|
|
dd4faa030f | ||
|
|
ab8691f5ac | ||
|
|
77ab073cdb | ||
|
|
87e0011525 | ||
|
|
7af3bb7226 | ||
|
|
5573352ce6 | ||
|
|
e6486e08ab | ||
|
|
48badaa927 | ||
|
|
2f13bf677e | ||
|
|
e63abc1b4b | ||
|
|
88334acdef | ||
|
|
0491aa9f6e | ||
|
|
5be76d7c0f | ||
|
|
3b510389fc | ||
|
|
32d88e9249 | ||
|
|
7b1a1ff4bb | ||
|
|
19beb919d0 | ||
|
|
ba09e8bf4d | ||
|
|
26dd2d0e8e | ||
|
|
69b15d58a2 | ||
|
|
ba68789fb9 | ||
|
|
47a6ceffbc | ||
|
|
b17ca66f73 | ||
|
|
93bc609026 | ||
|
|
3ea51c2e15 |
4
.hgtags
4
.hgtags
@@ -12,3 +12,7 @@ cbcf9c80fee4c908ef2efbf1c143c9e47676c9b2 pe1.8.0
|
|||||||
7b7c5a66ebee4e4b8125330d24fe9ce1a070ff25 se2.9.2
|
7b7c5a66ebee4e4b8125330d24fe9ce1a070ff25 se2.9.2
|
||||||
1cef6d39855f85d4be728646bc78b860e6d4e398 pe1.8.3
|
1cef6d39855f85d4be728646bc78b860e6d4e398 pe1.8.3
|
||||||
90ed56ee602666db2f267f73eac6f824347039b5 me5.7.2
|
90ed56ee602666db2f267f73eac6f824347039b5 me5.7.2
|
||||||
|
4c3cb1e671a333eabde1151c7c6ffb3609cab025 pe1.8.4
|
||||||
|
0a71306434bca51bea9a5d5ae54fe1bf0e4900d8 pe1.8.5
|
||||||
|
556baf4a410779e9bbf43129de133e4c4b26d679 pe1.8.6
|
||||||
|
9149024283959a50fe9a47a5f175b905d1672c19 se2.10.0
|
||||||
|
|||||||
4
README
4
README
@@ -27,6 +27,8 @@ General dependencies
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
- Python 2.6 (http://www.python.org)
|
- Python 2.6 (http://www.python.org)
|
||||||
|
- Send2Trash (http://hg.hardcoded.net/send2trash)
|
||||||
|
- lxml, to read and write XML files. (http://codespeak.net/lxml/)
|
||||||
- Mako, to generate help files. (http://www.makotemplates.org/)
|
- Mako, to generate help files. (http://www.makotemplates.org/)
|
||||||
- PyYaml, for help files and the build system. (http://pyyaml.org/)
|
- PyYaml, for help files and the build system. (http://pyyaml.org/)
|
||||||
- Nose, to run unit tests. (http://somethingaboutorange.com/mrl/projects/nose/)
|
- Nose, to run unit tests. (http://somethingaboutorange.com/mrl/projects/nose/)
|
||||||
@@ -45,7 +47,7 @@ Windows prerequisites
|
|||||||
- Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/)
|
- Visual Studio 2008 (Express is enough) is needed to build C extensions. (http://www.microsoft.com/Express/)
|
||||||
- PyQt 4.6 (http://www.riverbankcomputing.co.uk/news)
|
- PyQt 4.6 (http://www.riverbankcomputing.co.uk/news)
|
||||||
- Python Imaging Library for dupeGuru PE. (http://www.pythonware.com/products/pil/)
|
- Python Imaging Library for dupeGuru PE. (http://www.pythonware.com/products/pil/)
|
||||||
- PyInstaller, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://www.pyinstaller.org/)
|
- cx_Freeze, if you want to build a exe. You don't need it if you just want to run dupeGuru. (http://cx-freeze.sourceforge.net/)
|
||||||
- Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/)
|
- Advanced Installer, if you want to build the installer file. (http://www.advancedinstaller.com/)
|
||||||
|
|
||||||
Building dupeGuru
|
Building dupeGuru
|
||||||
|
|||||||
25
cocoa/base/ProblemDialog.h
Normal file
25
cocoa/base/ProblemDialog.h
Normal 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
|
||||||
40
cocoa/base/ProblemDialog.m
Normal file
40
cocoa/base/ProblemDialog.m
Normal 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
|
||||||
@@ -20,6 +20,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
- (void)clearIgnoreList;
|
- (void)clearIgnoreList;
|
||||||
- (void)purgeIgnoreList;
|
- (void)purgeIgnoreList;
|
||||||
- (NSString *)exportToXHTMLwithColumns:(NSArray *)aColIds;
|
- (NSString *)exportToXHTMLwithColumns:(NSArray *)aColIds;
|
||||||
|
- (void)invokeCommand:(NSString *)cmd;
|
||||||
|
|
||||||
- (NSNumber *)doScan;
|
- (NSNumber *)doScan;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
//Data
|
//Data
|
||||||
- (NSNumber *)getIgnoreListCount;
|
- (NSNumber *)getIgnoreListCount;
|
||||||
- (NSNumber *)getMarkCount;
|
- (NSNumber *)getMarkCount;
|
||||||
- (NSNumber *)getOperationalErrorCount;
|
- (BOOL)scanWasProblematic;
|
||||||
|
|
||||||
//Scanning options
|
//Scanning options
|
||||||
- (void)setMinMatchPercentage:(NSNumber *)percentage;
|
- (void)setMinMatchPercentage:(NSNumber *)percentage;
|
||||||
|
|||||||
14
cocoa/base/PyProblemDialog.h
Normal file
14
cocoa/base/PyProblemDialog.h
Normal 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
|
||||||
@@ -10,6 +10,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
#import "HSOutlineView.h"
|
#import "HSOutlineView.h"
|
||||||
#import "StatsLabel.h"
|
#import "StatsLabel.h"
|
||||||
#import "ResultOutline.h"
|
#import "ResultOutline.h"
|
||||||
|
#import "ProblemDialog.h"
|
||||||
#import "PyDupeGuru.h"
|
#import "PyDupeGuru.h"
|
||||||
|
|
||||||
@interface ResultWindowBase : NSWindowController
|
@interface ResultWindowBase : NSWindowController
|
||||||
@@ -28,6 +29,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
NSWindowController *preferencesPanel;
|
NSWindowController *preferencesPanel;
|
||||||
ResultOutline *outline;
|
ResultOutline *outline;
|
||||||
StatsLabel *statsLabel;
|
StatsLabel *statsLabel;
|
||||||
|
ProblemDialog *problemDialog;
|
||||||
}
|
}
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
- (void)fillColumnsMenu;
|
- (void)fillColumnsMenu;
|
||||||
@@ -46,6 +48,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
- (IBAction)exportToXHTML:(id)sender;
|
- (IBAction)exportToXHTML:(id)sender;
|
||||||
- (IBAction)filter:(id)sender;
|
- (IBAction)filter:(id)sender;
|
||||||
- (IBAction)ignoreSelected:(id)sender;
|
- (IBAction)ignoreSelected:(id)sender;
|
||||||
|
- (IBAction)invokeCustomCommand:(id)sender;
|
||||||
- (IBAction)markAll:(id)sender;
|
- (IBAction)markAll:(id)sender;
|
||||||
- (IBAction)markInvert:(id)sender;
|
- (IBAction)markInvert:(id)sender;
|
||||||
- (IBAction)markNone:(id)sender;
|
- (IBAction)markNone:(id)sender;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
|
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
|
||||||
outline = [[ResultOutline alloc] initWithPyParent:py view:matches];
|
outline = [[ResultOutline alloc] initWithPyParent:py view:matches];
|
||||||
statsLabel = [[StatsLabel alloc] initWithPyParent:py labelView:stats];
|
statsLabel = [[StatsLabel alloc] initWithPyParent:py labelView:stats];
|
||||||
|
problemDialog = [[ProblemDialog alloc] initWithPy:py];
|
||||||
[self initResultColumns];
|
[self initResultColumns];
|
||||||
[self fillColumnsMenu];
|
[self fillColumnsMenu];
|
||||||
[deltaSwitch setSelectedSegment:0];
|
[deltaSwitch setSelectedSegment:0];
|
||||||
@@ -38,6 +39,8 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
{
|
{
|
||||||
[outline release];
|
[outline release];
|
||||||
[preferencesPanel release];
|
[preferencesPanel release];
|
||||||
|
[statsLabel release];
|
||||||
|
[problemDialog release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +200,18 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
[py addSelectedToIgnoreList];
|
[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
|
- (IBAction)markAll:(id)sender
|
||||||
{
|
{
|
||||||
[py markAll];
|
[py markAll];
|
||||||
@@ -349,28 +364,30 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
|
|
||||||
- (void)jobCompleted:(NSNotification *)aNotification
|
- (void)jobCompleted:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
NSInteger r = n2i([py getOperationalErrorCount]);
|
|
||||||
id lastAction = [[ProgressController mainProgressController] jobId];
|
id lastAction = [[ProgressController mainProgressController] jobId];
|
||||||
if ([lastAction isEqualTo:jobCopy]) {
|
if ([lastAction isEqualTo:jobCopy]) {
|
||||||
if (r > 0)
|
if ([py scanWasProblematic]) {
|
||||||
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be copied.",r]];
|
[problemDialog showWindow:self];
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
[Dialogs showMessage:@"All marked files were copied sucessfully."];
|
[Dialogs showMessage:@"All marked files were copied sucessfully."];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([lastAction isEqualTo:jobMove]) {
|
else if ([lastAction isEqualTo:jobMove]) {
|
||||||
if (r > 0)
|
if ([py scanWasProblematic]) {
|
||||||
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be moved. They were kept in the results, and still are marked.",r]];
|
[problemDialog showWindow:self];
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
[Dialogs showMessage:@"All marked files were moved sucessfully."];
|
[Dialogs showMessage:@"All marked files were moved sucessfully."];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([lastAction isEqualTo:jobDelete]) {
|
else if ([lastAction isEqualTo:jobDelete]) {
|
||||||
if (r > 0) {
|
if ([py scanWasProblematic]) {
|
||||||
NSString *msg = @"%d file(s) couldn't be sent to Trash. They were kept in the results, "\
|
[problemDialog showWindow:self];
|
||||||
"and still are marked. See the F.A.Q. section in the help file for details.";
|
|
||||||
[Dialogs showMessage:[NSString stringWithFormat:msg,r]];
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
|
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([lastAction isEqualTo:jobScan]) {
|
else if ([lastAction isEqualTo:jobScan]) {
|
||||||
NSInteger groupCount = [outline intProperty:@"children_count" valueAtPath:nil];
|
NSInteger groupCount = [outline intProperty:@"children_count" valueAtPath:nil];
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||||
<data>
|
<data>
|
||||||
<int key="IBDocument.SystemTarget">1050</int>
|
<int key="IBDocument.SystemTarget">1050</int>
|
||||||
<string key="IBDocument.SystemVersion">10C540</string>
|
<string key="IBDocument.SystemVersion">10D573</string>
|
||||||
<string key="IBDocument.InterfaceBuilderVersion">740</string>
|
<string key="IBDocument.InterfaceBuilderVersion">740</string>
|
||||||
<string key="IBDocument.AppKitVersion">1038.25</string>
|
<string key="IBDocument.AppKitVersion">1038.29</string>
|
||||||
<string key="IBDocument.HIToolboxVersion">458.00</string>
|
<string key="IBDocument.HIToolboxVersion">460.00</string>
|
||||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="NS.object.0">740</string>
|
<string key="NS.object.0">740</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<integer value="598"/>
|
||||||
<integer value="219"/>
|
<integer value="219"/>
|
||||||
<integer value="29"/>
|
|
||||||
</object>
|
</object>
|
||||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
@@ -1146,7 +1146,7 @@
|
|||||||
<object class="NSMenuItem" id="578499792">
|
<object class="NSMenuItem" id="578499792">
|
||||||
<reference key="NSMenu" ref="600111647"/>
|
<reference key="NSMenu" ref="600111647"/>
|
||||||
<string key="NSTitle">Clear Ignore List</string>
|
<string key="NSTitle">Clear Ignore List</string>
|
||||||
<string key="NSKeyEquiv">I</string>
|
<string key="NSKeyEquiv">G</string>
|
||||||
<int key="NSKeyEquivModMask">1048576</int>
|
<int key="NSKeyEquivModMask">1048576</int>
|
||||||
<int key="NSMnemonicLoc">2147483647</int>
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
<reference key="NSOnImage" ref="852972005"/>
|
<reference key="NSOnImage" ref="852972005"/>
|
||||||
@@ -1231,7 +1231,7 @@
|
|||||||
<object class="NSMenuItem" id="904423169">
|
<object class="NSMenuItem" id="904423169">
|
||||||
<reference key="NSMenu" ref="600111647"/>
|
<reference key="NSMenu" ref="600111647"/>
|
||||||
<string key="NSTitle">Add Selected to Ignore List</string>
|
<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="NSKeyEquivModMask">1048576</int>
|
||||||
<int key="NSMnemonicLoc">2147483647</int>
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
<reference key="NSOnImage" ref="852972005"/>
|
<reference key="NSOnImage" ref="852972005"/>
|
||||||
@@ -1275,6 +1275,15 @@
|
|||||||
<reference key="NSOnImage" ref="852972005"/>
|
<reference key="NSOnImage" ref="852972005"/>
|
||||||
<reference key="NSMixedImage" ref="218295580"/>
|
<reference key="NSMixedImage" ref="218295580"/>
|
||||||
</object>
|
</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">
|
<object class="NSMenuItem" id="564101661">
|
||||||
<reference key="NSMenu" ref="600111647"/>
|
<reference key="NSMenu" ref="600111647"/>
|
||||||
<string key="NSTitle">Rename Selected</string>
|
<string key="NSTitle">Rename Selected</string>
|
||||||
@@ -2204,6 +2213,14 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">1176</int>
|
<int key="connectionID">1176</int>
|
||||||
</object>
|
</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>
|
||||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||||
<object class="NSArray" key="orderedObjects">
|
<object class="NSArray" key="orderedObjects">
|
||||||
@@ -2530,6 +2547,7 @@
|
|||||||
<reference ref="564101661"/>
|
<reference ref="564101661"/>
|
||||||
<reference ref="630362403"/>
|
<reference ref="630362403"/>
|
||||||
<reference ref="747820446"/>
|
<reference ref="747820446"/>
|
||||||
|
<reference ref="517397504"/>
|
||||||
</object>
|
</object>
|
||||||
<reference key="parent" ref="528113253"/>
|
<reference key="parent" ref="528113253"/>
|
||||||
</object>
|
</object>
|
||||||
@@ -3066,6 +3084,11 @@
|
|||||||
<reference key="object" ref="747820446"/>
|
<reference key="object" ref="747820446"/>
|
||||||
<reference key="parent" ref="600111647"/>
|
<reference key="parent" ref="600111647"/>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">1177</int>
|
||||||
|
<reference key="object" ref="517397504"/>
|
||||||
|
<reference key="parent" ref="600111647"/>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableDictionary" key="flattenedProperties">
|
<object class="NSMutableDictionary" key="flattenedProperties">
|
||||||
@@ -3117,6 +3140,7 @@
|
|||||||
<string>1171.IBPluginDependency</string>
|
<string>1171.IBPluginDependency</string>
|
||||||
<string>1172.IBPluginDependency</string>
|
<string>1172.IBPluginDependency</string>
|
||||||
<string>1173.IBPluginDependency</string>
|
<string>1173.IBPluginDependency</string>
|
||||||
|
<string>1177.IBPluginDependency</string>
|
||||||
<string>134.IBPluginDependency</string>
|
<string>134.IBPluginDependency</string>
|
||||||
<string>134.ImportedFromIB2</string>
|
<string>134.ImportedFromIB2</string>
|
||||||
<string>136.IBPluginDependency</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>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
@@ -3374,9 +3399,9 @@
|
|||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<boolean value="YES"/>
|
<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>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"/>
|
<boolean value="YES"/>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
@@ -3423,7 +3448,7 @@
|
|||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>{{286, 475}, {361, 293}}</string>
|
<string>{{286, 455}, {361, 313}}</string>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
@@ -3561,7 +3586,7 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<nil key="sourceID"/>
|
<nil key="sourceID"/>
|
||||||
<int key="maxID">1176</int>
|
<int key="maxID">1178</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||||
@@ -3776,8 +3801,17 @@
|
|||||||
<string key="className">ResultWindow</string>
|
<string key="className">ResultWindow</string>
|
||||||
<string key="superclassName">ResultWindowBase</string>
|
<string key="superclassName">ResultWindowBase</string>
|
||||||
<object class="NSMutableDictionary" key="actions">
|
<object class="NSMutableDictionary" key="actions">
|
||||||
<string key="NS.key.0">removeDeadTracks:</string>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<string key="NS.object.0">id</string>
|
<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>
|
||||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||||
<string key="majorKey">IBProjectSource</string>
|
<string key="majorKey">IBProjectSource</string>
|
||||||
@@ -3799,6 +3833,7 @@
|
|||||||
<string>exportToXHTML:</string>
|
<string>exportToXHTML:</string>
|
||||||
<string>filter:</string>
|
<string>filter:</string>
|
||||||
<string>ignoreSelected:</string>
|
<string>ignoreSelected:</string>
|
||||||
|
<string>invokeCustomCommand:</string>
|
||||||
<string>markAll:</string>
|
<string>markAll:</string>
|
||||||
<string>markInvert:</string>
|
<string>markInvert:</string>
|
||||||
<string>markNone:</string>
|
<string>markNone:</string>
|
||||||
@@ -3848,6 +3883,7 @@
|
|||||||
<string>id</string>
|
<string>id</string>
|
||||||
<string>id</string>
|
<string>id</string>
|
||||||
<string>id</string>
|
<string>id</string>
|
||||||
|
<string>id</string>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableDictionary" key="outlets">
|
<object class="NSMutableDictionary" key="outlets">
|
||||||
@@ -4500,7 +4536,7 @@
|
|||||||
<integer value="3000" key="NS.object.0"/>
|
<integer value="3000" key="NS.object.0"/>
|
||||||
</object>
|
</object>
|
||||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
<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>
|
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||||
</data>
|
</data>
|
||||||
</archive>
|
</archive>
|
||||||
|
|||||||
1142
cocoa/base/xib/ProblemDialog.xib
Normal file
1142
cocoa/base/xib/ProblemDialog.xib
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>hsft</string>
|
<string>hsft</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>5.7.2</string>
|
<string>5.8.0</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
<string>MainMenu</string>
|
<string>MainMenu</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ from core_me.app_cocoa import DupeGuruME
|
|||||||
from core.scanner import (SCAN_TYPE_FILENAME, SCAN_TYPE_FIELDS, SCAN_TYPE_FIELDS_NO_ORDER,
|
from core.scanner import (SCAN_TYPE_FILENAME, SCAN_TYPE_FIELDS, SCAN_TYPE_FIELDS_NO_ORDER,
|
||||||
SCAN_TYPE_TAG, SCAN_TYPE_CONTENT, SCAN_TYPE_CONTENT_AUDIO)
|
SCAN_TYPE_TAG, SCAN_TYPE_CONTENT, SCAN_TYPE_CONTENT_AUDIO)
|
||||||
|
|
||||||
# Fix py2app imports which chokes on relative imports
|
# Fix py2app imports which chokes on relative imports and other stuff
|
||||||
from core_me import app_cocoa, data, fs, scanner
|
from core_me import app_cocoa, data, fs, scanner
|
||||||
from hsmedia import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
|
from hsmedia import aiff, flac, genres, id3v1, id3v2, mp4, mpeg, ogg, wma
|
||||||
|
from lxml import etree, _elementpath
|
||||||
|
import gzip
|
||||||
|
|
||||||
class PyDupeGuru(PyDupeGuruBase):
|
class PyDupeGuru(PyDupeGuruBase):
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
CE003CCC11242D00004B0AA7 /* NSTableViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CC511242D00004B0AA7 /* NSTableViewAdditions.m */; };
|
CE003CCC11242D00004B0AA7 /* NSTableViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CC511242D00004B0AA7 /* NSTableViewAdditions.m */; };
|
||||||
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE003CCE11242D2C004B0AA7 /* DirectoryOutline.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 */; };
|
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 */; };
|
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B3D6611243F83009A7A30 /* ResultOutline.m */; };
|
||||||
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
|
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
|
||||||
CE14259F0AFB719300BD5167 /* Sparkle.framework in CopyFiles */ = {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; };
|
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; };
|
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>"; };
|
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; };
|
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; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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; };
|
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; };
|
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 */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
080E96DDFE201D6D7F000001 /* Classes */ = {
|
080E96DDFE201D6D7F000001 /* DGME */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CE381C9509914ACE003581CE /* AppDelegate.h */,
|
CE381C9509914ACE003581CE /* AppDelegate.h */,
|
||||||
CE381C9409914ACE003581CE /* AppDelegate.m */,
|
CE381C9409914ACE003581CE /* AppDelegate.m */,
|
||||||
CE848A1809DD85810004CB44 /* Consts.h */,
|
CE848A1809DD85810004CB44 /* Consts.h */,
|
||||||
CECA899A09DB132E00A3D774 /* DetailsPanel.h */,
|
|
||||||
CECA899B09DB132E00A3D774 /* DetailsPanel.m */,
|
|
||||||
CE68EE6509ABC48000971085 /* DirectoryPanel.h */,
|
CE68EE6509ABC48000971085 /* DirectoryPanel.h */,
|
||||||
CE68EE6609ABC48000971085 /* DirectoryPanel.m */,
|
CE68EE6609ABC48000971085 /* DirectoryPanel.m */,
|
||||||
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */,
|
CEFF18A009A4D387005E6321 /* PyDupeGuru.h */,
|
||||||
CE381C9B09914ADF003581CE /* ResultWindow.h */,
|
CE381C9B09914ADF003581CE /* ResultWindow.h */,
|
||||||
CE381C9A09914ADF003581CE /* ResultWindow.m */,
|
CE381C9A09914ADF003581CE /* ResultWindow.m */,
|
||||||
);
|
);
|
||||||
name = Classes;
|
name = DGME;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||||
@@ -228,7 +234,7 @@
|
|||||||
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
|
29B97314FDCFA39411CA2CEA /* dupeguru */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
080E96DDFE201D6D7F000001 /* Classes */,
|
080E96DDFE201D6D7F000001 /* DGME */,
|
||||||
CE515E140FC6C17900EC695D /* dgbase */,
|
CE515E140FC6C17900EC695D /* dgbase */,
|
||||||
CE515DDD0FC6C09400EC695D /* cocoalib */,
|
CE515DDD0FC6C09400EC695D /* cocoalib */,
|
||||||
29B97315FDCFA39411CA2CEA /* Other Sources */,
|
29B97315FDCFA39411CA2CEA /* Other Sources */,
|
||||||
@@ -277,6 +283,8 @@
|
|||||||
CE003CB411242D00004B0AA7 /* HSGUIController.m */,
|
CE003CB411242D00004B0AA7 /* HSGUIController.m */,
|
||||||
CE003CB511242D00004B0AA7 /* HSOutline.h */,
|
CE003CB511242D00004B0AA7 /* HSOutline.h */,
|
||||||
CE003CB611242D00004B0AA7 /* HSOutline.m */,
|
CE003CB611242D00004B0AA7 /* HSOutline.m */,
|
||||||
|
CE0A0BFE1175A1C000DCA3C6 /* HSTable.h */,
|
||||||
|
CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */,
|
||||||
CE003CB711242D00004B0AA7 /* HSWindowController.h */,
|
CE003CB711242D00004B0AA7 /* HSWindowController.h */,
|
||||||
CE003CB811242D00004B0AA7 /* HSWindowController.m */,
|
CE003CB811242D00004B0AA7 /* HSWindowController.m */,
|
||||||
);
|
);
|
||||||
@@ -289,6 +297,7 @@
|
|||||||
children = (
|
children = (
|
||||||
CE003CBC11242D00004B0AA7 /* PyGUI.h */,
|
CE003CBC11242D00004B0AA7 /* PyGUI.h */,
|
||||||
CE003CBD11242D00004B0AA7 /* PyOutline.h */,
|
CE003CBD11242D00004B0AA7 /* PyOutline.h */,
|
||||||
|
CE0A0C131175A28100DCA3C6 /* PyTable.h */,
|
||||||
);
|
);
|
||||||
name = proxies;
|
name = proxies;
|
||||||
path = ../../cocoalib/proxies;
|
path = ../../cocoalib/proxies;
|
||||||
@@ -315,6 +324,7 @@
|
|||||||
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
|
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
|
||||||
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
|
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
|
||||||
CE900AD1109B238600754048 /* Preferences.xib */,
|
CE900AD1109B238600754048 /* Preferences.xib */,
|
||||||
|
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */,
|
||||||
);
|
);
|
||||||
path = xib;
|
path = xib;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -383,6 +393,8 @@
|
|||||||
CE6032BF0FE6784C007E33FF /* DetailsPanel.m */,
|
CE6032BF0FE6784C007E33FF /* DetailsPanel.m */,
|
||||||
CE515E180FC6C19300EC695D /* DirectoryPanel.h */,
|
CE515E180FC6C19300EC695D /* DirectoryPanel.h */,
|
||||||
CE515E190FC6C19300EC695D /* DirectoryPanel.m */,
|
CE515E190FC6C19300EC695D /* DirectoryPanel.m */,
|
||||||
|
CE0A0C011175A1DE00DCA3C6 /* ProblemDialog.h */,
|
||||||
|
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */,
|
||||||
CE515E1B0FC6C19300EC695D /* ResultWindow.h */,
|
CE515E1B0FC6C19300EC695D /* ResultWindow.h */,
|
||||||
CE515E1C0FC6C19300EC695D /* ResultWindow.m */,
|
CE515E1C0FC6C19300EC695D /* ResultWindow.m */,
|
||||||
CE0B3D6511243F83009A7A30 /* ResultOutline.h */,
|
CE0B3D6511243F83009A7A30 /* ResultOutline.h */,
|
||||||
@@ -391,6 +403,7 @@
|
|||||||
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */,
|
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */,
|
||||||
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */,
|
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */,
|
||||||
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */,
|
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */,
|
||||||
|
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */,
|
||||||
CE0B3D6411243F83009A7A30 /* PyResultTree.h */,
|
CE0B3D6411243F83009A7A30 /* PyResultTree.h */,
|
||||||
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */,
|
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */,
|
||||||
);
|
);
|
||||||
@@ -466,6 +479,7 @@
|
|||||||
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */,
|
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */,
|
||||||
CE4B59C91119919700C06C9E /* progress.xib in Resources */,
|
CE4B59C91119919700C06C9E /* progress.xib in Resources */,
|
||||||
CE4B59CA1119919700C06C9E /* registration.xib in Resources */,
|
CE4B59CA1119919700C06C9E /* registration.xib in Resources */,
|
||||||
|
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -502,6 +516,8 @@
|
|||||||
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */,
|
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */,
|
||||||
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */,
|
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */,
|
||||||
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */,
|
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */,
|
||||||
|
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */,
|
||||||
|
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>hsft</string>
|
<string>hsft</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.8.4</string>
|
<string>1.8.6</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
<string>MainMenu</string>
|
<string>MainMenu</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
||||||
from core_pe import app_cocoa as app_pe_cocoa
|
from core_pe import app_cocoa as app_pe_cocoa
|
||||||
|
|
||||||
# Fix py2app imports which chokes on relative imports
|
# Fix py2app imports which chokes on relative imports and other stuff
|
||||||
from core_pe import block, cache, matchbase, data, _block_osx
|
from core_pe import block, cache, matchbase, data, _block_osx
|
||||||
|
from lxml import etree, _elementpath
|
||||||
|
import gzip
|
||||||
|
|
||||||
class PyDupeGuru(PyDupeGuruBase):
|
class PyDupeGuru(PyDupeGuruBase):
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||||
<data>
|
<data>
|
||||||
<int key="IBDocument.SystemTarget">1050</int>
|
<int key="IBDocument.SystemTarget">1050</int>
|
||||||
<string key="IBDocument.SystemVersion">10B504</string>
|
<string key="IBDocument.SystemVersion">10C540</string>
|
||||||
<string key="IBDocument.InterfaceBuilderVersion">740</string>
|
<string key="IBDocument.InterfaceBuilderVersion">740</string>
|
||||||
<string key="IBDocument.AppKitVersion">1038.2</string>
|
<string key="IBDocument.AppKitVersion">1038.25</string>
|
||||||
<string key="IBDocument.HIToolboxVersion">437.00</string>
|
<string key="IBDocument.HIToolboxVersion">458.00</string>
|
||||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="NS.object.0">740</string>
|
<string key="NS.object.0">740</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<integer value="2"/>
|
<integer value="3"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
@@ -39,6 +39,10 @@
|
|||||||
<string key="NSClassName">NSApplication</string>
|
<string key="NSClassName">NSApplication</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSUserDefaultsController" id="455472712">
|
<object class="NSUserDefaultsController" id="455472712">
|
||||||
|
<object class="NSMutableArray" key="NSDeclaredKeys">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<string>SUEnableAutomaticChecks</string>
|
||||||
|
</object>
|
||||||
<bool key="NSSharedInstance">YES</bool>
|
<bool key="NSSharedInstance">YES</bool>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSWindowTemplate" id="809668081">
|
<object class="NSWindowTemplate" id="809668081">
|
||||||
@@ -411,7 +415,7 @@
|
|||||||
<object class="NSButtonCell" key="NSCell" id="2297113">
|
<object class="NSButtonCell" key="NSCell" id="2297113">
|
||||||
<int key="NSCellFlags">67239424</int>
|
<int key="NSCellFlags">67239424</int>
|
||||||
<int key="NSCellFlags2">0</int>
|
<int key="NSCellFlags2">0</int>
|
||||||
<string key="NSContents">Check for update on startup</string>
|
<string key="NSContents">Automatically check for updates</string>
|
||||||
<reference key="NSSupport" ref="26"/>
|
<reference key="NSSupport" ref="26"/>
|
||||||
<reference key="NSControlView" ref="472028782"/>
|
<reference key="NSControlView" ref="472028782"/>
|
||||||
<int key="NSButtonFlags">1211912703</int>
|
<int key="NSButtonFlags">1211912703</int>
|
||||||
@@ -541,22 +545,6 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">39</int>
|
<int key="connectionID">39</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBConnectionRecord">
|
|
||||||
<object class="IBBindingConnection" key="connection">
|
|
||||||
<string key="label">value: values.SUCheckAtStartup</string>
|
|
||||||
<reference key="source" ref="472028782"/>
|
|
||||||
<reference key="destination" ref="455472712"/>
|
|
||||||
<object class="NSNibBindingConnector" key="connector">
|
|
||||||
<reference key="NSSource" ref="472028782"/>
|
|
||||||
<reference key="NSDestination" ref="455472712"/>
|
|
||||||
<string key="NSLabel">value: values.SUCheckAtStartup</string>
|
|
||||||
<string key="NSBinding">value</string>
|
|
||||||
<string key="NSKeyPath">values.SUCheckAtStartup</string>
|
|
||||||
<int key="NSNibBindingConnectorVersion">2</int>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
<int key="connectionID">40</int>
|
|
||||||
</object>
|
|
||||||
<object class="IBConnectionRecord">
|
<object class="IBConnectionRecord">
|
||||||
<object class="IBActionConnection" key="connection">
|
<object class="IBActionConnection" key="connection">
|
||||||
<string key="label">revertToInitialValues:</string>
|
<string key="label">revertToInitialValues:</string>
|
||||||
@@ -677,6 +665,22 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">51</int>
|
<int key="connectionID">51</int>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBBindingConnection" key="connection">
|
||||||
|
<string key="label">value: values.SUEnableAutomaticChecks</string>
|
||||||
|
<reference key="source" ref="472028782"/>
|
||||||
|
<reference key="destination" ref="455472712"/>
|
||||||
|
<object class="NSNibBindingConnector" key="connector">
|
||||||
|
<reference key="NSSource" ref="472028782"/>
|
||||||
|
<reference key="NSDestination" ref="455472712"/>
|
||||||
|
<string key="NSLabel">value: values.SUEnableAutomaticChecks</string>
|
||||||
|
<string key="NSBinding">value</string>
|
||||||
|
<string key="NSKeyPath">values.SUEnableAutomaticChecks</string>
|
||||||
|
<int key="NSNibBindingConnectorVersion">2</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">58</int>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||||
<object class="NSArray" key="orderedObjects">
|
<object class="NSArray" key="orderedObjects">
|
||||||
@@ -1110,9 +1114,26 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<nil key="sourceID"/>
|
<nil key="sourceID"/>
|
||||||
<int key="maxID">51</int>
|
<int key="maxID">58</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||||
|
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<object class="IBPartialClassDescription">
|
||||||
|
<string key="className">NSObject</string>
|
||||||
|
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||||
|
<string key="majorKey">IBProjectSource</string>
|
||||||
|
<string key="minorKey">../views/HSOutlineView.h</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="IBPartialClassDescription">
|
||||||
|
<string key="className">NSObject</string>
|
||||||
|
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||||
|
<string key="majorKey">IBProjectSource</string>
|
||||||
|
<string key="minorKey">../views/NSTableViewAdditions.h</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
|
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="IBPartialClassDescription">
|
<object class="IBPartialClassDescription">
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>hsft</string>
|
<string>hsft</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2.9.2</string>
|
<string>2.10.0</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
<string>MainMenu</string>
|
<string>MainMenu</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import "../../cocoalib/Outline.h"
|
|
||||||
#import "../base/ResultWindow.h"
|
#import "../base/ResultWindow.h"
|
||||||
#import "DirectoryPanel.h"
|
#import "DirectoryPanel.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
- (void)awakeFromNib
|
- (void)awakeFromNib
|
||||||
{
|
{
|
||||||
[super awakeFromNib];
|
[super awakeFromNib];
|
||||||
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)] retain];
|
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)];
|
||||||
[_deltaColumns removeIndex:3];
|
[deltaColumns removeIndex:3];
|
||||||
|
[outline setDeltaColumns:deltaColumns];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
@@ -56,8 +57,6 @@ http://www.hardcoded.net/licenses/hs_license
|
|||||||
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
|
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes
|
||||||
[_py setSizeThreshold:sizeThreshold];
|
[_py setSizeThreshold:sizeThreshold];
|
||||||
int r = n2i([py doScan]);
|
int r = n2i([py doScan]);
|
||||||
[matches reloadData];
|
|
||||||
[self refreshStats];
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
[[ProgressController mainProgressController] hide];
|
[[ProgressController mainProgressController] hide];
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ from core import scanner
|
|||||||
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
|
||||||
from core_se.app_cocoa import DupeGuru
|
from core_se.app_cocoa import DupeGuru
|
||||||
|
|
||||||
# Fix py2app imports with chokes on relative imports
|
# Fix py2app imports with chokes on relative imports and other stuff
|
||||||
from core_se import fs, data
|
from core_se import fs, data
|
||||||
|
from lxml import etree, _elementpath
|
||||||
|
import gzip
|
||||||
|
|
||||||
class PyDupeGuru(PyDupeGuruBase):
|
class PyDupeGuru(PyDupeGuruBase):
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3A46F9109B212E002ABFD5 /* MainMenu.xib */; };
|
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3A46F9109B212E002ABFD5 /* MainMenu.xib */; };
|
||||||
CE45579B0AE3BC2B005A9546 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
|
CE45579B0AE3BC2B005A9546 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
|
||||||
CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {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 */; };
|
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */; };
|
||||||
CE76FDC4111EE37C006618EA /* HSOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDBF111EE37C006618EA /* HSOutlineView.m */; };
|
CE76FDC4111EE37C006618EA /* HSOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDBF111EE37C006618EA /* HSOutlineView.m */; };
|
||||||
CE76FDC5111EE37C006618EA /* NSIndexPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDC1111EE37C006618EA /* NSIndexPathAdditions.m */; };
|
CE76FDC5111EE37C006618EA /* NSIndexPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDC1111EE37C006618EA /* NSIndexPathAdditions.m */; };
|
||||||
@@ -27,6 +29,9 @@
|
|||||||
CE76FDD4111EE3A7006618EA /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */; };
|
CE76FDD4111EE3A7006618EA /* DirectoryOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */; };
|
||||||
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; };
|
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; };
|
||||||
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
|
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
|
||||||
|
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 */; };
|
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; };
|
||||||
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */; };
|
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */; };
|
||||||
CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; };
|
CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; };
|
||||||
@@ -39,7 +44,6 @@
|
|||||||
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
|
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
|
||||||
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8B0FC9517500CD5728 /* Dialogs.m */; };
|
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8B0FC9517500CD5728 /* Dialogs.m */; };
|
||||||
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */; };
|
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */; };
|
||||||
CEFC7FA00FC9517500CD5728 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8F0FC9517500CD5728 /* Outline.m */; };
|
|
||||||
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F910FC9517500CD5728 /* ProgressController.m */; };
|
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F910FC9517500CD5728 /* ProgressController.m */; };
|
||||||
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F950FC9517500CD5728 /* RecentDirectories.m */; };
|
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F950FC9517500CD5728 /* RecentDirectories.m */; };
|
||||||
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F970FC9517500CD5728 /* RegistrationInterface.m */; };
|
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F970FC9517500CD5728 /* RegistrationInterface.m */; };
|
||||||
@@ -82,6 +86,10 @@
|
|||||||
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
|
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
|
||||||
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../base/xib/MainMenu.xib; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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>"; };
|
CE76FDBE111EE37C006618EA /* HSOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSOutlineView.h; sourceTree = "<group>"; };
|
||||||
@@ -101,6 +109,14 @@
|
|||||||
CE76FDDE111EE42F006618EA /* HSOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSOutline.m; sourceTree = "<group>"; };
|
CE76FDDE111EE42F006618EA /* HSOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSOutline.m; sourceTree = "<group>"; };
|
||||||
CE76FDF5111EE561006618EA /* NSEventAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSEventAdditions.h; path = ../../cocoalib/NSEventAdditions.h; sourceTree = SOURCE_ROOT; };
|
CE76FDF5111EE561006618EA /* NSEventAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSEventAdditions.h; path = ../../cocoalib/NSEventAdditions.h; sourceTree = SOURCE_ROOT; };
|
||||||
CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; };
|
CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; };
|
||||||
|
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; };
|
||||||
|
CE91F212113BC22D0010360B /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
|
||||||
|
CE91F213113BC22D0010360B /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
|
||||||
|
CE91F214113BC22D0010360B /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
|
||||||
CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
|
CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
|
||||||
CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSWindowController.h; sourceTree = "<group>"; };
|
CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSWindowController.h; sourceTree = "<group>"; };
|
||||||
CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSWindowController.m; sourceTree = "<group>"; };
|
CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSWindowController.m; sourceTree = "<group>"; };
|
||||||
@@ -118,8 +134,6 @@
|
|||||||
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
|
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
|
||||||
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
|
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = ../../cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
|
||||||
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; };
|
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSErrorReportWindow.m; path = ../../cocoalib/HSErrorReportWindow.m; sourceTree = SOURCE_ROOT; };
|
||||||
CEFC7F8E0FC9517500CD5728 /* Outline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Outline.h; path = ../../cocoalib/Outline.h; sourceTree = SOURCE_ROOT; };
|
|
||||||
CEFC7F8F0FC9517500CD5728 /* Outline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Outline.m; path = ../../cocoalib/Outline.m; sourceTree = SOURCE_ROOT; };
|
|
||||||
CEFC7F900FC9517500CD5728 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
|
CEFC7F900FC9517500CD5728 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
|
||||||
CEFC7F910FC9517500CD5728 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
|
CEFC7F910FC9517500CD5728 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
|
||||||
CEFC7F920FC9517500CD5728 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
|
CEFC7F920FC9517500CD5728 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
|
||||||
@@ -266,6 +280,7 @@
|
|||||||
CE76FDDE111EE42F006618EA /* HSOutline.m */,
|
CE76FDDE111EE42F006618EA /* HSOutline.m */,
|
||||||
CE76FDC8111EE38E006618EA /* HSGUIController.h */,
|
CE76FDC8111EE38E006618EA /* HSGUIController.h */,
|
||||||
CE76FDC9111EE38E006618EA /* HSGUIController.m */,
|
CE76FDC9111EE38E006618EA /* HSGUIController.m */,
|
||||||
|
CE8C53BB117324CE0011B41F /* HSTable.m */,
|
||||||
);
|
);
|
||||||
name = controllers;
|
name = controllers;
|
||||||
path = ../../cocoalib/controllers;
|
path = ../../cocoalib/controllers;
|
||||||
@@ -276,6 +291,7 @@
|
|||||||
children = (
|
children = (
|
||||||
CE76FDCD111EE38E006618EA /* PyGUI.h */,
|
CE76FDCD111EE38E006618EA /* PyGUI.h */,
|
||||||
CE76FDCE111EE38E006618EA /* PyOutline.h */,
|
CE76FDCE111EE38E006618EA /* PyOutline.h */,
|
||||||
|
CE8C53B61173248F0011B41F /* PyTable.h */,
|
||||||
);
|
);
|
||||||
name = proxies;
|
name = proxies;
|
||||||
path = ../../cocoalib/proxies;
|
path = ../../cocoalib/proxies;
|
||||||
@@ -294,6 +310,7 @@
|
|||||||
CEEFC0CA10943849001F3A39 /* xib */ = {
|
CEEFC0CA10943849001F3A39 /* xib */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CE647E581173026F006D28BA /* ProblemDialog.xib */,
|
||||||
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */,
|
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */,
|
||||||
CEAC6810109B0B7E00B43C85 /* Preferences.xib */,
|
CEAC6810109B0B7E00B43C85 /* Preferences.xib */,
|
||||||
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */,
|
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */,
|
||||||
@@ -326,8 +343,6 @@
|
|||||||
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */,
|
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */,
|
||||||
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */,
|
CEFC7F8C0FC9517500CD5728 /* HSErrorReportWindow.h */,
|
||||||
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */,
|
CEFC7F8D0FC9517500CD5728 /* HSErrorReportWindow.m */,
|
||||||
CEFC7F8E0FC9517500CD5728 /* Outline.h */,
|
|
||||||
CEFC7F8F0FC9517500CD5728 /* Outline.m */,
|
|
||||||
CEFC7F900FC9517500CD5728 /* ProgressController.h */,
|
CEFC7F900FC9517500CD5728 /* ProgressController.h */,
|
||||||
CEFC7F910FC9517500CD5728 /* ProgressController.m */,
|
CEFC7F910FC9517500CD5728 /* ProgressController.m */,
|
||||||
CEFC7F920FC9517500CD5728 /* PyApp.h */,
|
CEFC7F920FC9517500CD5728 /* PyApp.h */,
|
||||||
@@ -347,6 +362,12 @@
|
|||||||
CEFC7FB00FC9518F00CD5728 /* dgbase */ = {
|
CEFC7FB00FC9518F00CD5728 /* dgbase */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CE91F20F113BC22D0010360B /* PyResultTree.h */,
|
||||||
|
CE91F210113BC22D0010360B /* PyStatsLabel.h */,
|
||||||
|
CE91F211113BC22D0010360B /* ResultOutline.h */,
|
||||||
|
CE91F212113BC22D0010360B /* ResultOutline.m */,
|
||||||
|
CE91F213113BC22D0010360B /* StatsLabel.h */,
|
||||||
|
CE91F214113BC22D0010360B /* StatsLabel.m */,
|
||||||
CE76FDD1111EE3A7006618EA /* DirectoryOutline.h */,
|
CE76FDD1111EE3A7006618EA /* DirectoryOutline.h */,
|
||||||
CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */,
|
CE76FDD2111EE3A7006618EA /* DirectoryOutline.m */,
|
||||||
CE76FDD3111EE3A7006618EA /* PyDirectoryOutline.h */,
|
CE76FDD3111EE3A7006618EA /* PyDirectoryOutline.h */,
|
||||||
@@ -361,6 +382,9 @@
|
|||||||
CE6E7407111C997500C350E3 /* PyDetailsPanel.h */,
|
CE6E7407111C997500C350E3 /* PyDetailsPanel.h */,
|
||||||
CEFC7FB70FC951A700CD5728 /* ResultWindow.h */,
|
CEFC7FB70FC951A700CD5728 /* ResultWindow.h */,
|
||||||
CEFC7FB80FC951A700CD5728 /* ResultWindow.m */,
|
CEFC7FB80FC951A700CD5728 /* ResultWindow.m */,
|
||||||
|
CE647E541173024A006D28BA /* ProblemDialog.h */,
|
||||||
|
CE647E551173024A006D28BA /* ProblemDialog.m */,
|
||||||
|
CE647E561173024A006D28BA /* PyProblemDialog.h */,
|
||||||
);
|
);
|
||||||
name = dgbase;
|
name = dgbase;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -426,6 +450,7 @@
|
|||||||
CE19BC6311199231007CCEB0 /* ErrorReportWindow.xib in Resources */,
|
CE19BC6311199231007CCEB0 /* ErrorReportWindow.xib in Resources */,
|
||||||
CE19BC6411199231007CCEB0 /* progress.xib in Resources */,
|
CE19BC6411199231007CCEB0 /* progress.xib in Resources */,
|
||||||
CE19BC6511199231007CCEB0 /* registration.xib in Resources */,
|
CE19BC6511199231007CCEB0 /* registration.xib in Resources */,
|
||||||
|
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -441,7 +466,6 @@
|
|||||||
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */,
|
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */,
|
||||||
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */,
|
CEFC7F9E0FC9517500CD5728 /* Dialogs.m in Sources */,
|
||||||
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */,
|
CEFC7F9F0FC9517500CD5728 /* HSErrorReportWindow.m in Sources */,
|
||||||
CEFC7FA00FC9517500CD5728 /* Outline.m in Sources */,
|
|
||||||
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */,
|
CEFC7FA10FC9517500CD5728 /* ProgressController.m in Sources */,
|
||||||
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */,
|
CEFC7FA20FC9517500CD5728 /* RecentDirectories.m in Sources */,
|
||||||
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */,
|
CEFC7FA30FC9517500CD5728 /* RegistrationInterface.m in Sources */,
|
||||||
@@ -460,6 +484,10 @@
|
|||||||
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */,
|
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */,
|
||||||
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */,
|
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */,
|
||||||
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */,
|
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */,
|
||||||
|
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */,
|
||||||
|
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */,
|
||||||
|
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */,
|
||||||
|
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
86
core/app.py
86
core/app.py
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Created By: Virgil Dupras
|
# Created By: Virgil Dupras
|
||||||
# Created On: 2006/11/11
|
# Created On: 2006/11/11
|
||||||
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
# Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
|
||||||
@@ -12,7 +11,10 @@ from __future__ import unicode_literals
|
|||||||
import os
|
import os
|
||||||
import os.path as op
|
import os.path as op
|
||||||
import logging
|
import logging
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
|
||||||
|
from send2trash import send2trash
|
||||||
from hsutil import io, files
|
from hsutil import io, files
|
||||||
from hsutil.path import Path
|
from hsutil.path import Path
|
||||||
from hsutil.reg import RegistrableApplication, RegistrationRequired
|
from hsutil.reg import RegistrableApplication, RegistrationRequired
|
||||||
@@ -48,7 +50,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self.results = results.Results(data_module)
|
self.results = results.Results(data_module)
|
||||||
self.scanner = scanner.Scanner()
|
self.scanner = scanner.Scanner()
|
||||||
self.action_count = 0
|
self.action_count = 0
|
||||||
self.last_op_error_count = 0
|
|
||||||
self.options = {
|
self.options = {
|
||||||
'escape_filter_regexp': True,
|
'escape_filter_regexp': True,
|
||||||
'clean_empty_dirs': False,
|
'clean_empty_dirs': False,
|
||||||
@@ -70,17 +71,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
return self._do_delete_dupe(dupe)
|
return self._do_delete_dupe(dupe)
|
||||||
|
|
||||||
j.start_job(self.results.mark_count)
|
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):
|
def _do_delete_dupe(self, dupe):
|
||||||
if not io.exists(dupe.path):
|
if not io.exists(dupe.path):
|
||||||
return True
|
return
|
||||||
self._recycle_dupe(dupe)
|
send2trash(unicode(dupe.path)) # Raises OSError when there's a problem
|
||||||
self.clean_empty_dirs(dupe.path[:-1])
|
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):
|
def _do_load(self, j):
|
||||||
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
||||||
@@ -88,8 +85,14 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
j = j.start_subjob([1, 9])
|
j = j.start_subjob([1, 9])
|
||||||
self.results.load_from_xml(op.join(self.appdata, 'last_results.xml'), self._get_file, j)
|
self.results.load_from_xml(op.join(self.appdata, 'last_results.xml'), self._get_file, j)
|
||||||
files = flatten(g[:] for g in self.results.groups)
|
files = flatten(g[:] for g in self.results.groups)
|
||||||
for file in j.iter_with_progress(files, 'Reading metadata %d/%d'):
|
try:
|
||||||
file._read_all_info(attrnames=self.data.METADATA_TO_READ)
|
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):
|
def _get_display_info(self, dupe, group, delta=False):
|
||||||
if (dupe is None) or (group is None):
|
if (dupe is None) or (group is None):
|
||||||
@@ -106,17 +109,16 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
|
|
||||||
def _job_completed(self, jobid):
|
def _job_completed(self, jobid):
|
||||||
# Must be called by subclasses when they detect that an async job is completed.
|
# 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')
|
self.notify('results_changed')
|
||||||
|
elif jobid in (JOB_LOAD, JOB_MOVE, JOB_DELETE):
|
||||||
|
self.notify('results_changed')
|
||||||
|
self.notify('problems_changed')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _open_path(path):
|
def _open_path(path):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _recycle_dupe(dupe):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _reveal_path(path):
|
def _reveal_path(path):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@@ -178,28 +180,23 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
dest_path = dest_path + source_path[1:-1] #Remove drive letter and filename
|
dest_path = dest_path + source_path[1:-1] #Remove drive letter and filename
|
||||||
elif dest_type == 1:
|
elif dest_type == 1:
|
||||||
dest_path = dest_path + source_path[location_path:-1]
|
dest_path = dest_path + source_path[location_path:-1]
|
||||||
try:
|
if not io.exists(dest_path):
|
||||||
if not io.exists(dest_path):
|
io.makedirs(dest_path)
|
||||||
io.makedirs(dest_path)
|
# Raises an EnvironmentError if there's a problem
|
||||||
if copy:
|
if copy:
|
||||||
files.copy(source_path, dest_path)
|
files.copy(source_path, dest_path)
|
||||||
else:
|
else:
|
||||||
files.move(source_path, dest_path)
|
files.move(source_path, dest_path)
|
||||||
self.clean_empty_dirs(source_path[:-1])
|
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
|
|
||||||
|
|
||||||
def copy_or_move_marked(self, copy, destination, recreate_path):
|
def copy_or_move_marked(self, copy, destination, recreate_path):
|
||||||
def do(j):
|
def do(j):
|
||||||
def op(dupe):
|
def op(dupe):
|
||||||
j.add_progress()
|
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)
|
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()
|
self._demo_check()
|
||||||
jobid = JOB_COPY if copy else JOB_MOVE
|
jobid = JOB_COPY if copy else JOB_MOVE
|
||||||
@@ -223,6 +220,31 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
rows.append(row)
|
rows.append(row)
|
||||||
return export.export_to_xhtml(colnames, rows)
|
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):
|
def load(self):
|
||||||
self._start_job(JOB_LOAD, self._do_load)
|
self._start_job(JOB_LOAD, self._do_load)
|
||||||
self.load_ignore_list()
|
self.load_ignore_list()
|
||||||
@@ -279,7 +301,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
self.notify('results_changed_but_keep_selection')
|
self.notify('results_changed_but_keep_selection')
|
||||||
|
|
||||||
def remove_marked(self):
|
def remove_marked(self):
|
||||||
self.results.perform_on_marked(lambda x:True, True)
|
self.results.perform_on_marked(lambda x:None, True)
|
||||||
self.notify('results_changed')
|
self.notify('results_changed')
|
||||||
|
|
||||||
def remove_selected(self):
|
def remove_selected(self):
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ from hsutil import cocoa, job
|
|||||||
from hsutil.cocoa import install_exception_hook
|
from hsutil.cocoa import install_exception_hook
|
||||||
from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
|
from hsutil.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
|
||||||
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
|
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
|
||||||
NSWorkspace, NSWorkspaceRecycleOperation)
|
NSWorkspace)
|
||||||
from hsutil.reg import RegistrationRequired
|
from hsutil.reg import RegistrationRequired
|
||||||
|
|
||||||
from . import app, fs
|
from . import app
|
||||||
|
|
||||||
JOBID2TITLE = {
|
JOBID2TITLE = {
|
||||||
app.JOB_SCAN: "Scanning for duplicates",
|
app.JOB_SCAN: "Scanning for duplicates",
|
||||||
@@ -51,14 +51,6 @@ class DupeGuru(app.DupeGuru):
|
|||||||
def _open_path(path):
|
def _open_path(path):
|
||||||
NSWorkspace.sharedWorkspace().openFile_(unicode(path))
|
NSWorkspace.sharedWorkspace().openFile_(unicode(path))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _recycle_dupe(dupe):
|
|
||||||
# local import because first appkit import takes a lot of memory. we want to avoid it.
|
|
||||||
directory = unicode(dupe.path[:-1])
|
|
||||||
filename = dupe.name
|
|
||||||
result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
|
|
||||||
NSWorkspaceRecycleOperation, directory, '', [filename], None)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _reveal_path(path):
|
def _reveal_path(path):
|
||||||
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(unicode(path), '')
|
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(unicode(path), '')
|
||||||
|
|||||||
@@ -9,10 +9,12 @@
|
|||||||
|
|
||||||
# Common interface for all editions' dg_cocoa unit.
|
# 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.details_panel import DetailsPanel
|
||||||
from .gui.directory_tree import DirectoryTree
|
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.result_tree import ResultTree
|
||||||
from .gui.stats_label import StatsLabel
|
from .gui.stats_label import StatsLabel
|
||||||
|
|
||||||
@@ -93,6 +95,9 @@ class PyDupeGuruBase(PyRegistrable):
|
|||||||
def revealSelected(self):
|
def revealSelected(self):
|
||||||
self.py.reveal_selected()
|
self.py.reveal_selected()
|
||||||
|
|
||||||
|
def invokeCommand_(self, cmd):
|
||||||
|
self.py.invoke_command(cmd)
|
||||||
|
|
||||||
#---Information
|
#---Information
|
||||||
def getIgnoreListCount(self):
|
def getIgnoreListCount(self):
|
||||||
return len(self.py.scanner.ignore_list)
|
return len(self.py.scanner.ignore_list)
|
||||||
@@ -100,8 +105,9 @@ class PyDupeGuruBase(PyRegistrable):
|
|||||||
def getMarkCount(self):
|
def getMarkCount(self):
|
||||||
return self.py.results.mark_count
|
return self.py.results.mark_count
|
||||||
|
|
||||||
def getOperationalErrorCount(self):
|
@signature('i@:')
|
||||||
return self.py.last_op_error_count
|
def scanWasProblematic(self):
|
||||||
|
return bool(self.py.results.problems)
|
||||||
|
|
||||||
#---Properties
|
#---Properties
|
||||||
def setMixFileKind_(self, mix_file_kind):
|
def setMixFileKind_(self, mix_file_kind):
|
||||||
@@ -196,3 +202,13 @@ class PyStatsLabel(PyGUIObject):
|
|||||||
def display(self):
|
def display(self):
|
||||||
return self.py.display
|
return self.py.display
|
||||||
|
|
||||||
|
|
||||||
|
class PyProblemDialog(PyGUIObject):
|
||||||
|
py_class = ProblemDialog
|
||||||
|
|
||||||
|
def revealSelected(self):
|
||||||
|
self.py.reveal_selected_dupe()
|
||||||
|
|
||||||
|
|
||||||
|
class PyProblemTable(PyTable):
|
||||||
|
py_class = ProblemTable
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
import xml.dom.minidom
|
from lxml import etree
|
||||||
|
|
||||||
from hsutil import io
|
from hsutil import io
|
||||||
from hsutil.files import FileOrPath
|
from hsutil.files import FileOrPath
|
||||||
@@ -126,38 +126,38 @@ class Directories(object):
|
|||||||
|
|
||||||
def load_from_file(self, infile):
|
def load_from_file(self, infile):
|
||||||
try:
|
try:
|
||||||
doc = xml.dom.minidom.parse(infile)
|
root = etree.parse(infile).getroot()
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
root_path_nodes = doc.getElementsByTagName('root_directory')
|
for rdn in root.iterchildren('root_directory'):
|
||||||
for rdn in root_path_nodes:
|
attrib = rdn.attrib
|
||||||
if not rdn.getAttributeNode('path'):
|
if 'path' not in attrib:
|
||||||
continue
|
continue
|
||||||
path = rdn.getAttributeNode('path').nodeValue
|
path = attrib['path']
|
||||||
try:
|
try:
|
||||||
self.add_path(Path(path))
|
self.add_path(Path(path))
|
||||||
except (AlreadyThereError, InvalidPathError):
|
except (AlreadyThereError, InvalidPathError):
|
||||||
pass
|
pass
|
||||||
state_nodes = doc.getElementsByTagName('state')
|
for sn in root.iterchildren('state'):
|
||||||
for sn in state_nodes:
|
attrib = sn.attrib
|
||||||
if not (sn.getAttributeNode('path') and sn.getAttributeNode('value')):
|
if not ('path' in attrib and 'value' in attrib):
|
||||||
continue
|
continue
|
||||||
path = sn.getAttributeNode('path').nodeValue
|
path = attrib['path']
|
||||||
state = sn.getAttributeNode('value').nodeValue
|
state = attrib['value']
|
||||||
self.set_state(Path(path), int(state))
|
self.set_state(Path(path), int(state))
|
||||||
|
|
||||||
def save_to_file(self,outfile):
|
def save_to_file(self, outfile):
|
||||||
with FileOrPath(outfile, 'wb') as fp:
|
with FileOrPath(outfile, 'wb') as fp:
|
||||||
doc = xml.dom.minidom.Document()
|
root = etree.Element('directories')
|
||||||
root = doc.appendChild(doc.createElement('directories'))
|
|
||||||
for root_path in self:
|
for root_path in self:
|
||||||
root_path_node = root.appendChild(doc.createElement('root_directory'))
|
root_path_node = etree.SubElement(root, 'root_directory')
|
||||||
root_path_node.setAttribute('path', unicode(root_path).encode('utf-8'))
|
root_path_node.set('path', unicode(root_path))
|
||||||
for path, state in self.states.iteritems():
|
for path, state in self.states.iteritems():
|
||||||
state_node = root.appendChild(doc.createElement('state'))
|
state_node = etree.SubElement(root, 'state')
|
||||||
state_node.setAttribute('path', unicode(path).encode('utf-8'))
|
state_node.set('path', unicode(path))
|
||||||
state_node.setAttribute('value', str(state))
|
state_node.set('value', unicode(state))
|
||||||
doc.writexml(fp, '\t', '\t', '\n', encoding='utf-8')
|
tree = etree.ElementTree(root)
|
||||||
|
tree.write(fp, encoding='utf-8')
|
||||||
|
|
||||||
def set_state(self, path, state):
|
def set_state(self, path, state):
|
||||||
if self.get_state(path) == state:
|
if self.get_state(path) == state:
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ class GUIObject(Listener):
|
|||||||
def marking_changed(self):
|
def marking_changed(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def problems_changed(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def results_changed(self):
|
def results_changed(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
31
core/gui/problem_dialog.py
Normal file
31
core/gui/problem_dialog.py
Normal 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
43
core/gui/problem_table.py
Normal 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)
|
||||||
|
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from hsutil.files import FileOrPath
|
from lxml import etree
|
||||||
|
|
||||||
import xml.dom.minidom
|
from hsutil.files import FileOrPath
|
||||||
|
|
||||||
class IgnoreList(object):
|
class IgnoreList(object):
|
||||||
"""An ignore list implementation that is iterable, filterable and exportable to XML.
|
"""An ignore list implementation that is iterable, filterable and exportable to XML.
|
||||||
@@ -71,45 +71,38 @@ class IgnoreList(object):
|
|||||||
self._ignored[first] = matches
|
self._ignored[first] = matches
|
||||||
self._count += 1
|
self._count += 1
|
||||||
|
|
||||||
def load_from_xml(self,infile):
|
def load_from_xml(self, infile):
|
||||||
"""Loads the ignore list from a XML created with save_to_xml.
|
"""Loads the ignore list from a XML created with save_to_xml.
|
||||||
|
|
||||||
infile can be a file object or a filename.
|
infile can be a file object or a filename.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
doc = xml.dom.minidom.parse(infile)
|
root = etree.parse(infile).getroot()
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
file_nodes = doc.getElementsByTagName('file')
|
for fn in root.iterchildren('file'):
|
||||||
for fn in file_nodes:
|
file_path = fn.get('path')
|
||||||
if not fn.getAttributeNode('path'):
|
if not file_path:
|
||||||
continue
|
continue
|
||||||
file_path = fn.getAttributeNode('path').nodeValue
|
for sfn in fn.iterchildren('file'):
|
||||||
subfile_nodes = fn.getElementsByTagName('file')
|
subfile_path = sfn.get('path')
|
||||||
for sfn in subfile_nodes:
|
if subfile_path:
|
||||||
if not sfn.getAttributeNode('path'):
|
self.Ignore(file_path, subfile_path)
|
||||||
continue
|
|
||||||
subfile_path = sfn.getAttributeNode('path').nodeValue
|
|
||||||
self.Ignore(file_path,subfile_path)
|
|
||||||
|
|
||||||
def save_to_xml(self,outfile):
|
def save_to_xml(self, outfile):
|
||||||
"""Create a XML file that can be used by load_from_xml.
|
"""Create a XML file that can be used by load_from_xml.
|
||||||
|
|
||||||
outfile can be a file object or a filename.
|
outfile can be a file object or a filename.
|
||||||
"""
|
"""
|
||||||
doc = xml.dom.minidom.Document()
|
root = etree.Element('ignore_list')
|
||||||
root = doc.appendChild(doc.createElement('ignore_list'))
|
for filename, subfiles in self._ignored.items():
|
||||||
for file,subfiles in self._ignored.items():
|
file_node = etree.SubElement(root, 'file')
|
||||||
file_node = root.appendChild(doc.createElement('file'))
|
file_node.set('path', filename)
|
||||||
if isinstance(file,unicode):
|
for subfilename in subfiles:
|
||||||
file = file.encode('utf-8')
|
subfile_node = etree.SubElement(file_node, 'file')
|
||||||
file_node.setAttribute('path',file)
|
subfile_node.set('path', subfilename)
|
||||||
for subfile in subfiles:
|
tree = etree.ElementTree(root)
|
||||||
subfile_node = file_node.appendChild(doc.createElement('file'))
|
|
||||||
if isinstance(subfile,unicode):
|
|
||||||
subfile = subfile.encode('utf-8')
|
|
||||||
subfile_node.setAttribute('path',subfile)
|
|
||||||
with FileOrPath(outfile, 'wb') as fp:
|
with FileOrPath(outfile, 'wb') as fp:
|
||||||
doc.writexml(fp,'\t','\t','\n',encoding='utf-8')
|
tree.write(fp, encoding='utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
208
core/results.py
208
core/results.py
@@ -8,16 +8,14 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from xml.sax import handler, make_parser, SAXException
|
from lxml import etree
|
||||||
from xml.sax.saxutils import XMLGenerator
|
|
||||||
from xml.sax.xmlreader import AttributesImpl
|
|
||||||
|
|
||||||
from . import engine
|
from . import engine
|
||||||
from hsutil.job import nulljob
|
from hsutil.job import nulljob
|
||||||
from hsutil.markable import Markable
|
from hsutil.markable import Markable
|
||||||
from hsutil.misc import flatten, cond, nonone
|
from hsutil.misc import flatten, nonone
|
||||||
from hsutil.str import format_size
|
from hsutil.str import format_size
|
||||||
from hsutil.files import open_if_filename
|
from hsutil.files import FileOrPath
|
||||||
|
|
||||||
class Results(Markable):
|
class Results(Markable):
|
||||||
#---Override
|
#---Override
|
||||||
@@ -34,6 +32,7 @@ class Results(Markable):
|
|||||||
self.__recalculate_stats()
|
self.__recalculate_stats()
|
||||||
self.__marked_size = 0
|
self.__marked_size = 0
|
||||||
self.data = data_module
|
self.data = data_module
|
||||||
|
self.problems = [] # (dupe, error_msg)
|
||||||
|
|
||||||
def _did_mark(self, dupe):
|
def _did_mark(self, dupe):
|
||||||
self.__marked_size += dupe.size
|
self.__marked_size += dupe.size
|
||||||
@@ -148,7 +147,7 @@ class Results(Markable):
|
|||||||
self.__filters.append(filter_str)
|
self.__filters.append(filter_str)
|
||||||
if self.__filtered_dupes is None:
|
if self.__filtered_dupes is None:
|
||||||
self.__filtered_dupes = flatten(g[:] for g in self.groups)
|
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()
|
filtered_groups = set()
|
||||||
for dupe in self.__filtered_dupes:
|
for dupe in self.__filtered_dupes:
|
||||||
filtered_groups.add(self.get_group_of_duplicate(dupe))
|
filtered_groups.add(self.get_group_of_duplicate(dupe))
|
||||||
@@ -168,42 +167,54 @@ class Results(Markable):
|
|||||||
is_markable = _is_markable
|
is_markable = _is_markable
|
||||||
|
|
||||||
def load_from_xml(self, infile, get_file, j=nulljob):
|
def load_from_xml(self, infile, get_file, j=nulljob):
|
||||||
|
def do_match(ref_file, other_files, group):
|
||||||
|
if not other_files:
|
||||||
|
return
|
||||||
|
for other_file in other_files:
|
||||||
|
group.add_match(engine.get_match(ref_file, other_file))
|
||||||
|
do_match(other_files[0], other_files[1:], group)
|
||||||
|
|
||||||
self.apply_filter(None)
|
self.apply_filter(None)
|
||||||
handler = _ResultsHandler(get_file)
|
|
||||||
try:
|
try:
|
||||||
parser = make_parser()
|
root = etree.parse(infile).getroot()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# This special handling is to try to figure out the cause of #47
|
|
||||||
# We don't silently return, because we want the user to send error report.
|
|
||||||
logging.exception(e)
|
|
||||||
try:
|
|
||||||
import xml.parsers.expat
|
|
||||||
logging.warning('importing xml.parsers.expat went ok, WTF?')
|
|
||||||
except Exception as e:
|
|
||||||
# This log should give a little more details about the cause of this all
|
|
||||||
logging.exception(e)
|
|
||||||
raise
|
|
||||||
raise
|
|
||||||
parser.setContentHandler(handler)
|
|
||||||
try:
|
|
||||||
infile, must_close = open_if_filename(infile)
|
|
||||||
except IOError:
|
|
||||||
return
|
return
|
||||||
BUFSIZE = 1024 * 1024 # 1mb buffer
|
group_elems = list(root.iterchildren('group'))
|
||||||
infile.seek(0, 2)
|
groups = []
|
||||||
j.start_job(infile.tell() // BUFSIZE)
|
marked = set()
|
||||||
infile.seek(0, 0)
|
for group_elem in j.iter_with_progress(group_elems, every=100):
|
||||||
try:
|
group = engine.Group()
|
||||||
while True:
|
dupes = []
|
||||||
data = infile.read(BUFSIZE)
|
for file_elem in group_elem.iterchildren('file'):
|
||||||
if not data:
|
path = file_elem.get('path')
|
||||||
break
|
words = file_elem.get('words', '')
|
||||||
parser.feed(data)
|
if not path:
|
||||||
j.add_progress()
|
continue
|
||||||
except SAXException:
|
file = get_file(path)
|
||||||
return
|
if file is None:
|
||||||
self.groups = handler.groups
|
continue
|
||||||
for dupe_file in handler.marked:
|
file.words = words.split(',')
|
||||||
|
file.is_ref = file_elem.get('is_ref') == 'y'
|
||||||
|
dupes.append(file)
|
||||||
|
if file_elem.get('marked') == 'y':
|
||||||
|
marked.add(file)
|
||||||
|
for match_elem in group_elem.iterchildren('match'):
|
||||||
|
try:
|
||||||
|
attrs = match_elem.attrib
|
||||||
|
first_file = dupes[int(attrs['first'])]
|
||||||
|
second_file = dupes[int(attrs['second'])]
|
||||||
|
percentage = int(attrs['percentage'])
|
||||||
|
group.add_match(engine.Match(first_file, second_file, percentage))
|
||||||
|
except (IndexError, KeyError, ValueError): # Covers missing attr, non-int values and indexes out of bounds
|
||||||
|
pass
|
||||||
|
if (not group.matches) and (len(dupes) >= 2):
|
||||||
|
do_match(dupes[0], dupes[1:], group)
|
||||||
|
group.prioritize(lambda x: dupes.index(x))
|
||||||
|
if len(group):
|
||||||
|
groups.append(group)
|
||||||
|
j.add_progress()
|
||||||
|
self.groups = groups
|
||||||
|
for dupe_file in marked:
|
||||||
self.mark(dupe_file)
|
self.mark(dupe_file)
|
||||||
|
|
||||||
def make_ref(self, dupe):
|
def make_ref(self, dupe):
|
||||||
@@ -220,17 +231,22 @@ class Results(Markable):
|
|||||||
self.__dupes = None
|
self.__dupes = None
|
||||||
|
|
||||||
def perform_on_marked(self, func, remove_from_results):
|
def perform_on_marked(self, func, remove_from_results):
|
||||||
problems = []
|
# Performs `func` on all marked dupes. If an EnvironmentError is raised during the call,
|
||||||
for d in self.dupes:
|
# the problematic dupe is added to self.problems.
|
||||||
if self.is_marked(d) and (not func(d)):
|
self.problems = []
|
||||||
problems.append(d)
|
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:
|
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.remove_duplicates(to_remove)
|
||||||
self.mark_none()
|
self.mark_none()
|
||||||
for d in problems:
|
for dupe, _ in self.problems:
|
||||||
self.mark(d)
|
self.mark(dupe)
|
||||||
return len(problems)
|
|
||||||
|
|
||||||
def remove_duplicates(self, dupes):
|
def remove_duplicates(self, dupes):
|
||||||
'''Remove 'dupes' from their respective group, and remove the group is it ends up empty.
|
'''Remove 'dupes' from their respective group, and remove the group is it ends up empty.
|
||||||
@@ -256,13 +272,10 @@ class Results(Markable):
|
|||||||
|
|
||||||
def save_to_xml(self, outfile):
|
def save_to_xml(self, outfile):
|
||||||
self.apply_filter(None)
|
self.apply_filter(None)
|
||||||
outfile, must_close = open_if_filename(outfile, 'wb')
|
root = etree.Element('results')
|
||||||
writer = XMLGenerator(outfile, 'utf-8')
|
# writer = XMLGenerator(outfile, 'utf-8')
|
||||||
writer.startDocument()
|
|
||||||
empty_attrs = AttributesImpl({})
|
|
||||||
writer.startElement('results', empty_attrs)
|
|
||||||
for g in self.groups:
|
for g in self.groups:
|
||||||
writer.startElement('group', empty_attrs)
|
group_elem = etree.SubElement(root, 'group')
|
||||||
dupe2index = {}
|
dupe2index = {}
|
||||||
for index, d in enumerate(g):
|
for index, d in enumerate(g):
|
||||||
dupe2index[d] = index
|
dupe2index[d] = index
|
||||||
@@ -270,27 +283,19 @@ class Results(Markable):
|
|||||||
words = engine.unpack_fields(d.words)
|
words = engine.unpack_fields(d.words)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
words = ()
|
words = ()
|
||||||
attrs = AttributesImpl({
|
file_elem = etree.SubElement(group_elem, 'file')
|
||||||
'path': unicode(d.path),
|
file_elem.set('path', unicode(d.path))
|
||||||
'is_ref': cond(d.is_ref, 'y', 'n'),
|
file_elem.set('is_ref', ('y' if d.is_ref else 'n'))
|
||||||
'words': ','.join(words),
|
file_elem.set('words', ','.join(words))
|
||||||
'marked': cond(self.is_marked(d), 'y', 'n')
|
file_elem.set('marked', ('y' if self.is_marked(d) else 'n'))
|
||||||
})
|
|
||||||
writer.startElement('file', attrs)
|
|
||||||
writer.endElement('file')
|
|
||||||
for match in g.matches:
|
for match in g.matches:
|
||||||
attrs = AttributesImpl({
|
match_elem = etree.SubElement(group_elem, 'match')
|
||||||
'first': str(dupe2index[match.first]),
|
match_elem.set('first', unicode(dupe2index[match.first]))
|
||||||
'second': str(dupe2index[match.second]),
|
match_elem.set('second', unicode(dupe2index[match.second]))
|
||||||
'percentage': str(int(match.percentage)),
|
match_elem.set('percentage', unicode(int(match.percentage)))
|
||||||
})
|
tree = etree.ElementTree(root)
|
||||||
writer.startElement('match', attrs)
|
with FileOrPath(outfile, 'wb') as fp:
|
||||||
writer.endElement('match')
|
tree.write(fp, encoding='utf-8')
|
||||||
writer.endElement('group')
|
|
||||||
writer.endElement('results')
|
|
||||||
writer.endDocument()
|
|
||||||
if must_close:
|
|
||||||
outfile.close()
|
|
||||||
|
|
||||||
def sort_dupes(self, key, asc=True, delta=False):
|
def sort_dupes(self, key, asc=True, delta=False):
|
||||||
if not self.__dupes:
|
if not self.__dupes:
|
||||||
@@ -310,60 +315,3 @@ class Results(Markable):
|
|||||||
dupes = property(__get_dupe_list)
|
dupes = property(__get_dupe_list)
|
||||||
groups = property(__get_groups, __set_groups)
|
groups = property(__get_groups, __set_groups)
|
||||||
stat_line = property(__get_stat_line)
|
stat_line = property(__get_stat_line)
|
||||||
|
|
||||||
class _ResultsHandler(handler.ContentHandler):
|
|
||||||
def __init__(self, get_file):
|
|
||||||
self.group = None
|
|
||||||
self.dupes = None
|
|
||||||
self.marked = set()
|
|
||||||
self.groups = []
|
|
||||||
self.get_file = get_file
|
|
||||||
|
|
||||||
def startElement(self, name, attrs):
|
|
||||||
if name == 'group':
|
|
||||||
self.group = engine.Group()
|
|
||||||
self.dupes = []
|
|
||||||
return
|
|
||||||
if (name == 'file') and (self.group is not None):
|
|
||||||
if not (('path' in attrs) and ('words' in attrs)):
|
|
||||||
return
|
|
||||||
path = attrs['path']
|
|
||||||
file = self.get_file(path)
|
|
||||||
if file is None:
|
|
||||||
return
|
|
||||||
file.words = attrs['words'].split(',')
|
|
||||||
file.is_ref = attrs.get('is_ref') == 'y'
|
|
||||||
self.dupes.append(file)
|
|
||||||
if attrs.get('marked') == 'y':
|
|
||||||
self.marked.add(file)
|
|
||||||
if (name == 'match') and (self.group is not None):
|
|
||||||
try:
|
|
||||||
first_file = self.dupes[int(attrs['first'])]
|
|
||||||
second_file = self.dupes[int(attrs['second'])]
|
|
||||||
percentage = int(attrs['percentage'])
|
|
||||||
self.group.add_match(engine.Match(first_file, second_file, percentage))
|
|
||||||
except (IndexError, KeyError, ValueError): # Covers missing attr, non-int values and indexes out of bounds
|
|
||||||
pass
|
|
||||||
|
|
||||||
def endElement(self, name):
|
|
||||||
def do_match(ref_file, other_files, group):
|
|
||||||
if not other_files:
|
|
||||||
return
|
|
||||||
for other_file in other_files:
|
|
||||||
group.add_match(engine.get_match(ref_file, other_file))
|
|
||||||
do_match(other_files[0], other_files[1:], group)
|
|
||||||
|
|
||||||
if name == 'group':
|
|
||||||
group = self.group
|
|
||||||
self.group = None
|
|
||||||
dupes = self.dupes
|
|
||||||
self.dupes = []
|
|
||||||
if group is None:
|
|
||||||
return
|
|
||||||
if len(dupes) < 2:
|
|
||||||
return
|
|
||||||
if not group.matches: # <match> elements not present, do it manually, without %
|
|
||||||
do_match(dupes[0], dupes[1:], group)
|
|
||||||
group.prioritize(lambda x: dupes.index(x))
|
|
||||||
self.groups.append(group)
|
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ class TCDupeGuruWithResults(TestCase):
|
|||||||
self.rtree.selected_paths = paths
|
self.rtree.selected_paths = paths
|
||||||
self.app.remove_selected()
|
self.app.remove_selected()
|
||||||
# The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos.
|
# The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos.
|
||||||
eq_(self.rtree.selected_paths, [[0]]) # no exception
|
eq_(self.rtree.selected_paths, [[0, 0]]) # no exception
|
||||||
|
|
||||||
def test_selectResultNodePaths(self):
|
def test_selectResultNodePaths(self):
|
||||||
app = self.app
|
app = self.app
|
||||||
@@ -366,10 +366,7 @@ class TCDupeGuruWithResults(TestCase):
|
|||||||
app = self.app
|
app = self.app
|
||||||
self.rtree.selected_paths = [[0, 0], [1, 0]]
|
self.rtree.selected_paths = [[0, 0], [1, 0]]
|
||||||
app.remove_selected()
|
app.remove_selected()
|
||||||
eq_(len(app.results.dupes), 1)
|
eq_(len(app.results.dupes), 1) # the first path is now selected
|
||||||
app.remove_selected()
|
|
||||||
eq_(len(app.results.dupes), 1)
|
|
||||||
self.rtree.selected_path = [0, 0]
|
|
||||||
app.remove_selected()
|
app.remove_selected()
|
||||||
eq_(len(app.results.dupes), 0)
|
eq_(len(app.results.dupes), 0)
|
||||||
|
|
||||||
|
|||||||
@@ -229,10 +229,9 @@ class TCbuild_word_dict(TestCase):
|
|||||||
self.log = []
|
self.log = []
|
||||||
s = "foo bar"
|
s = "foo bar"
|
||||||
build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
|
build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
|
||||||
|
# We don't have intermediate log because iter_with_progress is called with every > 1
|
||||||
self.assertEqual(0,self.log[0])
|
self.assertEqual(0,self.log[0])
|
||||||
self.assertEqual(33,self.log[1])
|
self.assertEqual(100,self.log[1])
|
||||||
self.assertEqual(66,self.log[2])
|
|
||||||
self.assertEqual(100,self.log[3])
|
|
||||||
|
|
||||||
|
|
||||||
class TCmerge_similar_words(TestCase):
|
class TCmerge_similar_words(TestCase):
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import xml.dom.minidom
|
from lxml import etree
|
||||||
|
|
||||||
from nose.tools import eq_
|
from nose.tools import eq_
|
||||||
|
|
||||||
@@ -62,26 +62,25 @@ def test_save_to_xml():
|
|||||||
f = cStringIO.StringIO()
|
f = cStringIO.StringIO()
|
||||||
il.save_to_xml(f)
|
il.save_to_xml(f)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
doc = xml.dom.minidom.parse(f)
|
doc = etree.parse(f)
|
||||||
root = doc.documentElement
|
root = doc.getroot()
|
||||||
eq_('ignore_list',root.nodeName)
|
eq_(root.tag, 'ignore_list')
|
||||||
children = [c for c in root.childNodes if c.localName]
|
eq_(len(root), 2)
|
||||||
eq_(2,len(children))
|
eq_(len([c for c in root if c.tag == 'file']), 2)
|
||||||
eq_(2,len([c for c in children if c.nodeName == 'file']))
|
f1, f2 = root[:]
|
||||||
f1,f2 = children
|
subchildren = [c for c in f1 if c.tag == 'file'] + [c for c in f2 if c.tag == 'file']
|
||||||
subchildren = [c for c in f1.childNodes if c.localName == 'file'] +\
|
eq_(len(subchildren), 3)
|
||||||
[c for c in f2.childNodes if c.localName == 'file']
|
|
||||||
eq_(3,len(subchildren))
|
|
||||||
|
|
||||||
def test_SaveThenLoad():
|
def test_SaveThenLoad():
|
||||||
il = IgnoreList()
|
il = IgnoreList()
|
||||||
il.Ignore('foo','bar')
|
il.Ignore('foo', 'bar')
|
||||||
il.Ignore('foo','bleh')
|
il.Ignore('foo', 'bleh')
|
||||||
il.Ignore('bleh','bar')
|
il.Ignore('bleh', 'bar')
|
||||||
il.Ignore(u'\u00e9','bar')
|
il.Ignore(u'\u00e9', 'bar')
|
||||||
f = cStringIO.StringIO()
|
f = cStringIO.StringIO()
|
||||||
il.save_to_xml(f)
|
il.save_to_xml(f)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
f.seek(0)
|
||||||
il = IgnoreList()
|
il = IgnoreList()
|
||||||
il.load_from_xml(f)
|
il.load_from_xml(f)
|
||||||
eq_(4,len(il))
|
eq_(4,len(il))
|
||||||
@@ -129,9 +128,9 @@ def test_filter():
|
|||||||
assert not il.AreIgnored('foo','bar')
|
assert not il.AreIgnored('foo','bar')
|
||||||
assert il.AreIgnored('bar','baz')
|
assert il.AreIgnored('bar','baz')
|
||||||
|
|
||||||
def test_save_with_non_ascii_non_unicode_items():
|
def test_save_with_non_ascii_items():
|
||||||
il = IgnoreList()
|
il = IgnoreList()
|
||||||
il.Ignore('\xac','\xbf')
|
il.Ignore(u'\xac', u'\xbf')
|
||||||
f = cStringIO.StringIO()
|
f = cStringIO.StringIO()
|
||||||
try:
|
try:
|
||||||
il.save_to_xml(f)
|
il.save_to_xml(f)
|
||||||
|
|||||||
@@ -7,18 +7,19 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
import unittest
|
|
||||||
import StringIO
|
import StringIO
|
||||||
import xml.dom.minidom
|
|
||||||
import os.path as op
|
import os.path as op
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
from nose.tools import eq_
|
||||||
|
|
||||||
from hsutil.path import Path
|
from hsutil.path import Path
|
||||||
from hsutil.testcase import TestCase
|
from hsutil.testcase import TestCase
|
||||||
from hsutil.misc import first
|
from hsutil.misc import first
|
||||||
|
|
||||||
from . import engine_test, data
|
from . import engine_test, data
|
||||||
from .. import engine
|
from .. import engine
|
||||||
from ..results import *
|
from ..results import Results
|
||||||
|
|
||||||
class NamedObject(engine_test.NamedObject):
|
class NamedObject(engine_test.NamedObject):
|
||||||
path = property(lambda x:Path('basepath') + x.name)
|
path = property(lambda x:Path('basepath') + x.name)
|
||||||
@@ -65,9 +66,9 @@ class TCResultsEmpty(TestCase):
|
|||||||
f = StringIO.StringIO()
|
f = StringIO.StringIO()
|
||||||
self.results.save_to_xml(f)
|
self.results.save_to_xml(f)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
doc = xml.dom.minidom.parse(f)
|
doc = etree.parse(f)
|
||||||
root = doc.documentElement
|
root = doc.getroot()
|
||||||
self.assertEqual('results',root.nodeName)
|
self.assertEqual('results', root.tag)
|
||||||
|
|
||||||
|
|
||||||
class TCResultsWithSomeGroups(TestCase):
|
class TCResultsWithSomeGroups(TestCase):
|
||||||
@@ -253,18 +254,23 @@ class TCResultsMarkings(TestCase):
|
|||||||
def test_perform_on_marked_with_problems(self):
|
def test_perform_on_marked_with_problems(self):
|
||||||
def log_object(o):
|
def log_object(o):
|
||||||
log.append(o)
|
log.append(o)
|
||||||
return o is not self.objects[1]
|
if o is self.objects[1]:
|
||||||
|
raise EnvironmentError('foobar')
|
||||||
|
|
||||||
log = []
|
log = []
|
||||||
self.results.mark_all()
|
self.results.mark_all()
|
||||||
self.assert_(self.results.is_marked(self.objects[1]))
|
assert self.results.is_marked(self.objects[1])
|
||||||
self.assertEqual(1,self.results.perform_on_marked(log_object, True))
|
self.results.perform_on_marked(log_object, True)
|
||||||
self.assertEqual(3,len(log))
|
eq_(len(log), 3)
|
||||||
self.assertEqual(1,len(self.results.groups))
|
eq_(len(self.results.groups), 1)
|
||||||
self.assertEqual(2,len(self.results.groups[0]))
|
eq_(len(self.results.groups[0]), 2)
|
||||||
self.assert_(self.objects[1] in self.results.groups[0])
|
assert self.objects[1] in self.results.groups[0]
|
||||||
self.assert_(not self.results.is_marked(self.objects[2]))
|
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])
|
||||||
|
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 test_perform_on_marked_with_ref(self):
|
||||||
def log_object(o):
|
def log_object(o):
|
||||||
@@ -321,16 +327,16 @@ class TCResultsMarkings(TestCase):
|
|||||||
f = StringIO.StringIO()
|
f = StringIO.StringIO()
|
||||||
self.results.save_to_xml(f)
|
self.results.save_to_xml(f)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
doc = xml.dom.minidom.parse(f)
|
doc = etree.parse(f)
|
||||||
root = doc.documentElement
|
root = doc.getroot()
|
||||||
g1,g2 = root.getElementsByTagName('group')
|
g1, g2 = root.iterchildren('group')
|
||||||
d1,d2,d3 = g1.getElementsByTagName('file')
|
d1, d2, d3 = g1.iterchildren('file')
|
||||||
self.assertEqual('n',d1.getAttributeNode('marked').nodeValue)
|
self.assertEqual('n', d1.get('marked'))
|
||||||
self.assertEqual('n',d2.getAttributeNode('marked').nodeValue)
|
self.assertEqual('n', d2.get('marked'))
|
||||||
self.assertEqual('y',d3.getAttributeNode('marked').nodeValue)
|
self.assertEqual('y', d3.get('marked'))
|
||||||
d1,d2 = g2.getElementsByTagName('file')
|
d1, d2 = g2.iterchildren('file')
|
||||||
self.assertEqual('n',d1.getAttributeNode('marked').nodeValue)
|
self.assertEqual('n', d1.get('marked'))
|
||||||
self.assertEqual('y',d2.getAttributeNode('marked').nodeValue)
|
self.assertEqual('y', d2.get('marked'))
|
||||||
|
|
||||||
def test_LoadXML(self):
|
def test_LoadXML(self):
|
||||||
def get_file(path):
|
def get_file(path):
|
||||||
@@ -366,38 +372,35 @@ class TCResultsXML(TestCase):
|
|||||||
f = StringIO.StringIO()
|
f = StringIO.StringIO()
|
||||||
self.results.save_to_xml(f)
|
self.results.save_to_xml(f)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
doc = xml.dom.minidom.parse(f)
|
doc = etree.parse(f)
|
||||||
root = doc.documentElement
|
root = doc.getroot()
|
||||||
self.assertEqual('results',root.nodeName)
|
self.assertEqual('results', root.tag)
|
||||||
children = [c for c in root.childNodes if c.localName]
|
self.assertEqual(2, len(root))
|
||||||
self.assertEqual(2,len(children))
|
self.assertEqual(2, len([c for c in root if c.tag == 'group']))
|
||||||
self.assertEqual(2,len([c for c in children if c.nodeName == 'group']))
|
g1, g2 = root
|
||||||
g1,g2 = children
|
self.assertEqual(6,len(g1))
|
||||||
children = [c for c in g1.childNodes if c.localName]
|
self.assertEqual(3,len([c for c in g1 if c.tag == 'file']))
|
||||||
self.assertEqual(6,len(children))
|
self.assertEqual(3,len([c for c in g1 if c.tag == 'match']))
|
||||||
self.assertEqual(3,len([c for c in children if c.nodeName == 'file']))
|
d1, d2, d3 = [c for c in g1 if c.tag == 'file']
|
||||||
self.assertEqual(3,len([c for c in children if c.nodeName == 'match']))
|
self.assertEqual(op.join('basepath','foo bar'),d1.get('path'))
|
||||||
d1,d2,d3 = [c for c in children if c.nodeName == 'file']
|
self.assertEqual(op.join('basepath','bar bleh'),d2.get('path'))
|
||||||
self.assertEqual(op.join('basepath','foo bar'),d1.getAttributeNode('path').nodeValue)
|
self.assertEqual(op.join('basepath','foo bleh'),d3.get('path'))
|
||||||
self.assertEqual(op.join('basepath','bar bleh'),d2.getAttributeNode('path').nodeValue)
|
self.assertEqual('y',d1.get('is_ref'))
|
||||||
self.assertEqual(op.join('basepath','foo bleh'),d3.getAttributeNode('path').nodeValue)
|
self.assertEqual('n',d2.get('is_ref'))
|
||||||
self.assertEqual('y',d1.getAttributeNode('is_ref').nodeValue)
|
self.assertEqual('n',d3.get('is_ref'))
|
||||||
self.assertEqual('n',d2.getAttributeNode('is_ref').nodeValue)
|
self.assertEqual('foo,bar',d1.get('words'))
|
||||||
self.assertEqual('n',d3.getAttributeNode('is_ref').nodeValue)
|
self.assertEqual('bar,bleh',d2.get('words'))
|
||||||
self.assertEqual('foo,bar',d1.getAttributeNode('words').nodeValue)
|
self.assertEqual('foo,bleh',d3.get('words'))
|
||||||
self.assertEqual('bar,bleh',d2.getAttributeNode('words').nodeValue)
|
self.assertEqual(3,len(g2))
|
||||||
self.assertEqual('foo,bleh',d3.getAttributeNode('words').nodeValue)
|
self.assertEqual(2,len([c for c in g2 if c.tag == 'file']))
|
||||||
children = [c for c in g2.childNodes if c.localName]
|
self.assertEqual(1,len([c for c in g2 if c.tag == 'match']))
|
||||||
self.assertEqual(3,len(children))
|
d1, d2 = [c for c in g2 if c.tag == 'file']
|
||||||
self.assertEqual(2,len([c for c in children if c.nodeName == 'file']))
|
self.assertEqual(op.join('basepath','ibabtu'),d1.get('path'))
|
||||||
self.assertEqual(1,len([c for c in children if c.nodeName == 'match']))
|
self.assertEqual(op.join('basepath','ibabtu'),d2.get('path'))
|
||||||
d1,d2 = [c for c in children if c.nodeName == 'file']
|
self.assertEqual('n',d1.get('is_ref'))
|
||||||
self.assertEqual(op.join('basepath','ibabtu'),d1.getAttributeNode('path').nodeValue)
|
self.assertEqual('n',d2.get('is_ref'))
|
||||||
self.assertEqual(op.join('basepath','ibabtu'),d2.getAttributeNode('path').nodeValue)
|
self.assertEqual('ibabtu',d1.get('words'))
|
||||||
self.assertEqual('n',d1.getAttributeNode('is_ref').nodeValue)
|
self.assertEqual('ibabtu',d2.get('words'))
|
||||||
self.assertEqual('n',d2.getAttributeNode('is_ref').nodeValue)
|
|
||||||
self.assertEqual('ibabtu',d1.getAttributeNode('words').nodeValue)
|
|
||||||
self.assertEqual('ibabtu',d2.getAttributeNode('words').nodeValue)
|
|
||||||
|
|
||||||
def test_LoadXML(self):
|
def test_LoadXML(self):
|
||||||
def get_file(path):
|
def get_file(path):
|
||||||
@@ -460,41 +463,41 @@ class TCResultsXML(TestCase):
|
|||||||
def get_file(path):
|
def get_file(path):
|
||||||
return [f for f in self.objects if str(f.path) == path][0]
|
return [f for f in self.objects if str(f.path) == path][0]
|
||||||
|
|
||||||
doc = xml.dom.minidom.Document()
|
root = etree.Element('foobar') #The root element shouldn't matter, really.
|
||||||
root = doc.appendChild(doc.createElement('foobar')) #The root element shouldn't matter, really.
|
group_node = etree.SubElement(root, 'group')
|
||||||
group_node = root.appendChild(doc.createElement('group'))
|
dupe_node = etree.SubElement(group_node, 'file') #Perfectly correct file
|
||||||
dupe_node = group_node.appendChild(doc.createElement('file')) #Perfectly correct file
|
dupe_node.set('path', op.join('basepath','foo bar'))
|
||||||
dupe_node.setAttribute('path',op.join('basepath','foo bar'))
|
dupe_node.set('is_ref', 'y')
|
||||||
dupe_node.setAttribute('is_ref','y')
|
dupe_node.set('words', 'foo,bar')
|
||||||
dupe_node.setAttribute('words','foo,bar')
|
dupe_node = etree.SubElement(group_node, 'file') #is_ref missing, default to 'n'
|
||||||
dupe_node = group_node.appendChild(doc.createElement('file')) #is_ref missing, default to 'n'
|
dupe_node.set('path',op.join('basepath','foo bleh'))
|
||||||
dupe_node.setAttribute('path',op.join('basepath','foo bleh'))
|
dupe_node.set('words','foo,bleh')
|
||||||
dupe_node.setAttribute('words','foo,bleh')
|
dupe_node = etree.SubElement(group_node, 'file') #words are missing, valid.
|
||||||
dupe_node = group_node.appendChild(doc.createElement('file')) #words are missing, invalid.
|
dupe_node.set('path',op.join('basepath','bar bleh'))
|
||||||
dupe_node.setAttribute('path',op.join('basepath','bar bleh'))
|
dupe_node = etree.SubElement(group_node, 'file') #path is missing, invalid.
|
||||||
dupe_node = group_node.appendChild(doc.createElement('file')) #path is missing, invalid.
|
dupe_node.set('words','foo,bleh')
|
||||||
dupe_node.setAttribute('words','foo,bleh')
|
dupe_node = etree.SubElement(group_node, 'foobar') #Invalid element name
|
||||||
dupe_node = group_node.appendChild(doc.createElement('foobar')) #Invalid element name
|
dupe_node.set('path',op.join('basepath','bar bleh'))
|
||||||
dupe_node.setAttribute('path',op.join('basepath','bar bleh'))
|
dupe_node.set('is_ref','y')
|
||||||
dupe_node.setAttribute('is_ref','y')
|
dupe_node.set('words','bar,bleh')
|
||||||
dupe_node.setAttribute('words','bar,bleh')
|
match_node = etree.SubElement(group_node, 'match') # match pointing to a bad index
|
||||||
match_node = group_node.appendChild(doc.createElement('match')) # match pointing to a bad index
|
match_node.set('first', '42')
|
||||||
match_node.setAttribute('first', '42')
|
match_node.set('second', '45')
|
||||||
match_node.setAttribute('second', '45')
|
match_node = etree.SubElement(group_node, 'match') # match with missing attrs
|
||||||
match_node = group_node.appendChild(doc.createElement('match')) # match with missing attrs
|
match_node = etree.SubElement(group_node, 'match') # match with non-int values
|
||||||
match_node = group_node.appendChild(doc.createElement('match')) # match with non-int values
|
match_node.set('first', 'foo')
|
||||||
match_node.setAttribute('first', 'foo')
|
match_node.set('second', 'bar')
|
||||||
match_node.setAttribute('second', 'bar')
|
match_node.set('percentage', 'baz')
|
||||||
match_node.setAttribute('percentage', 'baz')
|
group_node = etree.SubElement(root, 'foobar') #invalid group
|
||||||
group_node = root.appendChild(doc.createElement('foobar')) #invalid group
|
group_node = etree.SubElement(root, 'group') #empty group
|
||||||
group_node = root.appendChild(doc.createElement('group')) #empty group
|
|
||||||
f = StringIO.StringIO()
|
f = StringIO.StringIO()
|
||||||
doc.writexml(f,'\t','\t','\n',encoding='utf-8')
|
tree = etree.ElementTree(root)
|
||||||
|
tree.write(f, encoding='utf-8')
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
r = Results(data)
|
r = Results(data)
|
||||||
r.load_from_xml(f,get_file)
|
r.load_from_xml(f, get_file)
|
||||||
self.assertEqual(1,len(r.groups))
|
self.assertEqual(1,len(r.groups))
|
||||||
self.assertEqual(2,len(r.groups[0]))
|
self.assertEqual(3,len(r.groups[0]))
|
||||||
|
|
||||||
def test_xml_non_ascii(self):
|
def test_xml_non_ascii(self):
|
||||||
def get_file(path):
|
def get_file(path):
|
||||||
@@ -567,6 +570,10 @@ class TCResultsXML(TestCase):
|
|||||||
self.results.load_from_xml(f, self.get_file)
|
self.results.load_from_xml(f, self.get_file)
|
||||||
first(self.results.groups[0].matches).percentage
|
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):
|
class TCResultsFilter(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@@ -7,10 +7,9 @@
|
|||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
import os.path as op
|
import os.path as op
|
||||||
import logging
|
|
||||||
import plistlib
|
import plistlib
|
||||||
import re
|
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
from appscript import app, k, CommandError
|
from appscript import app, k, CommandError
|
||||||
|
|
||||||
from hsutil import io
|
from hsutil import io
|
||||||
@@ -68,15 +67,10 @@ def get_iphoto_database_path():
|
|||||||
def get_iphoto_pictures(plistpath):
|
def get_iphoto_pictures(plistpath):
|
||||||
if not io.exists(plistpath):
|
if not io.exists(plistpath):
|
||||||
return []
|
return []
|
||||||
s = io.open(plistpath).read()
|
# We make the xml go through lxml so that it can fix broken xml which iPhoto sometimes produces.
|
||||||
# There was a case where a guy had 0x10 chars in his plist, causing expat errors on loading
|
parser = etree.XMLParser(recover=True)
|
||||||
s = s.replace('\x10', '')
|
root = etree.parse(io.open(plistpath), parser=parser).getroot()
|
||||||
# It seems that iPhoto sometimes doesn't properly escape & chars. The regexp below is to find
|
s = etree.tostring(root)
|
||||||
# any & char that is not a &-based entity (&, ", etc.). based on TextMate's XML
|
|
||||||
# bundle's regexp
|
|
||||||
s, count = re.subn(r'&(?![a-zA-Z0-9_-]+|#[0-9]+|#x[0-9a-fA-F]+;)', '', s)
|
|
||||||
if count:
|
|
||||||
logging.warning("%d invalid XML entities replacement made", count)
|
|
||||||
plist = plistlib.readPlistFromString(s)
|
plist = plistlib.readPlistFromString(s)
|
||||||
result = []
|
result = []
|
||||||
for photo_data in plist['Master Image List'].values():
|
for photo_data in plist['Master Image List'].values():
|
||||||
@@ -152,7 +146,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
|
|||||||
except (CommandError, RuntimeError):
|
except (CommandError, RuntimeError):
|
||||||
pass
|
pass
|
||||||
j.start_job(self.results.mark_count, "Sending dupes to the Trash")
|
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
|
del self.path2iphoto
|
||||||
|
|
||||||
def _do_delete_dupe(self, dupe):
|
def _do_delete_dupe(self, dupe):
|
||||||
@@ -162,14 +156,13 @@ class DupeGuruPE(app_cocoa.DupeGuru):
|
|||||||
try:
|
try:
|
||||||
a = app('iPhoto')
|
a = app('iPhoto')
|
||||||
a.remove(photo, timeout=0)
|
a.remove(photo, timeout=0)
|
||||||
return True
|
except (CommandError, RuntimeError) as e:
|
||||||
except (CommandError, RuntimeError):
|
raise EnvironmentError(unicode(e))
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
logging.warning(u"Could not find photo %s in iPhoto Library", unicode(dupe.path))
|
msg = u"Could not find photo %s in iPhoto Library" % unicode(dupe.path)
|
||||||
return False
|
raise EnvironmentError(msg)
|
||||||
else:
|
else:
|
||||||
return app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
|
app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
|
||||||
|
|
||||||
def _do_load(self, j):
|
def _do_load(self, j):
|
||||||
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
self.directories.load_from_file(op.join(self.appdata, 'last_directories.xml'))
|
||||||
|
|||||||
@@ -111,8 +111,13 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
|
|||||||
others = [pic for pic in others if not pic.is_ref]
|
others = [pic for pic in others if not pic.is_ref]
|
||||||
if others:
|
if others:
|
||||||
cache_ids = [f.cache_id for f in others]
|
cache_ids = [f.cache_id for f in others]
|
||||||
args = (ref.cache_id, cache_ids, cache_path, threshold)
|
# We limit the number of cache_ids we send for multi-processing because otherwise, we
|
||||||
async_results.append(pool.apply_async(async_compare, args))
|
# 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:]
|
||||||
if len(async_results) > RESULTS_QUEUE_LIMIT:
|
if len(async_results) > RESULTS_QUEUE_LIMIT:
|
||||||
result = async_results.pop(0)
|
result = async_results.pop(0)
|
||||||
matches.extend(result.get())
|
matches.extend(result.get())
|
||||||
|
|||||||
12
debian_me/control
Normal file
12
debian_me/control
Normal 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
11
debian_me/copyright
Normal 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
3
debian_me/dirs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
usr/local/bin
|
||||||
|
usr/local/share
|
||||||
|
usr/share/applications
|
||||||
10
debian_me/dupeguru_me.desktop
Normal file
10
debian_me/dupeguru_me.desktop
Normal 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
86
debian_me/rules
Executable 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
12
debian_pe/control
Normal 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
11
debian_pe/copyright
Normal 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
3
debian_pe/dirs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
usr/local/bin
|
||||||
|
usr/local/share
|
||||||
|
usr/share/applications
|
||||||
9
debian_pe/dupeguru_pe.desktop
Normal file
9
debian_pe/dupeguru_pe.desktop
Normal 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
86
debian_pe/rules
Executable 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
12
debian_se/control
Normal 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
11
debian_se/copyright
Normal 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
3
debian_se/dirs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
usr/local/bin
|
||||||
|
usr/local/share
|
||||||
|
usr/share/applications
|
||||||
9
debian_se/dupeguru_se.desktop
Normal file
9
debian_se/dupeguru_se.desktop
Normal 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
86
debian_se/rules
Executable 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
|
||||||
@@ -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
|
- date: 2010-02-13
|
||||||
version: 5.7.2
|
version: 5.7.2
|
||||||
description: |
|
description: |
|
||||||
|
|||||||
@@ -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".
|
* **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.
|
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"
|
||||||
|
|||||||
@@ -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.
|
* **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.
|
* **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.
|
* **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.
|
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
- date: 2010-04-08
|
||||||
|
version: 1.8.6
|
||||||
|
description: |
|
||||||
|
* Fixed a crash when performing very big scans.
|
||||||
|
* Fixed a rare crash during results loading. (#90)
|
||||||
|
- date: 2010-03-01
|
||||||
|
version: 1.8.5
|
||||||
|
description: |
|
||||||
|
* Fixed a bug preventing some iPhoto Libraries to be read. [Mac OS X]
|
||||||
|
* Improved results loading and saving speed.
|
||||||
- date: 2010-02-18
|
- date: 2010-02-18
|
||||||
version: 1.8.4
|
version: 1.8.4
|
||||||
description: |
|
description: |
|
||||||
|
|||||||
@@ -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
|
- date: 2010-02-10
|
||||||
version: 2.9.2
|
version: 2.9.2
|
||||||
description: |
|
description: |
|
||||||
|
|||||||
@@ -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".
|
* **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.
|
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"
|
||||||
|
|||||||
@@ -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.
|
* **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.
|
* **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.
|
* **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.
|
* **Rename Selected:** Prompts you for a new name, and then rename the selected file.
|
||||||
|
|||||||
89
package.py
89
package.py
@@ -10,11 +10,13 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import os.path as op
|
import os.path as op
|
||||||
|
import compileall
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from hsutil.build import build_dmg, add_to_pythonpath, print_and_do
|
from hsutil.build import (build_dmg, add_to_pythonpath, print_and_do, copy_packages,
|
||||||
|
build_debian_changelog, copy_qt_plugins)
|
||||||
|
|
||||||
def package_cocoa(edition):
|
def package_cocoa(edition):
|
||||||
app_path = {
|
app_path = {
|
||||||
@@ -24,7 +26,7 @@ def package_cocoa(edition):
|
|||||||
}[edition]
|
}[edition]
|
||||||
build_dmg(app_path, '.')
|
build_dmg(app_path, '.')
|
||||||
|
|
||||||
def package_qt(edition):
|
def package_windows(edition, dev):
|
||||||
# On Windows, PyInstaller is used to build an exe (py2exe creates a very bad looking icon)
|
# On Windows, PyInstaller is used to build an exe (py2exe creates a very bad looking icon)
|
||||||
# The release version is outdated. Use at least r672 on http://svn.pyinstaller.org/trunk
|
# The release version is outdated. Use at least r672 on http://svn.pyinstaller.org/trunk
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
@@ -36,47 +38,88 @@ def package_qt(edition):
|
|||||||
os.chdir(op.join('qt', edition))
|
os.chdir(op.join('qt', edition))
|
||||||
from app import DupeGuru
|
from app import DupeGuru
|
||||||
|
|
||||||
# Removing build and dist
|
|
||||||
if op.exists('build'):
|
|
||||||
shutil.rmtree('build')
|
|
||||||
if op.exists('dist'):
|
if op.exists('dist'):
|
||||||
shutil.rmtree('dist')
|
shutil.rmtree('dist')
|
||||||
version = DupeGuru.VERSION
|
|
||||||
versioncomma = version.replace('.', ', ') + ', 0'
|
|
||||||
verinfo = open('verinfo').read()
|
|
||||||
verinfo = verinfo.replace('$versioncomma', versioncomma).replace('$version', version)
|
|
||||||
fp = open('verinfo_tmp', 'w')
|
|
||||||
fp.write(verinfo)
|
|
||||||
fp.close()
|
|
||||||
print_and_do("python C:\\Python26\\pyinstaller\\Build.py dg{0}.spec".format(edition))
|
|
||||||
os.remove('verinfo_tmp')
|
|
||||||
|
|
||||||
print_and_do("del dist\\*90.dll") # They're in vcredist, no need to include them
|
cmd = 'cxfreeze --base-name Win32GUI --target-name "{0}.exe" --icon {1} start.py'
|
||||||
print_and_do("del dist\\POWRPROF.dll") # no need of that crap
|
target_name = {'se': 'dupeGuru', 'me': 'dupeGuru ME', 'pe': 'dupeGuru PE'}[edition]
|
||||||
print_and_do("del dist\\SHLWAPI.dll") # no need of that crap
|
icon_path = '..\\..\\images\\dg{0}_logo.ico'.format(edition)
|
||||||
print_and_do("xcopy /Y /S /I ..\\..\\help_me\\dupeguru_me_help dist\\help")
|
print_and_do(cmd.format(target_name, icon_path))
|
||||||
|
|
||||||
|
if not dev:
|
||||||
|
# Copy qt plugins
|
||||||
|
plugin_dest = op.join('dist', 'qt4_plugins')
|
||||||
|
plugin_names = ['accessible', 'codecs', 'iconengines', 'imageformats']
|
||||||
|
copy_qt_plugins(plugin_names, plugin_dest)
|
||||||
|
|
||||||
|
# Compress with UPX
|
||||||
|
libs = [name for name in os.listdir('dist') if op.splitext(name)[1] in ('.pyd', '.dll', '.exe')]
|
||||||
|
for lib in libs:
|
||||||
|
print_and_do("upx --best \"dist\\{0}\"".format(lib))
|
||||||
|
|
||||||
|
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
|
# AdvancedInstaller.com has to be in your PATH
|
||||||
# this is so we don'a have to re-commit installer.aip at every version change
|
# this is so we don'a have to re-commit installer.aip at every version change
|
||||||
shutil.copy('installer.aip', 'installer_tmp.aip')
|
shutil.copy('installer.aip', 'installer_tmp.aip')
|
||||||
print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion %s' % version)
|
print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion %s' % DupeGuru.VERSION)
|
||||||
print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force')
|
print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force')
|
||||||
os.remove('installer_tmp.aip')
|
os.remove('installer_tmp.aip')
|
||||||
os.chdir(op.join('..', '..'))
|
os.chdir(op.join('..', '..'))
|
||||||
|
|
||||||
|
def package_debian(edition):
|
||||||
|
add_to_pythonpath('qt')
|
||||||
|
add_to_pythonpath(op.join('qt', edition))
|
||||||
|
from app import DupeGuru
|
||||||
|
|
||||||
|
if op.exists('build'):
|
||||||
|
shutil.rmtree('build')
|
||||||
|
ed = lambda s: s.format(edition)
|
||||||
|
destpath = op.join('build', 'dupeguru-{0}-{1}'.format(edition, DupeGuru.VERSION))
|
||||||
|
srcpath = op.join(destpath, 'src')
|
||||||
|
help_src = ed('help_{0}')
|
||||||
|
os.makedirs(destpath)
|
||||||
|
shutil.copytree(ed('qt/{0}'), srcpath)
|
||||||
|
packages = ['hsutil', 'hsgui', 'core', ed('core_{0}'), 'qtlib', 'qt/base']
|
||||||
|
if edition == 'me':
|
||||||
|
packages.append('hsmedia')
|
||||||
|
copy_packages(packages, srcpath)
|
||||||
|
# We also have to copy the Send2Trash package
|
||||||
|
import send2trash
|
||||||
|
pkg_path = op.dirname(send2trash.__file__)
|
||||||
|
shutil.copytree(pkg_path, op.join(srcpath, 'send2trash'))
|
||||||
|
shutil.copytree(ed('debian_{0}'), op.join(destpath, 'debian'))
|
||||||
|
yaml_path = op.join(help_src, 'changelog.yaml')
|
||||||
|
changelog_dest = op.join(destpath, 'debian', 'changelog')
|
||||||
|
project_name = ed('dupeguru-{0}')
|
||||||
|
from_version = {'se': '2.9.2', 'me': '5.7.2', 'pe': '1.8.5'}[edition]
|
||||||
|
build_debian_changelog(yaml_path, changelog_dest, project_name, from_version=from_version)
|
||||||
|
help_name = {'se': 'dupeguru_help', 'me': 'dupeguru_me_help', 'pe': 'dupeguru_pe_help'}[edition]
|
||||||
|
shutil.copytree(op.join(help_src, help_name), op.join(srcpath, 'help'))
|
||||||
|
shutil.copy(op.join('images', ed('dg{0}_logo_128.png')), srcpath)
|
||||||
|
compileall.compile_dir(srcpath)
|
||||||
|
os.chdir(destpath)
|
||||||
|
os.system("dpkg-buildpackage")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
conf = yaml.load(open('conf.yaml'))
|
conf = yaml.load(open('conf.yaml'))
|
||||||
edition = conf['edition']
|
edition = conf['edition']
|
||||||
ui = conf['ui']
|
ui = conf['ui']
|
||||||
dev = conf['dev']
|
dev = conf['dev']
|
||||||
if dev:
|
|
||||||
print "You can't package in dev mode"
|
|
||||||
return
|
|
||||||
print "Packaging dupeGuru {0} with UI {1}".format(edition.upper(), ui)
|
print "Packaging dupeGuru {0} with UI {1}".format(edition.upper(), ui)
|
||||||
if ui == 'cocoa':
|
if ui == 'cocoa':
|
||||||
package_cocoa(edition)
|
package_cocoa(edition)
|
||||||
elif ui == 'qt':
|
elif ui == 'qt':
|
||||||
package_qt(edition)
|
if sys.platform == "win32":
|
||||||
|
package_windows(edition, dev)
|
||||||
|
elif sys.platform == "linux2":
|
||||||
|
package_debian(edition)
|
||||||
|
else:
|
||||||
|
print "Qt packaging only works under Windows or Linux."
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
@@ -28,6 +28,7 @@ from . import platform
|
|||||||
|
|
||||||
from .main_window import MainWindow
|
from .main_window import MainWindow
|
||||||
from .directories_dialog import DirectoriesDialog
|
from .directories_dialog import DirectoriesDialog
|
||||||
|
from .problem_dialog import ProblemDialog
|
||||||
|
|
||||||
JOBID2TITLE = {
|
JOBID2TITLE = {
|
||||||
JOB_SCAN: "Scanning for duplicates",
|
JOB_SCAN: "Scanning for duplicates",
|
||||||
@@ -71,6 +72,7 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
self._progress = Progress(self.main_window)
|
self._progress = Progress(self.main_window)
|
||||||
self.directories_dialog = DirectoriesDialog(self.main_window, self)
|
self.directories_dialog = DirectoriesDialog(self.main_window, self)
|
||||||
self.details_dialog = self._create_details_dialog(self.main_window)
|
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.preferences_dialog = self._create_preferences_dialog(self.main_window)
|
||||||
self.about_box = AboutBox(self.main_window, self)
|
self.about_box = AboutBox(self.main_window, self)
|
||||||
|
|
||||||
@@ -121,10 +123,6 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
url = QUrl.fromLocalFile(unicode(path))
|
url = QUrl.fromLocalFile(unicode(path))
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _recycle_dupe(dupe):
|
|
||||||
platform.recycle_file(dupe.path)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _reveal_path(path):
|
def _reveal_path(path):
|
||||||
DupeGuru._open_path(path[:-1])
|
DupeGuru._open_path(path[:-1])
|
||||||
@@ -173,6 +171,14 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
def askForRegCode(self):
|
def askForRegCode(self):
|
||||||
self.reg.ask_for_code()
|
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):
|
def openDebugLog(self):
|
||||||
debugLogPath = op.join(self.appdata, 'debug.log')
|
debugLogPath = op.join(self.appdata, 'debug.log')
|
||||||
self._open_path(debugLogPath)
|
self._open_path(debugLogPath)
|
||||||
@@ -187,7 +193,8 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
self.directories_dialog.show()
|
self.directories_dialog.show()
|
||||||
|
|
||||||
def show_help(self):
|
def show_help(self):
|
||||||
url = QUrl.fromLocalFile(op.abspath('help/intro.htm'))
|
base_path = platform.HELP_PATH.format(self.EDITION)
|
||||||
|
url = QUrl.fromLocalFile(op.abspath(op.join(base_path, 'intro.htm')))
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
def show_preferences(self):
|
def show_preferences(self):
|
||||||
@@ -209,9 +216,12 @@ class DupeGuru(DupeGuruBase, QObject):
|
|||||||
|
|
||||||
def job_finished(self, jobid):
|
def job_finished(self, jobid):
|
||||||
self._job_completed(jobid)
|
self._job_completed(jobid)
|
||||||
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE) and self.last_op_error_count > 0:
|
if jobid in (JOB_MOVE, JOB_COPY, JOB_DELETE):
|
||||||
msg = "{0} files could not be processed.".format(self.results.mark_count)
|
if self.results.problems:
|
||||||
QMessageBox.warning(self.main_window, 'Warning', msg)
|
self.problemDialog.show()
|
||||||
|
else:
|
||||||
|
msg = "All files were processed successfully."
|
||||||
|
QMessageBox.information(self.main_window, 'Operation Complete', msg)
|
||||||
elif jobid == JOB_SCAN:
|
elif jobid == JOB_SCAN:
|
||||||
if not self.results.groups:
|
if not self.results.groups:
|
||||||
title = "Scanning complete"
|
title = "Scanning complete"
|
||||||
|
|||||||
9
qt/base/cxfreeze_fix.py
Normal file
9
qt/base/cxfreeze_fix.py
Normal 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'
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl
|
from PyQt4.QtCore import Qt, QCoreApplication, QProcess, SIGNAL, QUrl
|
||||||
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView,
|
from PyQt4.QtGui import (QMainWindow, QMenu, QPixmap, QIcon, QToolButton, QLabel, QHeaderView,
|
||||||
QMessageBox, QInputDialog, QLineEdit, QDesktopServices)
|
QMessageBox, QInputDialog, QLineEdit, QDesktopServices)
|
||||||
@@ -35,6 +37,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
|
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
|
||||||
self.connect(self.resultsView, SIGNAL('doubleClicked()'), self.resultsDoubleClicked)
|
self.connect(self.resultsView, SIGNAL('doubleClicked()'), self.resultsDoubleClicked)
|
||||||
self.connect(self.resultsView, SIGNAL('spacePressed()'), self.resultsSpacePressed)
|
self.connect(self.resultsView, SIGNAL('spacePressed()'), self.resultsSpacePressed)
|
||||||
|
self.actionInvokeCustomCommand.triggered.connect(self.app.invokeCustomCommand)
|
||||||
|
|
||||||
def _setupUi(self):
|
def _setupUi(self):
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@@ -74,6 +77,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
actionMenu.addSeparator()
|
actionMenu.addSeparator()
|
||||||
actionMenu.addAction(self.actionOpenSelected)
|
actionMenu.addAction(self.actionOpenSelected)
|
||||||
actionMenu.addAction(self.actionRevealSelected)
|
actionMenu.addAction(self.actionRevealSelected)
|
||||||
|
actionMenu.addAction(self.actionInvokeCustomCommand)
|
||||||
actionMenu.addAction(self.actionRenameSelected)
|
actionMenu.addAction(self.actionRenameSelected)
|
||||||
self.actionActions.setMenu(actionMenu)
|
self.actionActions.setMenu(actionMenu)
|
||||||
button = QToolButton(self.toolBar)
|
button = QToolButton(self.toolBar)
|
||||||
@@ -86,6 +90,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||||||
self.statusLabel = QLabel(self)
|
self.statusLabel = QLabel(self)
|
||||||
self.statusbar.addPermanentWidget(self.statusLabel, 1)
|
self.statusbar.addPermanentWidget(self.statusLabel, 1)
|
||||||
|
|
||||||
|
# Linux setup
|
||||||
|
if sys.platform == 'linux2':
|
||||||
|
self.actionCheckForUpdate.setVisible(False) # This only works on Windows
|
||||||
|
|
||||||
#--- Private
|
#--- Private
|
||||||
def _confirm(self, title, msg, default_button=QMessageBox.Yes):
|
def _confirm(self, title, msg, default_button=QMessageBox.Yes):
|
||||||
buttons = QMessageBox.Yes | QMessageBox.No
|
buttons = QMessageBox.Yes | QMessageBox.No
|
||||||
|
|||||||
@@ -44,6 +44,9 @@
|
|||||||
<attribute name="headerStretchLastSection">
|
<attribute name="headerStretchLastSection">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<attribute name="headerStretchLastSection">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -54,7 +57,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>630</width>
|
<width>630</width>
|
||||||
<height>22</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuColumns">
|
<widget class="QMenu" name="menuColumns">
|
||||||
@@ -77,6 +80,7 @@
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionOpenSelected"/>
|
<addaction name="actionOpenSelected"/>
|
||||||
<addaction name="actionRevealSelected"/>
|
<addaction name="actionRevealSelected"/>
|
||||||
|
<addaction name="actionInvokeCustomCommand"/>
|
||||||
<addaction name="actionRenameSelected"/>
|
<addaction name="actionRenameSelected"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionApplyFilter"/>
|
<addaction name="actionApplyFilter"/>
|
||||||
@@ -428,6 +432,14 @@
|
|||||||
<string>Open Debug Log</string>
|
<string>Open Debug Log</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionInvokeCustomCommand">
|
||||||
|
<property name="text">
|
||||||
|
<string>Invoke Custom Command</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+I</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
@@ -7,7 +7,5 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
INITIAL_FOLDER_IN_DIALOGS = '/'
|
INITIAL_FOLDER_IN_DIALOGS = u'/'
|
||||||
|
HELP_PATH = '/usr/local/share/dupeguru_{0}/help'
|
||||||
def recycle_file(path):
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -9,7 +9,5 @@
|
|||||||
|
|
||||||
# dummy unit to allow the app to run under OSX during development
|
# dummy unit to allow the app to run under OSX during development
|
||||||
|
|
||||||
INITIAL_FOLDER_IN_DIALOGS = '/'
|
INITIAL_FOLDER_IN_DIALOGS = u'/'
|
||||||
|
HELP_PATH = ''
|
||||||
def recycle_file(path):
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -7,16 +7,5 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/hs_license
|
# http://www.hardcoded.net/licenses/hs_license
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
INITIAL_FOLDER_IN_DIALOGS = u'C:\\'
|
||||||
|
HELP_PATH = 'help'
|
||||||
import logging
|
|
||||||
|
|
||||||
import winshell
|
|
||||||
|
|
||||||
INITIAL_FOLDER_IN_DIALOGS = 'C:\\'
|
|
||||||
|
|
||||||
def recycle_file(path):
|
|
||||||
try:
|
|
||||||
winshell.delete_file(unicode(path), no_confirm=True, silent=True)
|
|
||||||
except winshell.x_winshell as e:
|
|
||||||
logging.warning("winshell error: %s", e)
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class Preferences(PreferencesBase):
|
|||||||
self.use_regexp = get('UseRegexp', self.use_regexp)
|
self.use_regexp = get('UseRegexp', self.use_regexp)
|
||||||
self.remove_empty_folders = get('RemoveEmptyFolders', self.remove_empty_folders)
|
self.remove_empty_folders = get('RemoveEmptyFolders', self.remove_empty_folders)
|
||||||
self.destination_type = get('DestinationType', self.destination_type)
|
self.destination_type = get('DestinationType', self.destination_type)
|
||||||
|
self.custom_command = get('CustomCommand', self.custom_command)
|
||||||
widths = get('ColumnsWidth', self.columns_width)
|
widths = get('ColumnsWidth', self.columns_width)
|
||||||
# only set nonzero values
|
# only set nonzero values
|
||||||
for index, width in enumerate(widths[:len(self.columns_width)]):
|
for index, width in enumerate(widths[:len(self.columns_width)]):
|
||||||
@@ -46,6 +47,7 @@ class Preferences(PreferencesBase):
|
|||||||
self.use_regexp = False
|
self.use_regexp = False
|
||||||
self.remove_empty_folders = False
|
self.remove_empty_folders = False
|
||||||
self.destination_type = 1
|
self.destination_type = 1
|
||||||
|
self.custom_command = ''
|
||||||
self.registration_code = ''
|
self.registration_code = ''
|
||||||
self.registration_email = ''
|
self.registration_email = ''
|
||||||
self._reset_specific()
|
self._reset_specific()
|
||||||
@@ -64,6 +66,7 @@ class Preferences(PreferencesBase):
|
|||||||
set_('UseRegexp', self.use_regexp)
|
set_('UseRegexp', self.use_regexp)
|
||||||
set_('RemoveEmptyFolders', self.remove_empty_folders)
|
set_('RemoveEmptyFolders', self.remove_empty_folders)
|
||||||
set_('DestinationType', self.destination_type)
|
set_('DestinationType', self.destination_type)
|
||||||
|
set_('CustomCommand', self.custom_command)
|
||||||
set_('ColumnsWidth', self.columns_width)
|
set_('ColumnsWidth', self.columns_width)
|
||||||
set_('ColumnsVisible', self.columns_visible)
|
set_('ColumnsVisible', self.columns_visible)
|
||||||
set_('RegistrationCode', self.registration_code)
|
set_('RegistrationCode', self.registration_code)
|
||||||
|
|||||||
32
qt/base/problem_dialog.py
Normal file
32
qt/base/problem_dialog.py
Normal 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
116
qt/base/problem_dialog.ui
Normal 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
25
qt/base/problem_table.py
Normal 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
|
||||||
|
|
||||||
@@ -14,9 +14,10 @@ from preferences import Preferences
|
|||||||
from preferences_dialog import PreferencesDialog
|
from preferences_dialog import PreferencesDialog
|
||||||
|
|
||||||
class DupeGuru(DupeGuruBase):
|
class DupeGuru(DupeGuruBase):
|
||||||
|
EDITION = 'me'
|
||||||
LOGO_NAME = 'logo_me'
|
LOGO_NAME = 'logo_me'
|
||||||
NAME = 'dupeGuru Music Edition'
|
NAME = 'dupeGuru Music Edition'
|
||||||
VERSION = '5.7.2'
|
VERSION = '5.8.0'
|
||||||
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8])
|
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7, 8])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@@ -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'))
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5" modules="professional" RootPath="." Language="en">
|
<DOCUMENT Type="Advanced Installer" CreateVersion="4.7.2" version="7.6" Modules="professional" RootPath="." Language="en">
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
||||||
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
||||||
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
||||||
@@ -28,18 +28,13 @@
|
|||||||
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
|
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
|
||||||
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
|
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
|
||||||
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
||||||
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
|
|
||||||
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
|
|
||||||
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
|
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
|
||||||
<ROW Directory="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
|
|
||||||
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
|
|
||||||
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
|
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
|
||||||
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
|
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||||
<ROW Component="AIShRegAnswer" ComponentId="{7DB5C163-2978-436F-A47D-54F1C76F1D64}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
|
<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="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="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="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"/>
|
<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="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="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="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"/>
|
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_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"/>
|
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
<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.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="6"/>
|
<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="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="7"/>
|
||||||
<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="8"/>
|
||||||
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="24"/>
|
|
||||||
<ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
|
<ROW File="bz2.pyd" Component_="bz2.pyd_1" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
|
||||||
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="36"/>
|
<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="37"/>
|
<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" Attributes="0" SourcePath="dist\dupeGuru ME.exe" SelfReg="false" Sequence="2"/>
|
<ROW File="dupeGuru_ME.exe" Component_="dupeGuru_ME.exe" FileName="dupeGu~1.exe|dupeGuru ME.exe" 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="38"/>
|
<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="39"/>
|
<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="32"/>
|
<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="40"/>
|
<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="41"/>
|
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="20"/>
|
||||||
<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="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="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="43"/>
|
<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="pyexpat.pyd" Component_="bz2.pyd_1" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="4"/>
|
<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="7"/>
|
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="6"/>
|
||||||
<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="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="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="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="24"/>
|
||||||
<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="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="9"/>
|
||||||
<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="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="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="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="10"/>
|
||||||
<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="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="13"/>
|
||||||
<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="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" 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="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="11"/>
|
||||||
<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="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_STUBS>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
||||||
<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="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="25"/>
|
||||||
<ROW File="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="10"/>
|
|
||||||
<ROW File="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="11"/>
|
|
||||||
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="22"/>
|
|
||||||
<ROW File="qtwcodecs4.dll" Component_="qtwcodecs4.dll" FileName="qtwcod~1.dll|qtwcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qtwcodecs4.dll" SelfReg="false" Sequence="15"/>
|
|
||||||
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="44"/>
|
|
||||||
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="45"/>
|
|
||||||
<ROW File="select.pyd" Component_="bz2.pyd_1" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="25"/>
|
|
||||||
<ROW File="sip.pyd" Component_="bz2.pyd_1" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="26"/>
|
|
||||||
<ROW File="socket.pyd" Component_="bz2.pyd_1" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="33"/>
|
|
||||||
<ROW File="ssl.pyd" Component_="bz2.pyd_1" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="34"/>
|
|
||||||
<ROW File="unicodedata.pyd" Component_="bz2.pyd_1" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="27"/>
|
|
||||||
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
|
||||||
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="46"/>
|
|
||||||
<ROW File="win32api.pyd" Component_="bz2.pyd_1" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="28"/>
|
|
||||||
<ROW File="win32com.shell.shell.pyd" Component_="bz2.pyd_1" FileName="win32c~1.pyd|win32com.shell.shell.pyd" Attributes="0" SourcePath="dist\win32com.shell.shell.pyd" SelfReg="false" Sequence="29"/>
|
|
||||||
<ROW File="win32sysloader.pyd" Component_="bz2.pyd_1" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="35"/>
|
|
||||||
<ROW File="win32trace.pyd" Component_="bz2.pyd_1" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="30"/>
|
|
||||||
<ROW File="win32ui.pyd" Component_="bz2.pyd_1" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="31"/>
|
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
||||||
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_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"/>
|
<ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
|
<COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
|
||||||
|
<ATTRIBUTE name="Enable" value="false"/>
|
||||||
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
|
||||||
<ROW Path="<AI_DICTS>ui.ail"/>
|
<ROW Path="<AI_DICTS>ui.ail"/>
|
||||||
<ROW Path="<AI_DICTS>ui_en.ail"/>
|
<ROW Path="<AI_DICTS>ui_en.ail"/>
|
||||||
@@ -239,10 +204,11 @@
|
|||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
||||||
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
||||||
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
||||||
|
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
||||||
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||||
<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" Directory_="SHORTCUTDIR" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||||
<ROW Shortcut="dupeGuru_ME_1" Directory_="DesktopFolder" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
<ROW Shortcut="dupeGuru_ME_1" Directory_="DesktopFolder" Name="dupeGu~1|dupeGuru ME" Component_="dupeGuru_ME.exe" Target="[#dupeGuru_ME.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
|||||||
setchecked(self.useRegexpBox, prefs.use_regexp)
|
setchecked(self.useRegexpBox, prefs.use_regexp)
|
||||||
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
|
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
|
||||||
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
||||||
|
self.customCommandEdit.setText(prefs.custom_command)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
prefs = self.app.prefs
|
prefs = self.app.prefs
|
||||||
@@ -75,6 +76,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
|||||||
prefs.use_regexp = ischecked(self.useRegexpBox)
|
prefs.use_regexp = ischecked(self.useRegexpBox)
|
||||||
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
|
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
|
||||||
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
||||||
|
prefs.custom_command = unicode(self.customCommandEdit.text())
|
||||||
|
|
||||||
def resetToDefaults(self):
|
def resetToDefaults(self):
|
||||||
self.load(preferences.Preferences())
|
self.load(preferences.Preferences())
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>350</width>
|
<width>325</width>
|
||||||
<height>322</height>
|
<height>360</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,0,0,0,1">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
@@ -193,97 +193,86 @@
|
|||||||
<height>40</height>
|
<height>40</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QLabel" name="label_6">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<property name="geometry">
|
<property name="spacing">
|
||||||
<rect>
|
<number>0</number>
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>91</width>
|
|
||||||
<height>17</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="margin">
|
||||||
<string>Tags to scan:</string>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<item>
|
||||||
<widget class="QCheckBox" name="tagTrackBox">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="geometry">
|
<property name="text">
|
||||||
<rect>
|
<string>Tags to scan:</string>
|
||||||
<x>10</x>
|
</property>
|
||||||
<y>20</y>
|
</widget>
|
||||||
<width>51</width>
|
</item>
|
||||||
<height>21</height>
|
<item>
|
||||||
</rect>
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
</property>
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>0</number>
|
||||||
<string>Track</string>
|
</property>
|
||||||
</property>
|
<item>
|
||||||
</widget>
|
<spacer name="horizontalSpacer">
|
||||||
<widget class="QCheckBox" name="tagArtistBox">
|
<property name="orientation">
|
||||||
<property name="geometry">
|
<enum>Qt::Horizontal</enum>
|
||||||
<rect>
|
</property>
|
||||||
<x>60</x>
|
<property name="sizeType">
|
||||||
<y>20</y>
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
<width>51</width>
|
</property>
|
||||||
<height>21</height>
|
<property name="sizeHint" stdset="0">
|
||||||
</rect>
|
<size>
|
||||||
</property>
|
<width>15</width>
|
||||||
<property name="text">
|
<height>20</height>
|
||||||
<string>Artist</string>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</spacer>
|
||||||
<widget class="QCheckBox" name="tagAlbumBox">
|
</item>
|
||||||
<property name="geometry">
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="tagTrackBox">
|
||||||
<x>110</x>
|
<property name="text">
|
||||||
<y>20</y>
|
<string>Track</string>
|
||||||
<width>61</width>
|
</property>
|
||||||
<height>21</height>
|
</widget>
|
||||||
</rect>
|
</item>
|
||||||
</property>
|
<item>
|
||||||
<property name="text">
|
<widget class="QCheckBox" name="tagArtistBox">
|
||||||
<string>Album</string>
|
<property name="text">
|
||||||
</property>
|
<string>Artist</string>
|
||||||
</widget>
|
</property>
|
||||||
<widget class="QCheckBox" name="tagTitleBox">
|
</widget>
|
||||||
<property name="geometry">
|
</item>
|
||||||
<rect>
|
<item>
|
||||||
<x>170</x>
|
<widget class="QCheckBox" name="tagAlbumBox">
|
||||||
<y>20</y>
|
<property name="text">
|
||||||
<width>51</width>
|
<string>Album</string>
|
||||||
<height>21</height>
|
</property>
|
||||||
</rect>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Title</string>
|
<widget class="QCheckBox" name="tagTitleBox">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Title</string>
|
||||||
<widget class="QCheckBox" name="tagGenreBox">
|
</property>
|
||||||
<property name="geometry">
|
</widget>
|
||||||
<rect>
|
</item>
|
||||||
<x>220</x>
|
<item>
|
||||||
<y>20</y>
|
<widget class="QCheckBox" name="tagGenreBox">
|
||||||
<width>61</width>
|
<property name="text">
|
||||||
<height>21</height>
|
<string>Genre</string>
|
||||||
</rect>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Genre</string>
|
<item>
|
||||||
</property>
|
<widget class="QCheckBox" name="tagYearBox">
|
||||||
</widget>
|
<property name="text">
|
||||||
<widget class="QCheckBox" name="tagYearBox">
|
<string>Year</string>
|
||||||
<property name="geometry">
|
</property>
|
||||||
<rect>
|
</widget>
|
||||||
<x>280</x>
|
</item>
|
||||||
<y>20</y>
|
</layout>
|
||||||
<width>51</width>
|
</item>
|
||||||
<height>21</height>
|
</layout>
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Year</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -369,6 +358,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import base.dg_rc
|
|||||||
|
|
||||||
from app import DupeGuru
|
from app import DupeGuru
|
||||||
|
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import base.cxfreeze_fix
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.setWindowIcon(QIcon(QPixmap(":/logo_me")))
|
app.setWindowIcon(QIcon(QPixmap(":/logo_me")))
|
||||||
|
|||||||
@@ -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])])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@@ -54,9 +54,10 @@ class File(fs.File):
|
|||||||
|
|
||||||
|
|
||||||
class DupeGuru(DupeGuruBase):
|
class DupeGuru(DupeGuruBase):
|
||||||
|
EDITION = 'pe'
|
||||||
LOGO_NAME = 'logo_pe'
|
LOGO_NAME = 'logo_pe'
|
||||||
NAME = 'dupeGuru Picture Edition'
|
NAME = 'dupeGuru Picture Edition'
|
||||||
VERSION = '1.8.4'
|
VERSION = '1.8.6'
|
||||||
DELTA_COLUMNS = frozenset([2, 5, 6])
|
DELTA_COLUMNS = frozenset([2, 5, 6])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@@ -85,7 +85,7 @@
|
|||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>16777215</width>
|
<width>16777215</width>
|
||||||
<height>188</height>
|
<height>190</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
|
|||||||
@@ -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'))
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5" modules="professional" RootPath="." Language="en">
|
<DOCUMENT type="Advanced Installer" CreateVersion="4.7.2" version="7.5.2" modules="professional" RootPath="." Language="en">
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
||||||
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
||||||
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
||||||
@@ -28,110 +28,65 @@
|
|||||||
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
|
<ROW Directory="DesktopFolder" Directory_Parent="TARGETDIR" DefaultDir="Deskto~1|DesktopFolder" IsPseudoRoot="1"/>
|
||||||
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
|
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
|
||||||
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
||||||
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
|
|
||||||
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
|
|
||||||
<ROW Directory="gen_py_DIR" Directory_Parent="support_DIR" DefaultDir="gen_py"/>
|
|
||||||
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
|
<ROW Directory="help_DIR" Directory_Parent="APPDIR" DefaultDir="help"/>
|
||||||
<ROW Directory="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
|
|
||||||
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
|
|
||||||
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
|
<ROW Directory="images_DIR" Directory_Parent="help_DIR" DefaultDir="images"/>
|
||||||
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
|
|
||||||
<ROW Directory="support_DIR" Directory_Parent="APPDIR" DefaultDir="support"/>
|
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||||
<ROW Component="AIShRegAnswer" ComponentId="{F315B3C7-7C86-41EB-BE7D-2A6A8E3073B4}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
|
<ROW Component="AIShRegAnswer" ComponentId="{F315B3C7-7C86-41EB-BE7D-2A6A8E3073B4}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
|
||||||
<ROW Component="AI_ExePath" ComponentId="{8D009995-D5B9-4E68-A969-45A06F69ACB8}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
|
<ROW Component="AI_ExePath" ComponentId="{8D009995-D5B9-4E68-A969-45A06F69ACB8}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
|
||||||
<ROW Component="POWRPROF.dll" ComponentId="{65828A9D-101E-433C-82E5-11290FDB7054}" Directory_="APPDIR" Attributes="0" KeyPath="POWRPROF.dll"/>
|
<ROW Component="CurrentVersion" ComponentId="{1A0BFEFD-F9D9-4861-93AC-D9717B7A635E}" Directory_="APPDIR" Attributes="4" KeyPath="CurrentVersion"/>
|
||||||
<ROW Component="PyWinTypes26.dll" ComponentId="{51E80B3A-C753-48CB-B7A4-65610CC49E1F}" Directory_="APPDIR" Attributes="0" KeyPath="PyWinTypes26.dll"/>
|
|
||||||
<ROW Component="QtCore4.dll" ComponentId="{5BB6B87D-BE40-4240-B529-23A303942E18}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
|
<ROW Component="QtCore4.dll" ComponentId="{5BB6B87D-BE40-4240-B529-23A303942E18}" Directory_="APPDIR" Attributes="0" KeyPath="QtCore4.dll"/>
|
||||||
<ROW Component="QtGui4.dll" ComponentId="{EF519048-F252-4FA0-9875-A6B45C7F3020}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
|
<ROW Component="QtGui4.dll" ComponentId="{EF519048-F252-4FA0-9875-A6B45C7F3020}" Directory_="APPDIR" Attributes="0" KeyPath="QtGui4.dll"/>
|
||||||
<ROW Component="SHLWAPI.dll" ComponentId="{11CA10DE-F6AF-4EC7-B5B9-EE1E9D08A7B0}" Directory_="APPDIR" Attributes="0" KeyPath="SHLWAPI.dll"/>
|
|
||||||
<ROW Component="SHORTCUTDIR" ComponentId="{29E7E841-7820-418B-8542-7F8CCC9777A8}" Directory_="SHORTCUTDIR" Attributes="0"/>
|
<ROW Component="SHORTCUTDIR" ComponentId="{29E7E841-7820-418B-8542-7F8CCC9777A8}" Directory_="SHORTCUTDIR" Attributes="0"/>
|
||||||
<ROW Component="bz2.pyd" ComponentId="{F7FDAE87-233A-45B0-8976-021B8264E176}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
|
<ROW Component="bz2.pyd" ComponentId="{F7FDAE87-233A-45B0-8976-021B8264E176}" Directory_="APPDIR" Attributes="0" KeyPath="bz2.pyd" Type="0"/>
|
||||||
<ROW Component="credits.htm" ComponentId="{CF738E4F-8E05-4B2D-99FD-A035FC25D710}" Directory_="help_DIR" Attributes="0" KeyPath="credits.htm" Type="0"/>
|
<ROW Component="credits.htm" ComponentId="{CF738E4F-8E05-4B2D-99FD-A035FC25D710}" Directory_="help_DIR" Attributes="0" KeyPath="credits.htm" Type="0"/>
|
||||||
<ROW Component="dupeGuru_PE.exe" ComponentId="{4A31F2AE-F42E-4B0F-BC4D-A09F312D469B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_PE.exe"/>
|
<ROW Component="dupeGuru_PE.exe" ComponentId="{4A31F2AE-F42E-4B0F-BC4D-A09F312D469B}" Directory_="APPDIR" Attributes="0" KeyPath="dupeGuru_PE.exe"/>
|
||||||
<ROW Component="hs_title.png" ComponentId="{ACCD16EE-68BE-4EDA-AE6B-013621EAB3B2}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
|
<ROW Component="hs_title.png" ComponentId="{ACCD16EE-68BE-4EDA-AE6B-013621EAB3B2}" Directory_="images_DIR" Attributes="0" KeyPath="hs_title.png" Type="0"/>
|
||||||
<ROW Component="init_.py" ComponentId="{DBD0E45F-6773-431E-A716-5518A0B8C54E}" Directory_="gen_py_DIR" Attributes="0" KeyPath="init_.py" Type="0"/>
|
|
||||||
<ROW Component="python26.dll" ComponentId="{20529423-B717-4C53-AE3A-B82E53207A62}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
|
<ROW Component="python26.dll" ComponentId="{20529423-B717-4C53-AE3A-B82E53207A62}" Directory_="APPDIR" Attributes="0" KeyPath="python26.dll"/>
|
||||||
<ROW Component="pythoncom26.dll" ComponentId="{46CE0516-582F-44F0-86D7-7F2F5F7458C3}" Directory_="APPDIR" Attributes="0" KeyPath="pythoncom26.dll"/>
|
|
||||||
<ROW Component="qcncodecs4.dll" ComponentId="{629EB310-99C7-4304-91DB-9134E521A83F}" Directory_="codecs_DIR" Attributes="0" KeyPath="qcncodecs4.dll"/>
|
|
||||||
<ROW Component="qgif4.dll" ComponentId="{788DB84F-6216-4334-B92E-9992FD02A31A}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qgif4.dll"/>
|
|
||||||
<ROW Component="qico4.dll" ComponentId="{CED777C8-E8F6-421F-B533-91A7B5310BCF}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qico4.dll"/>
|
|
||||||
<ROW Component="qjpcodecs4.dll" ComponentId="{9A112855-BA4A-4C41-BCA0-20D564A2A7C2}" Directory_="codecs_DIR" Attributes="0" KeyPath="qjpcodecs4.dll"/>
|
|
||||||
<ROW Component="qjpeg4.dll" ComponentId="{0FC6A53E-6DDC-4833-944B-00944A45FB62}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qjpeg4.dll"/>
|
|
||||||
<ROW Component="qkrcodecs4.dll" ComponentId="{5EE53027-96D1-4ABA-A2F6-507A7D85EA44}" Directory_="codecs_DIR" Attributes="0" KeyPath="qkrcodecs4.dll"/>
|
|
||||||
<ROW Component="qmng4.dll" ComponentId="{5E3A9C7B-F545-4EF5-B083-2A29E54784BE}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qmng4.dll"/>
|
|
||||||
<ROW Component="qsvg4.dll" ComponentId="{590998F6-2A55-48DC-A83A-AABC75EF7F99}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qsvg4.dll"/>
|
|
||||||
<ROW Component="qsvgicon4.dll" ComponentId="{0440300E-1BAE-49C5-8575-AF43C2557271}" Directory_="iconengines_DIR" Attributes="0" KeyPath="qsvgicon4.dll"/>
|
|
||||||
<ROW Component="qtaccessiblecompatwidgets4.dll" ComponentId="{217EE5AA-868E-4DDA-B374-E1007D54C1CF}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblecompatwidgets4.dll"/>
|
|
||||||
<ROW Component="qtaccessiblewidgets4.dll" ComponentId="{74F17E1E-D2BC-4C85-A5B9-A093D4AFC840}" Directory_="accessible_DIR" Attributes="0" KeyPath="qtaccessiblewidgets4.dll"/>
|
|
||||||
<ROW Component="qtiff4.dll" ComponentId="{545FB567-9E3A-4E44-85A0-74446ABB8FC8}" Directory_="imageformats_DIR" Attributes="0" KeyPath="qtiff4.dll"/>
|
|
||||||
<ROW Component="qtwcodecs4.dll" ComponentId="{59FB6978-93A0-4DD6-A617-FE6460CDE4DB}" Directory_="codecs_DIR" Attributes="0" KeyPath="qtwcodecs4.dll"/>
|
|
||||||
<ROW Component="sqlite3.dll" ComponentId="{B5D4B746-A65D-4F4A-B31A-D1C3C7F59952}" Directory_="APPDIR" Attributes="0" KeyPath="sqlite3.dll"/>
|
<ROW Component="sqlite3.dll" ComponentId="{B5D4B746-A65D-4F4A-B31A-D1C3C7F59952}" Directory_="APPDIR" Attributes="0" KeyPath="sqlite3.dll"/>
|
||||||
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
|
<ROW Component="updater.exe" ComponentId="{D1DDB6CB-B336-4112-BC40-1ABD36C3ABDA}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_PE.exe AIShRegAnswer SHORTCUTDIR bz2.pyd POWRPROF.dll python26.dll pythoncom26.dll PyWinTypes26.dll qtaccessiblewidgets4.dll qcncodecs4.dll qjpcodecs4.dll qkrcodecs4.dll qtwcodecs4.dll qsvgicon4.dll qgif4.dll qico4.dll qjpeg4.dll qmng4.dll qsvg4.dll qtiff4.dll QtCore4.dll QtGui4.dll SHLWAPI.dll sqlite3.dll AI_ExePath credits.htm hs_title.png init_.py qtaccessiblecompatwidgets4.dll"/>
|
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru_PE.exe AIShRegAnswer SHORTCUTDIR bz2.pyd python26.dll QtCore4.dll QtGui4.dll sqlite3.dll AI_ExePath credits.htm hs_title.png CurrentVersion"/>
|
||||||
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
||||||
<ROW File="PIL._imaging.pyd" Component_="bz2.pyd" FileName="PIL_im~1.pyd|PIL._imaging.pyd" Attributes="0" SourcePath="dist\PIL._imaging.pyd" SelfReg="false" Sequence="4"/>
|
<ROW File="PIL._imaging.pyd" Component_="bz2.pyd" FileName="PIL_im~1.pyd|PIL._imaging.pyd" Attributes="0" SourcePath="dist\PIL._imaging.pyd" SelfReg="false" Sequence="4"/>
|
||||||
<ROW File="POWRPROF.dll" Component_="POWRPROF.dll" FileName="POWRPROF.dll" Attributes="0" SourcePath="dist\POWRPROF.dll" SelfReg="false" Sequence="5"/>
|
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="6"/>
|
||||||
<ROW File="PyQt4.QtCore.pyd" Component_="bz2.pyd" FileName="PyQt4Q~1.pyd|PyQt4.QtCore.pyd" Attributes="0" SourcePath="dist\PyQt4.QtCore.pyd" SelfReg="false" Sequence="7"/>
|
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="7"/>
|
||||||
<ROW File="PyQt4.QtGui.pyd" Component_="bz2.pyd" FileName="PyQt4Q~2.pyd|PyQt4.QtGui.pyd" Attributes="0" SourcePath="dist\PyQt4.QtGui.pyd" SelfReg="false" Sequence="8"/>
|
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="9"/>
|
||||||
<ROW File="PyWinTypes26.dll" Component_="PyWinTypes26.dll" FileName="PyWinT~1.dll|PyWinTypes26.dll" Attributes="0" SourcePath="dist\PyWinTypes26.dll" SelfReg="false" Sequence="11"/>
|
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="10"/>
|
||||||
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="24"/>
|
<ROW File="block.pyd" Component_="bz2.pyd" FileName="_block.pyd" Attributes="0" SourcePath="dist\_block.pyd" SelfReg="false" Sequence="15"/>
|
||||||
<ROW File="QtGui4.dll" Component_="QtGui4.dll" FileName="QtGui4.dll" Attributes="0" SourcePath="dist\QtGui4.dll" SelfReg="false" Sequence="25"/>
|
|
||||||
<ROW File="SHLWAPI.dll" Component_="SHLWAPI.dll" FileName="SHLWAPI.dll" Attributes="0" SourcePath="dist\SHLWAPI.dll" SelfReg="false" Sequence="27"/>
|
|
||||||
<ROW File="block.pyd" Component_="bz2.pyd" FileName="_block.pyd" Attributes="0" SourcePath="dist\_block.pyd" SelfReg="false" Sequence="35"/>
|
|
||||||
<ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
|
<ROW File="bz2.pyd" Component_="bz2.pyd" FileName="bz2.pyd" Attributes="0" SourcePath="dist\bz2.pyd" SelfReg="false" Sequence="3"/>
|
||||||
<ROW File="core_pe._block.pyd" Component_="bz2.pyd" FileName="core_p~1.pyd|core_pe._block.pyd" Attributes="0" SourcePath="dist\core_pe._block.pyd" SelfReg="false" Sequence="43"/>
|
<ROW File="core_pe._block.pyd" Component_="bz2.pyd" FileName="core_p~1.pyd|core_pe._block.pyd" Attributes="0" SourcePath="dist\core_pe._block.pyd" SelfReg="false" Sequence="22"/>
|
||||||
<ROW File="core_pe._cache.pyd" Component_="bz2.pyd" FileName="core_p~2.pyd|core_pe._cache.pyd" Attributes="0" SourcePath="dist\core_pe._cache.pyd" SelfReg="false" Sequence="44"/>
|
<ROW File="core_pe._cache.pyd" Component_="bz2.pyd" FileName="core_p~2.pyd|core_pe._cache.pyd" Attributes="0" SourcePath="dist\core_pe._cache.pyd" SelfReg="false" Sequence="23"/>
|
||||||
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="45"/>
|
<ROW File="credits.htm" Component_="credits.htm" FileName="credits.htm" Attributes="0" SourcePath="dist\help\credits.htm" SelfReg="false" Sequence="24"/>
|
||||||
<ROW File="ctypes.pyd" Component_="bz2.pyd" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" SelfReg="false" Sequence="36"/>
|
<ROW File="ctypes.pyd" Component_="bz2.pyd" FileName="_ctypes.pyd" Attributes="0" SourcePath="dist\_ctypes.pyd" SelfReg="false" Sequence="16"/>
|
||||||
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="46"/>
|
<ROW File="directories.htm" Component_="credits.htm" FileName="direct~1.htm|directories.htm" Attributes="0" SourcePath="dist\help\directories.htm" SelfReg="false" Sequence="25"/>
|
||||||
<ROW File="dupeGuru_PE.exe" Component_="dupeGuru_PE.exe" FileName="dupeGu~2.exe|dupeGuru PE.exe" Attributes="0" SourcePath="dist\dupeGuru PE.exe" SelfReg="false" Sequence="2"/>
|
<ROW File="dupeGuru_PE.exe" Component_="dupeGuru_PE.exe" FileName="dupeGu~2.exe|dupeGuru PE.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru PE.exe" SelfReg="false" Sequence="2"/>
|
||||||
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="47"/>
|
<ROW File="faq.htm" Component_="credits.htm" FileName="faq.htm" Attributes="0" SourcePath="dist\help\faq.htm" SelfReg="false" Sequence="26"/>
|
||||||
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="48"/>
|
<ROW File="hardcoded.css" Component_="credits.htm" FileName="hardco~1.css|hardcoded.css" Attributes="0" SourcePath="dist\help\hardcoded.css" SelfReg="false" Sequence="27"/>
|
||||||
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="37"/>
|
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="17"/>
|
||||||
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="49"/>
|
<ROW File="hs_title.png" Component_="hs_title.png" FileName="hs_title.png" Attributes="0" SourcePath="dist\help\images\hs_title.png" SelfReg="false" Sequence="28"/>
|
||||||
<ROW File="init_.py" Component_="init_.py" FileName="__init__.py" Attributes="0" SourcePath="dist\support\gen_py\__init__.py" SelfReg="false" Sequence="56"/>
|
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="29"/>
|
||||||
<ROW File="intro.htm" Component_="credits.htm" FileName="intro.htm" Attributes="0" SourcePath="dist\help\intro.htm" SelfReg="false" Sequence="50"/>
|
<ROW File="lxml.etree.pyd" Component_="bz2.pyd" FileName="lxmlet~1.pyd|lxml.etree.pyd" Attributes="0" SourcePath="dist\lxml.etree.pyd" SelfReg="false" Sequence="35"/>
|
||||||
<ROW File="multiprocessing.pyd" Component_="bz2.pyd" FileName="_multi~1.pyd|_multiprocessing.pyd" Attributes="0" SourcePath="dist\_multiprocessing.pyd" SelfReg="false" Sequence="38"/>
|
<ROW File="multiprocessing.pyd" Component_="bz2.pyd" FileName="_multi~1.pyd|_multiprocessing.pyd" Attributes="0" SourcePath="dist\_multiprocessing.pyd" SelfReg="false" Sequence="18"/>
|
||||||
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="51"/>
|
<ROW File="power_marker.htm" Component_="credits.htm" FileName="power_~1.htm|power_marker.htm" Attributes="0" SourcePath="dist\help\power_marker.htm" SelfReg="false" Sequence="30"/>
|
||||||
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="52"/>
|
<ROW File="preferences.htm" Component_="credits.htm" FileName="prefer~1.htm|preferences.htm" Attributes="0" SourcePath="dist\help\preferences.htm" SelfReg="false" Sequence="31"/>
|
||||||
<ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="6"/>
|
<ROW File="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="5"/>
|
||||||
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="9"/>
|
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="8"/>
|
||||||
<ROW File="pythoncom26.dll" Component_="pythoncom26.dll" FileName="python~1.dll|pythoncom26.dll" Attributes="0" SourcePath="dist\pythoncom26.dll" SelfReg="false" Sequence="10"/>
|
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="32"/>
|
||||||
<ROW File="qcncodecs4.dll" Component_="qcncodecs4.dll" FileName="qcncod~1.dll|qcncodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qcncodecs4.dll" SelfReg="false" Sequence="13"/>
|
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="33"/>
|
||||||
<ROW File="qgif4.dll" Component_="qgif4.dll" FileName="qgif4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qgif4.dll" SelfReg="false" Sequence="18"/>
|
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="11"/>
|
||||||
<ROW File="qico4.dll" Component_="qico4.dll" FileName="qico4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qico4.dll" SelfReg="false" Sequence="19"/>
|
<ROW File="send2trash_win.pyd" Component_="bz2.pyd" FileName="_send2~1.pyd|_send2trash_win.pyd" Attributes="0" SourcePath="dist\_send2trash_win.pyd" SelfReg="false" Sequence="36"/>
|
||||||
<ROW File="qjpcodecs4.dll" Component_="qjpcodecs4.dll" FileName="qjpcod~1.dll|qjpcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qjpcodecs4.dll" SelfReg="false" Sequence="14"/>
|
<ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="12"/>
|
||||||
<ROW File="qjpeg4.dll" Component_="qjpeg4.dll" FileName="qjpeg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qjpeg4.dll" SelfReg="false" Sequence="20"/>
|
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="19"/>
|
||||||
<ROW File="qkrcodecs4.dll" Component_="qkrcodecs4.dll" FileName="qkrcod~1.dll|qkrcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qkrcodecs4.dll" SelfReg="false" Sequence="15"/>
|
<ROW File="sqlite3.dll" Component_="sqlite3.dll" FileName="sqlite3.dll" Attributes="0" SourcePath="dist\sqlite3.dll" SelfReg="false" Sequence="13"/>
|
||||||
<ROW File="qmng4.dll" Component_="qmng4.dll" FileName="qmng4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qmng4.dll" SelfReg="false" Sequence="21"/>
|
<ROW File="sqlite3.pyd" Component_="bz2.pyd" FileName="_sqlite3.pyd" Attributes="0" SourcePath="dist\_sqlite3.pyd" SelfReg="false" Sequence="20"/>
|
||||||
<ROW File="qsvg4.dll" Component_="qsvg4.dll" FileName="qsvg4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qsvg4.dll" SelfReg="false" Sequence="22"/>
|
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="21"/>
|
||||||
<ROW File="qsvgicon4.dll" Component_="qsvgicon4.dll" FileName="qsvgic~1.dll|qsvgicon4.dll" Attributes="0" SourcePath="dist\qt4_plugins\iconengines\qsvgicon4.dll" SelfReg="false" Sequence="17"/>
|
<ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="14"/>
|
||||||
<ROW File="qtaccessiblecompatwidgets4.dll" Component_="qtaccessiblecompatwidgets4.dll" FileName="qtacce~1.dll|qtaccessiblecompatwidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblecompatwidgets4.dll" SelfReg="false" Sequence="57"/>
|
|
||||||
<ROW File="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="12"/>
|
|
||||||
<ROW File="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="23"/>
|
|
||||||
<ROW File="qtwcodecs4.dll" Component_="qtwcodecs4.dll" FileName="qtwcod~1.dll|qtwcodecs4.dll" Attributes="0" SourcePath="dist\qt4_plugins\codecs\qtwcodecs4.dll" SelfReg="false" Sequence="16"/>
|
|
||||||
<ROW File="quick_start.htm" Component_="credits.htm" FileName="quick_~1.htm|quick_start.htm" Attributes="0" SourcePath="dist\help\quick_start.htm" SelfReg="false" Sequence="53"/>
|
|
||||||
<ROW File="results.htm" Component_="credits.htm" FileName="results.htm" Attributes="0" SourcePath="dist\help\results.htm" SelfReg="false" Sequence="54"/>
|
|
||||||
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="26"/>
|
|
||||||
<ROW File="sip.pyd" Component_="bz2.pyd" FileName="sip.pyd" Attributes="0" SourcePath="dist\sip.pyd" SelfReg="false" Sequence="28"/>
|
|
||||||
<ROW File="socket.pyd" Component_="bz2.pyd" FileName="_socket.pyd" Attributes="0" SourcePath="dist\_socket.pyd" SelfReg="false" Sequence="39"/>
|
|
||||||
<ROW File="sqlite3.dll" Component_="sqlite3.dll" FileName="sqlite3.dll" Attributes="0" SourcePath="dist\sqlite3.dll" SelfReg="false" Sequence="29"/>
|
|
||||||
<ROW File="sqlite3.pyd" Component_="bz2.pyd" FileName="_sqlite3.pyd" Attributes="0" SourcePath="dist\_sqlite3.pyd" SelfReg="false" Sequence="40"/>
|
|
||||||
<ROW File="ssl.pyd" Component_="bz2.pyd" FileName="_ssl.pyd" Attributes="0" SourcePath="dist\_ssl.pyd" SelfReg="false" Sequence="41"/>
|
|
||||||
<ROW File="unicodedata.pyd" Component_="bz2.pyd" FileName="unicod~1.pyd|unicodedata.pyd" Attributes="0" SourcePath="dist\unicodedata.pyd" SelfReg="false" Sequence="30"/>
|
|
||||||
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>updater.exe" SelfReg="false" Sequence="1" DigSign="true"/>
|
||||||
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="55"/>
|
<ROW File="versions.htm" Component_="credits.htm" FileName="versions.htm" Attributes="0" SourcePath="dist\help\versions.htm" SelfReg="false" Sequence="34"/>
|
||||||
<ROW File="win32api.pyd" Component_="bz2.pyd" FileName="win32api.pyd" Attributes="0" SourcePath="dist\win32api.pyd" SelfReg="false" Sequence="31"/>
|
|
||||||
<ROW File="win32com.shell.shell.pyd" Component_="bz2.pyd" FileName="win32c~1.pyd|win32com.shell.shell.pyd" Attributes="0" SourcePath="dist\win32com.shell.shell.pyd" SelfReg="false" Sequence="32"/>
|
|
||||||
<ROW File="win32sysloader.pyd" Component_="bz2.pyd" FileName="_win32~1.pyd|_win32sysloader.pyd" Attributes="0" SourcePath="dist\_win32sysloader.pyd" SelfReg="false" Sequence="42"/>
|
|
||||||
<ROW File="win32trace.pyd" Component_="bz2.pyd" FileName="win32t~1.pyd|win32trace.pyd" Attributes="0" SourcePath="dist\win32trace.pyd" SelfReg="false" Sequence="33"/>
|
|
||||||
<ROW File="win32ui.pyd" Component_="bz2.pyd" FileName="win32ui.pyd" Attributes="0" SourcePath="dist\win32ui.pyd" SelfReg="false" Sequence="34"/>
|
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
||||||
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_pe_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
|
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageName="install\dupeguru_pe_win_[|ProductVersion]" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" CreateMd5="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\install" ExtUI="true"/>
|
||||||
@@ -261,6 +216,7 @@
|
|||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
||||||
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
||||||
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
||||||
|
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
||||||
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
<ROW Shortcut="Check_for_update" Directory_="SHORTCUTDIR" Name="Checkf~2|Check for update" Component_="updater.exe" Target="[#updater.exe]" Arguments="/checknow" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ import base.dg_rc
|
|||||||
|
|
||||||
from app import DupeGuru
|
from app import DupeGuru
|
||||||
|
|
||||||
# This is a workaround for a pyinstaller problem where compiled dupeguru can't read tiff files
|
if sys.platform == 'win32':
|
||||||
from PIL import TiffImagePlugin, TiffTags
|
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__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|||||||
@@ -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])])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@@ -24,9 +24,10 @@ class Directories(DirectoriesBase):
|
|||||||
return STATE_EXCLUDED
|
return STATE_EXCLUDED
|
||||||
|
|
||||||
class DupeGuru(DupeGuruBase):
|
class DupeGuru(DupeGuruBase):
|
||||||
|
EDITION = 'se'
|
||||||
LOGO_NAME = 'logo_se'
|
LOGO_NAME = 'logo_se'
|
||||||
NAME = 'dupeGuru'
|
NAME = 'dupeGuru'
|
||||||
VERSION = '2.9.2'
|
VERSION = '2.10.0'
|
||||||
DELTA_COLUMNS = frozenset([2, 4, 5])
|
DELTA_COLUMNS = frozenset([2, 4, 5])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@@ -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'))
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<DOCUMENT type="Advanced Installer" CreateVersion="4.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">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
||||||
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
||||||
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
<ROW Property="AI_SHORTCUTSREG" Value="0|0|0|"/>
|
||||||
@@ -30,23 +30,19 @@
|
|||||||
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
||||||
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
|
<ROW Directory="accessible_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="access~1|accessible"/>
|
||||||
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
|
<ROW Directory="codecs_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="codecs"/>
|
||||||
<ROW Directory="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="iconengines_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="iconen~1|iconengines"/>
|
||||||
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
|
<ROW Directory="imageformats_DIR" Directory_Parent="qt4_plugins_DIR" DefaultDir="imagef~1|imageformats"/>
|
||||||
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
|
<ROW Directory="qt4_plugins_DIR" Directory_Parent="APPDIR" DefaultDir="qt4_pl~1|qt4_plugins"/>
|
||||||
<ROW Directory="support_DIR" Directory_Parent="APPDIR" DefaultDir="support"/>
|
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||||
<ROW Component="AIShRegAnswer" ComponentId="{775090B3-2E56-40F5-9DD8-24A2F82DA601}" Directory_="APPDIR" Attributes="4" KeyPath="AIShRegAnswer"/>
|
<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="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="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="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="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="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="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="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="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"/>
|
<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="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="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="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="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="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="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"/>
|
<ROW Component="updater.exe" ComponentId="{CB63C33D-EB1B-420A-8BAA-CD380923F12B}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="updater.exe dupeGuru.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"/>
|
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
<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.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="11"/>
|
<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="5"/>
|
<ROW File="QtCore4.dll" Component_="QtCore4.dll" FileName="QtCore4.dll" Attributes="0" SourcePath="dist\QtCore4.dll" SelfReg="false" Sequence="4"/>
|
||||||
<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="5"/>
|
||||||
<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="6"/>
|
||||||
<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" Version="65535.65535.65535.65535" Attributes="0" SourcePath="dist\dupeGuru.exe" SelfReg="false" Sequence="2"/>
|
||||||
<ROW File="dupeGuru.exe" Component_="dupeGuru.exe" FileName="dupeGuru.exe" 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="31"/>
|
<ROW File="hashlib.pyd" Component_="bz2.pyd" FileName="_hashlib.pyd" Attributes="0" SourcePath="dist\_hashlib.pyd" SelfReg="false" Sequence="24"/>
|
||||||
<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="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="pyexpat.pyd" Component_="bz2.pyd" FileName="pyexpat.pyd" Attributes="0" SourcePath="dist\pyexpat.pyd" SelfReg="false" Sequence="9"/>
|
|
||||||
<ROW File="python26.dll" Component_="python26.dll" FileName="python26.dll" Attributes="0" SourcePath="dist\python26.dll" SelfReg="false" Sequence="3"/>
|
<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="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="15"/>
|
||||||
<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="16"/>
|
||||||
<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="11"/>
|
||||||
<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="17"/>
|
||||||
<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="12"/>
|
||||||
<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="18"/>
|
||||||
<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="19"/>
|
||||||
<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="14"/>
|
||||||
<ROW File="qsvgicon4.dll" Component_="qsvgicon4.dll" FileName="qsvgic~1.dll|qsvgicon4.dll" Attributes="0" SourcePath="dist\qt4_plugins\iconengines\qsvgicon4.dll" SelfReg="false" Sequence="17"/>
|
<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="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="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="20"/>
|
||||||
<ROW File="qtaccessiblewidgets4.dll" Component_="qtaccessiblewidgets4.dll" FileName="qtacce~2.dll|qtaccessiblewidgets4.dll" Attributes="0" SourcePath="dist\qt4_plugins\accessible\qtaccessiblewidgets4.dll" SelfReg="false" Sequence="12"/>
|
<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="qtiff4.dll" Component_="qtiff4.dll" FileName="qtiff4.dll" Attributes="0" SourcePath="dist\qt4_plugins\imageformats\qtiff4.dll" SelfReg="false" Sequence="23"/>
|
<ROW File="select.pyd" Component_="bz2.pyd" FileName="select.pyd" Attributes="0" SourcePath="dist\select.pyd" SelfReg="false" Sequence="21"/>
|
||||||
<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="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="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="22"/>
|
||||||
<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="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="26"/>
|
||||||
<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="23"/>
|
||||||
<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="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>updater.exe" SelfReg="false" Sequence="1"/>
|
<ROW File="updater.exe" Component_="updater.exe" FileName="updater.exe" Attributes="0" SourcePath="<AI_HOME>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>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
|
<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]"/>
|
<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">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
|
||||||
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
<ROW Registry="AIShRegAnswer" Root="-1" Key="Software\Caphyon\Advanced Installer\Installs\[ProductCode]" Name="AIShRegAnswer" Value="[AI_SHORTCUTSREG]" Component_="AIShRegAnswer"/>
|
||||||
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
|
||||||
|
<ROW Registry="CurrentVersion" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="CurrentVersion" Value="[ProductVersion]" Component_="CurrentVersion"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
||||||
<ROW Shortcut="Check_for_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="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" 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"/>
|
<ROW Shortcut="dupeGuru_1" Directory_="SHORTCUTDIR" Name="dupeGuru" Component_="dupeGuru.exe" Target="[#dupeGuru.exe]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
|||||||
setchecked(self.ignoreSmallFilesBox, prefs.ignore_small_files)
|
setchecked(self.ignoreSmallFilesBox, prefs.ignore_small_files)
|
||||||
self.sizeThresholdEdit.setText(unicode(prefs.small_file_threshold))
|
self.sizeThresholdEdit.setText(unicode(prefs.small_file_threshold))
|
||||||
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
|
||||||
|
self.customCommandEdit.setText(prefs.custom_command)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
prefs = self.app.prefs
|
prefs = self.app.prefs
|
||||||
@@ -64,6 +65,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
|
|||||||
prefs.ignore_small_files = ischecked(self.ignoreSmallFilesBox)
|
prefs.ignore_small_files = ischecked(self.ignoreSmallFilesBox)
|
||||||
prefs.small_file_threshold = tryint(self.sizeThresholdEdit.text())
|
prefs.small_file_threshold = tryint(self.sizeThresholdEdit.text())
|
||||||
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
|
||||||
|
prefs.custom_command = unicode(self.customCommandEdit.text())
|
||||||
|
|
||||||
def resetToDefaults(self):
|
def resetToDefaults(self):
|
||||||
self.load(preferences.Preferences())
|
self.load(preferences.Preferences())
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>294</width>
|
<width>308</width>
|
||||||
<height>296</height>
|
<height>361</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,1">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
@@ -170,110 +170,93 @@
|
|||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
<height>134</height>
|
<height>136</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QCheckBox" name="wordWeightingBox">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<property name="geometry">
|
<item>
|
||||||
<rect>
|
<widget class="QCheckBox" name="wordWeightingBox">
|
||||||
<x>0</x>
|
<property name="text">
|
||||||
<y>0</y>
|
<string>Word weighting</string>
|
||||||
<width>350</width>
|
</property>
|
||||||
<height>21</height>
|
</widget>
|
||||||
</rect>
|
</item>
|
||||||
</property>
|
<item>
|
||||||
<property name="text">
|
<widget class="QCheckBox" name="matchSimilarBox">
|
||||||
<string>Word weighting</string>
|
<property name="text">
|
||||||
</property>
|
<string>Match similar words</string>
|
||||||
</widget>
|
</property>
|
||||||
<widget class="QCheckBox" name="matchSimilarBox">
|
</widget>
|
||||||
<property name="geometry">
|
</item>
|
||||||
<rect>
|
<item>
|
||||||
<x>0</x>
|
<widget class="QCheckBox" name="mixFileKindBox">
|
||||||
<y>22</y>
|
<property name="text">
|
||||||
<width>350</width>
|
<string>Can mix file kind</string>
|
||||||
<height>21</height>
|
</property>
|
||||||
</rect>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Match similar words</string>
|
<widget class="QCheckBox" name="useRegexpBox">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Use regular expressions when filtering</string>
|
||||||
<widget class="QCheckBox" name="mixFileKindBox">
|
</property>
|
||||||
<property name="geometry">
|
</widget>
|
||||||
<rect>
|
</item>
|
||||||
<x>0</x>
|
<item>
|
||||||
<y>44</y>
|
<widget class="QCheckBox" name="removeEmptyFoldersBox">
|
||||||
<width>350</width>
|
<property name="text">
|
||||||
<height>21</height>
|
<string>Remove empty folders on delete or move</string>
|
||||||
</rect>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Can mix file kind</string>
|
<item>
|
||||||
</property>
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
</widget>
|
<item>
|
||||||
<widget class="QCheckBox" name="useRegexpBox">
|
<widget class="QCheckBox" name="ignoreSmallFilesBox">
|
||||||
<property name="geometry">
|
<property name="text">
|
||||||
<rect>
|
<string>Ignore files smaller than</string>
|
||||||
<x>0</x>
|
</property>
|
||||||
<y>66</y>
|
</widget>
|
||||||
<width>350</width>
|
</item>
|
||||||
<height>21</height>
|
<item>
|
||||||
</rect>
|
<widget class="QLineEdit" name="sizeThresholdEdit">
|
||||||
</property>
|
<property name="sizePolicy">
|
||||||
<property name="text">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<string>Use regular expressions when filtering</string>
|
<horstretch>0</horstretch>
|
||||||
</property>
|
<verstretch>0</verstretch>
|
||||||
</widget>
|
</sizepolicy>
|
||||||
<widget class="QCheckBox" name="removeEmptyFoldersBox">
|
</property>
|
||||||
<property name="geometry">
|
<property name="maximumSize">
|
||||||
<rect>
|
<size>
|
||||||
<x>0</x>
|
<width>50</width>
|
||||||
<y>88</y>
|
<height>16777215</height>
|
||||||
<width>350</width>
|
</size>
|
||||||
<height>21</height>
|
</property>
|
||||||
</rect>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Remove empty folders on delete or move</string>
|
<widget class="QLabel" name="label_6">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>KB</string>
|
||||||
<widget class="QCheckBox" name="ignoreSmallFilesBox">
|
</property>
|
||||||
<property name="geometry">
|
</widget>
|
||||||
<rect>
|
</item>
|
||||||
<x>0</x>
|
<item>
|
||||||
<y>110</y>
|
<spacer name="horizontalSpacer">
|
||||||
<width>171</width>
|
<property name="orientation">
|
||||||
<height>21</height>
|
<enum>Qt::Horizontal</enum>
|
||||||
</rect>
|
</property>
|
||||||
</property>
|
<property name="sizeHint" stdset="0">
|
||||||
<property name="text">
|
<size>
|
||||||
<string>Ignore files smaller than</string>
|
<width>40</width>
|
||||||
</property>
|
<height>20</height>
|
||||||
</widget>
|
</size>
|
||||||
<widget class="QLineEdit" name="sizeThresholdEdit">
|
</property>
|
||||||
<property name="geometry">
|
</spacer>
|
||||||
<rect>
|
</item>
|
||||||
<x>170</x>
|
</layout>
|
||||||
<y>110</y>
|
</item>
|
||||||
<width>51</width>
|
</layout>
|
||||||
<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>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -324,6 +307,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ import base.dg_rc
|
|||||||
|
|
||||||
from app import DupeGuru
|
from app import DupeGuru
|
||||||
|
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import base.cxfreeze_fix
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.setWindowIcon(QIcon(QPixmap(":/logo_se")))
|
app.setWindowIcon(QIcon(QPixmap(":/logo_se")))
|
||||||
|
|||||||
@@ -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])])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user