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

Compare commits

..

49 Commits

Author SHA1 Message Date
hsoft
b8bb40de62 dgme cocoa: v5.7.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40271
2009-12-18 13:04:30 +00:00
hsoft
67dff7fbf2 dgme qt: v5.7.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40270
2009-12-18 12:58:14 +00:00
hsoft
6e226f32fd dgme help: "packagified" help and updated to 5.7.0.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40269
2009-12-18 12:57:47 +00:00
hsoft
cf819dc0a8 dgme qt: fixed gen script and updated FAQ.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40268
2009-12-18 12:21:33 +00:00
hsoft
4f6af6e4dc dgpe cocoa: ugh... fixed typo
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40266
2009-12-16 16:16:22 +00:00
hsoft
a6d2a9b7b3 dgpe cocoa: Fixed a crash happening when iPhoto was never launched.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40265
2009-12-16 15:51:26 +00:00
hsoft
cf34164191 dg cocoa: Since there are problems with the latest pyobjc + py2app + Snow Leopard, I've got to stick with pyobjc1.4 for a while after all...
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40264
2009-12-16 14:48:37 +00:00
hsoft
9a7bb30df4 dgse cocoa: Since there are problems with the latest pyobjc + py2app + Snow Leopard, I've got to stick with pyobjc1.4 for a while after all...
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40263
2009-12-16 14:48:18 +00:00
hsoft
5dc78809b6 dgpe: oops, wrong release date for 1.8.0.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40262
2009-12-16 10:29:02 +00:00
hsoft
2b53a6e7d6 dgpe cocoa: removed the forgotten "-A" flag in bundle generation script.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40261
2009-12-16 10:10:18 +00:00
hsoft
eb82a35e5b dgpe cocoa v1.8.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40260
2009-12-16 09:54:51 +00:00
hsoft
51b14435e0 dgpe qt v1.8.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40259
2009-12-16 09:54:00 +00:00
hsoft
59de033523 [#79 state:fixed] Wrapped PIL's IOError into a warning logging.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40258
2009-12-15 16:54:47 +00:00
hsoft
c9b0a278ca [#78 state:fixed] Wrapped appscript errors, updated error message and the F.A.Q. to give users a clue of what to do.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40257
2009-12-15 16:23:02 +00:00
hsoft
b487189742 [#76 state:fixed] Added combobox painting for the selected item in Directories' State column.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40256
2009-12-15 14:09:13 +00:00
hsoft
d5a60b1580 dgpe cocoa: Made the help file generation process independent from the current work directory. Reverted XCode version of the project to 3.0 so that it can be compiled on Leopard.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40255
2009-12-15 12:52:21 +00:00
hsoft
e2665610e9 dgpe qt: Packagified help.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40254
2009-12-15 11:35:30 +00:00
hsoft
3262ee9938 dgbase: Changed ask_for_reg_code() to askForRegCode() to adapt to change in qtlib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40253
2009-12-15 11:35:08 +00:00
hsoft
2f153003b3 dgpe help: packagified the help folder.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40252
2009-12-15 11:34:21 +00:00
hsoft
6724e710d8 cocoa: Removed fixed toolbar identifiers so that IB 3.0 can compile MainMenu.xib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40248
2009-11-03 13:19:46 +00:00
hsoft
9729e05fe8 se: Fixed changelog for v2.9.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40247
2009-11-03 08:57:43 +00:00
hsoft
686c60b83b se qt v2.9.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40246
2009-11-02 16:59:48 +00:00
hsoft
5fe11f3b3a qt: fixed bug in registration mechanism.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40245
2009-11-02 16:55:36 +00:00
hsoft
30d29c6b34 dgbase qt: fixed rename.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40244
2009-11-02 16:43:05 +00:00
hsoft
fbfb16e77a se cocoa: v2.9.0
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40243
2009-11-02 16:31:16 +00:00
hsoft
7aea384f86 dgse qt: fixed the gen script (didn't gen rc file).
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40242
2009-11-02 16:10:40 +00:00
hsoft
78bef5c3c6 dgme cocoa: adjusted to the detail panel toggling change.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40241
2009-11-02 15:27:54 +00:00
hsoft
5c8d90a57c dgpe cocoa: adjusted to the detail panel toggling change.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40240
2009-11-02 15:22:30 +00:00
hsoft
13dc9ff76d Fixed a bug where the details panel would sometimes not be updated. Also, pushed the details toggling mechanism in dgbase.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40239
2009-11-02 15:16:34 +00:00
hsoft
eb3645d493 Fixed a bug where the mark state of a switched dupe would not be refreshed immediately on Make Selected Reference.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40238
2009-11-02 14:40:29 +00:00
hsoft
0a06e52d65 dg cocoa: adjusted to pyobjc upgrade (functions with multiple return values now require None placeholders to be placed at the places of the output arguments) and removed a couple of forgotten "dupe.parent".
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40237
2009-10-30 16:24:34 +00:00
hsoft
e004c0c2d4 [#10 state:port] Changed the Remove Selected from Results's shortcut to Cmd-Del.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40236
2009-10-30 15:31:18 +00:00
hsoft
6d5f6a0c3c dgpe cocoa: extracted the pref pane from MainMenu.xib into Preferences.xib, Removed code duplicated with dgbase.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40235
2009-10-30 15:26:09 +00:00
hsoft
024e3c380f dgse cocoa: Adjusted to the dgme change (applicationDidFinishLaunching: pushed down and column removal in xib).
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40234
2009-10-30 14:45:38 +00:00
hsoft
06859fe9cd dgme cocoa: extracted the pref pane from MainMenu.xib into Preferences.xib, Removed code duplicated with dgbase. Pushed down AppDelegate.applicationDidFinishLaunching: to dgbase.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40233
2009-10-30 14:40:17 +00:00
hsoft
6392d08584 dgse cocoa: Changed the MainMenu reference to the dgbase one.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40232
2009-10-30 13:27:55 +00:00
hsoft
80a5290bc8 Moved dgse's MainMenu.xib to dgbase
--HG--
rename : se/cocoa/xib/MainMenu.xib => base/cocoa/xib/MainMenu.xib
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40231
2009-10-30 13:26:39 +00:00
hsoft
6b30c88fba dgse cocoa: extracted the pref pane from MainMenu.xib into Preferences.xib, Removed column menu items, which are now generated in the code. other little things.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40230
2009-10-30 12:56:05 +00:00
hsoft
6adce9bf03 dgbase qt: Now uses qtlib's about_box and reg.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40229
2009-10-30 11:41:14 +00:00
hsoft
3c90ad81a7 [#13 state:fixed] Remember window size/pos.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40228
2009-10-30 11:31:40 +00:00
hsoft
484529add0 [#13] Remember window size/pos.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40227
2009-10-30 11:30:32 +00:00
hsoft
600c7906a4 [#13 state:port] On cocoa, the columns were already remembered, so only the window size/pos had to be remembered.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40226
2009-10-30 11:19:32 +00:00
hsoft
f070e90347 [#72 state:fixed] When files are deleted during the scan, don't include them in the grouping phase.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40225
2009-10-30 11:09:04 +00:00
hsoft
88127d8b8d [#9] Implemented directories drag&drop on the QT side.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40224
2009-10-29 12:02:49 +00:00
hsoft
607ab86188 [#9] mapped the delete key to the remove button.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40223
2009-10-28 16:13:50 +00:00
hsoft
c936f9ccc6 [#9 state:port] implemented drag&drop for directories on the cocoa side.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40222
2009-10-28 15:48:19 +00:00
hsoft
d4d8917956 dgpe cocoa: dropped tiger support. Added toolbar creation in the MainMenu nib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40221
2009-10-25 11:46:26 +00:00
hsoft
89bce95c27 dgse cocoa: dropped tiger support. Added toolbar creation in the MainMenu nib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40220
2009-10-25 11:17:13 +00:00
hsoft
f0a38a2b3f dgse cocoa: dropped tiger support. Moved Details.nib and Directories.nib to dgbase. Added toolbar creation in the MainMenu nib.
--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%40219
2009-10-25 10:42:00 +00:00
106 changed files with 15567 additions and 3089 deletions

View File

@@ -9,17 +9,22 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "RecentDirectories.h" #import "RecentDirectories.h"
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
#import "ResultWindow.h"
#import "DetailsPanel.h"
@interface AppDelegateBase : NSObject @interface AppDelegateBase : NSObject
{ {
IBOutlet PyDupeGuruBase *py; IBOutlet PyDupeGuruBase *py;
IBOutlet RecentDirectories *recentDirectories; IBOutlet RecentDirectories *recentDirectories;
IBOutlet NSMenuItem *unlockMenuItem; IBOutlet NSMenuItem *unlockMenuItem;
IBOutlet ResultWindowBase *result;
NSString *_appName; NSString *_appName;
DetailsPanelBase *_detailsPanel;
} }
- (IBAction)unlockApp:(id)sender; - (IBAction)unlockApp:(id)sender;
- (PyDupeGuruBase *)py; - (PyDupeGuruBase *)py;
- (RecentDirectories *)recentDirectories; - (RecentDirectories *)recentDirectories;
- (DetailsPanelBase *)detailsPanel; // Virtual
@end @end

View File

@@ -27,7 +27,7 @@ http://www.hardcoded.net/licenses/hs_license
RegistrationInterface *ri = [[RegistrationInterface alloc] initWithApp:[self py] name:_appName limitDescription:LIMIT_DESC]; RegistrationInterface *ri = [[RegistrationInterface alloc] initWithApp:[self py] name:_appName limitDescription:LIMIT_DESC];
if ([ri enterCode] == NSOKButton) if ([ri enterCode] == NSOKButton)
{ {
NSString *menuTitle = [NSString stringWithFormat:@"Thanks for buying %@",_appName]; NSString *menuTitle = [NSString stringWithFormat:@"Thanks for buying %@!",_appName];
[unlockMenuItem setTitle:menuTitle]; [unlockMenuItem setTitle:menuTitle];
} }
[ri release]; [ri release];
@@ -35,4 +35,25 @@ http://www.hardcoded.net/licenses/hs_license
- (PyDupeGuruBase *)py { return py; } - (PyDupeGuruBase *)py { return py; }
- (RecentDirectories *)recentDirectories { return recentDirectories; } - (RecentDirectories *)recentDirectories { return recentDirectories; }
- (DetailsPanelBase *)detailsPanel { return nil; } // Virtual
/* Delegate */
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[ProgressController mainProgressController] setWorker:py];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
//Restore Columns
NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"];
NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"];
if ([columnsOrder count])
[result restoreColumnsPosition:columnsOrder widths:columnsWidth];
else
[result resetColumnsToDefault:nil];
//Reg stuff
if ([RegistrationInterface showNagWithApp:[self py] name:_appName limitDescription:LIMIT_DESC])
[unlockMenuItem setTitle:[NSString stringWithFormat:@"Thanks for buying %@!",_appName]];
//Restore results
[py loadIgnoreList];
[py loadResults];
}
@end @end

View File

@@ -18,6 +18,7 @@ http://www.hardcoded.net/licenses/hs_license
- (id)initWithPy:(PyApp *)aPy; - (id)initWithPy:(PyApp *)aPy;
- (void)refresh; - (void)refresh;
- (void)toggleVisibility;
/* Notifications */ /* Notifications */
- (void)duplicateSelectionChanged:(NSNotification *)aNotification; - (void)duplicateSelectionChanged:(NSNotification *)aNotification;

View File

@@ -12,7 +12,7 @@ http://www.hardcoded.net/licenses/hs_license
@implementation DetailsPanelBase @implementation DetailsPanelBase
- (id)initWithPy:(PyApp *)aPy - (id)initWithPy:(PyApp *)aPy
{ {
self = [super initWithWindowNibName:@"Details"]; self = [super initWithWindowNibName:@"DetailsPanel"];
[self window]; //So the detailsTable is initialized. [self window]; //So the detailsTable is initialized.
[detailsTable setPy:aPy]; [detailsTable setPy:aPy];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(duplicateSelectionChanged:) name:DuplicateSelectionChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(duplicateSelectionChanged:) name:DuplicateSelectionChangedNotification object:nil];
@@ -24,6 +24,17 @@ http://www.hardcoded.net/licenses/hs_license
[detailsTable reloadData]; [detailsTable reloadData];
} }
- (void)toggleVisibility
{
if ([[self window] isVisible])
[[self window] close];
else
{
[self refresh]; // selection might have changed since last time
[[self window] orderFront:nil];
}
}
/* Notifications */ /* Notifications */
- (void)duplicateSelectionChanged:(NSNotification *)aNotification - (void)duplicateSelectionChanged:(NSNotification *)aNotification
{ {

View File

@@ -11,10 +11,19 @@ http://www.hardcoded.net/licenses/hs_license
#import "Outline.h" #import "Outline.h"
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
@interface DirectoryOutline : OutlineView
{
}
@end
@protocol DirectoryOutlineDelegate
- (void)outlineView:(NSOutlineView *)outlineView addDirectory:(NSString *)directory;
@end
@interface DirectoryPanelBase : NSWindowController @interface DirectoryPanelBase : NSWindowController
{ {
IBOutlet NSPopUpButton *addButtonPopUp; IBOutlet NSPopUpButton *addButtonPopUp;
IBOutlet OutlineView *directories; IBOutlet DirectoryOutline *directories;
IBOutlet NSButton *removeButton; IBOutlet NSButton *removeButton;
PyDupeGuruBase *_py; PyDupeGuruBase *_py;

View File

@@ -11,10 +11,52 @@ http://www.hardcoded.net/licenses/hs_license
#import "Utils.h" #import "Utils.h"
#import "AppDelegate.h" #import "AppDelegate.h"
@implementation DirectoryOutline
- (void)doInit
{
[super doInit];
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [info draggingSourceOperationMask];
pboard = [info draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType])
{
if (sourceDragMask & NSDragOperationLink)
return NSDragOperationLink;
}
return NSDragOperationNone;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
{
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [info draggingSourceOperationMask];
pboard = [info draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] )
{
NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType];
if (!(sourceDragMask & NSDragOperationLink))
return NO;
if (([self delegate] == nil) || (![[self delegate] respondsToSelector:@selector(outlineView:addDirectory:)]))
return NO;
for (NSString *filename in filenames)
[[self delegate] outlineView:self addDirectory:filename];
}
return YES;
}
@end
@implementation DirectoryPanelBase @implementation DirectoryPanelBase
- (id)initWithParentApp:(id)aParentApp - (id)initWithParentApp:(id)aParentApp
{ {
self = [super initWithWindowNibName:@"Directories"]; self = [super initWithWindowNibName:@"DirectoryPanel"];
[self window]; [self window];
AppDelegateBase *app = aParentApp; AppDelegateBase *app = aParentApp;
_py = [app py]; _py = [app py];
@@ -104,10 +146,7 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)toggleVisible:(id)sender - (IBAction)toggleVisible:(id)sender
{ {
if ([[self window] isVisible]) [[self window] makeKeyAndOrderFront:nil];
[[self window] close];
else
[[self window] makeKeyAndOrderFront:nil];
} }
/* Public */ /* Public */
@@ -154,6 +193,11 @@ http://www.hardcoded.net/licenses/hs_license
/* Delegate */ /* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView addDirectory:(NSString *)directory
{
[self addDirectory:directory];
}
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{ {
OVNode *node = item; OVNode *node = item;

View File

@@ -8,7 +8,6 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "Outline.h" #import "Outline.h"
#import "DirectoryPanel.h"
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
@interface MatchesView : OutlineView @interface MatchesView : OutlineView
@@ -20,29 +19,29 @@ http://www.hardcoded.net/licenses/hs_license
@protected @protected
IBOutlet PyDupeGuruBase *py; IBOutlet PyDupeGuruBase *py;
IBOutlet id app; IBOutlet id app;
IBOutlet NSView *actionMenuView;
IBOutlet NSSegmentedControl *deltaSwitch; IBOutlet NSSegmentedControl *deltaSwitch;
IBOutlet NSView *deltaSwitchView;
IBOutlet NSView *filterFieldView;
IBOutlet MatchesView *matches; IBOutlet MatchesView *matches;
IBOutlet NSSegmentedControl *pmSwitch; IBOutlet NSSegmentedControl *pmSwitch;
IBOutlet NSView *pmSwitchView;
IBOutlet NSTextField *stats; IBOutlet NSTextField *stats;
IBOutlet NSMenu *columnsMenu;
BOOL _powerMode; BOOL _powerMode;
BOOL _displayDelta; BOOL _displayDelta;
NSMutableArray *_resultColumns;
NSWindowController *preferencesPanel;
} }
/* Override */
- (NSString *)logoImageName;
/* Helpers */ /* Helpers */
- (void)fillColumnsMenu;
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn;
- (NSArray *)getColumnsOrder; - (NSArray *)getColumnsOrder;
- (NSDictionary *)getColumnsWidth; - (NSDictionary *)getColumnsWidth;
- (NSArray *)getSelected:(BOOL)aDupesOnly; - (NSArray *)getSelected:(BOOL)aDupesOnly;
- (NSArray *)getSelectedPaths:(BOOL)aDupesOnly; - (NSArray *)getSelectedPaths:(BOOL)aDupesOnly;
- (void)initResultColumns;
- (void)updatePySelection; - (void)updatePySelection;
- (void)performPySelection:(NSArray *)aIndexPaths; - (void)performPySelection:(NSArray *)aIndexPaths;
- (void)refreshStats; - (void)refreshStats;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
/* Actions */ /* Actions */
- (IBAction)changeDelta:(id)sender; - (IBAction)changeDelta:(id)sender;
@@ -52,7 +51,11 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)expandAll:(id)sender; - (IBAction)expandAll:(id)sender;
- (IBAction)exportToXHTML:(id)sender; - (IBAction)exportToXHTML:(id)sender;
- (IBAction)moveMarked:(id)sender; - (IBAction)moveMarked:(id)sender;
- (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)switchSelected:(id)sender; - (IBAction)switchSelected:(id)sender;
- (IBAction)toggleColumn:(id)sender;
- (IBAction)toggleDetailsPanel:(id)sender;
- (IBAction)togglePowerMarker:(id)sender; - (IBAction)togglePowerMarker:(id)sender;
/* Notifications */ /* Notifications */

View File

@@ -14,15 +14,6 @@ http://www.hardcoded.net/licenses/hs_license
#import "AppDelegate.h" #import "AppDelegate.h"
#import "Consts.h" #import "Consts.h"
#define tbbDirectories @"tbbDirectories"
#define tbbDetails @"tbbDetail"
#define tbbPreferences @"tbbPreferences"
#define tbbPowerMarker @"tbbPowerMarker"
#define tbbScan @"tbbScan"
#define tbbAction @"tbbAction"
#define tbbDelta @"tbbDelta"
#define tbbFilter @"tbbFilter"
@implementation MatchesView @implementation MatchesView
- (void)keyDown:(NSEvent *)theEvent - (void)keyDown:(NSEvent *)theEvent
{ {
@@ -60,6 +51,9 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib - (void)awakeFromNib
{ {
[self window]; [self window];
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
[self initResultColumns];
[self fillColumnsMenu];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registrationRequired:) name:RegistrationRequired object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registrationRequired:) name:RegistrationRequired object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobCompleted:) name:JobCompletedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil];
@@ -68,13 +62,42 @@ http://www.hardcoded.net/licenses/hs_license
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsUpdated:) name:ResultsUpdatedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsUpdated:) name:ResultsUpdatedNotification object:nil];
} }
/* Virtual */ - (void)dealloc
- (NSString *)logoImageName
{ {
return @"dg_logo32"; [preferencesPanel release];
[super dealloc];
} }
/* Helpers */ /* Helpers */
- (void)fillColumnsMenu
{
// The columns menu is supposed to be empty and initResultColumns must have been called
for (NSTableColumn *col in _resultColumns)
{
NSMenuItem *mi = [columnsMenu addItemWithTitle:[[col headerCell] stringValue] action:@selector(toggleColumn:) keyEquivalent:@""];
[mi setTag:[[col identifier] integerValue]];
[mi setTarget:self];
if ([[matches tableColumns] containsObject:col])
[mi setState:NSOnState];
}
[columnsMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem *mi = [columnsMenu addItemWithTitle:@"Reset to Default" action:@selector(resetColumnsToDefault:) keyEquivalent:@""];
[mi setTarget:self];
}
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn
{
NSNumber *n = [NSNumber numberWithInt:aIdentifier];
NSTableColumn *col = [[NSTableColumn alloc] initWithIdentifier:[n stringValue]];
[col setWidth:aWidth];
[col setEditable:NO];
[[col dataCell] setFont:[[aColumn dataCell] font]];
[[col headerCell] setStringValue:aTitle];
[col setResizingMask:NSTableColumnUserResizingMask];
[col setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:[n stringValue] ascending:YES]];
return col;
}
//Returns an array of identifiers, in order. //Returns an array of identifiers, in order.
- (NSArray *)getColumnsOrder - (NSArray *)getColumnsOrder
{ {
@@ -135,6 +158,40 @@ http://www.hardcoded.net/licenses/hs_license
return r; return r;
} }
- (void)initResultColumns
{
// Virtual
}
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth
{
NSTableColumn *col;
NSString *colId;
NSNumber *width;
NSMenuItem *mi;
//Remove all columns
NSEnumerator *e = [[columnsMenu itemArray] objectEnumerator];
while (mi = [e nextObject])
{
if ([mi state] == NSOnState)
[self toggleColumn:mi];
}
//Add columns and set widths
e = [aColumnsOrder objectEnumerator];
while (colId = [e nextObject])
{
if (![colId isEqual:@"mark"])
{
col = [_resultColumns objectAtIndex:[colId intValue]];
width = [aColumnsWidth objectForKey:[col identifier]];
mi = [columnsMenu itemWithTag:[colId intValue]];
if (width)
[col setWidth:[width floatValue]];
[self toggleColumn:mi];
}
}
}
- (void)updatePySelection - (void)updatePySelection
{ {
NSArray *selection; NSArray *selection;
@@ -242,6 +299,16 @@ http://www.hardcoded.net/licenses/hs_license
} }
} }
- (IBAction)resetColumnsToDefault:(id)sender
{
// Virtual
}
- (IBAction)showPreferencesPanel:(id)sender
{
[preferencesPanel showWindow:sender];
}
- (IBAction)switchSelected:(id)sender - (IBAction)switchSelected:(id)sender
{ {
// It might look like a complicated way to get the length of the current dupe list on the py side // It might look like a complicated way to get the length of the current dupe list on the py side
@@ -259,6 +326,31 @@ http://www.hardcoded.net/licenses/hs_license
[[NSNotificationCenter defaultCenter] postNotificationName:ResultsChangedNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResultsChangedNotification object:self];
} }
- (IBAction)toggleColumn:(id)sender
{
NSMenuItem *mi = sender;
NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]];
NSTableColumn *col = [matches tableColumnWithIdentifier:colId];
if (col == nil)
{
//Add Column
col = [_resultColumns objectAtIndex:[mi tag]];
[matches addTableColumn:col];
[mi setState:NSOnState];
}
else
{
//Remove column
[matches removeTableColumn:col];
[mi setState:NSOffState];
}
}
- (IBAction)toggleDetailsPanel:(id)sender
{
[[(AppDelegateBase *)app detailsPanel] toggleVisibility];
}
- (IBAction)togglePowerMarker:(id)sender - (IBAction)togglePowerMarker:(id)sender
{ {
if ([pmSwitch selectedSegment] == 1) if ([pmSwitch selectedSegment] == 1)
@@ -311,7 +403,11 @@ http://www.hardcoded.net/licenses/hs_license
if ([lastAction isEqualTo:jobDelete]) if ([lastAction isEqualTo:jobDelete])
{ {
if (r > 0) if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be sent to Trash. They were kept in the results, and still are marked.",r]]; {
NSString *msg = @"%d file(s) couldn't be sent to Trash. They were kept in the results, "\
"and still are marked. See the F.A.Q. section in the help file for details.";
[Dialogs showMessage:[NSString stringWithFormat:msg,r]];
}
else else
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."]; [Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
} }
@@ -353,107 +449,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)resultsUpdated:(NSNotification *)aNotification - (void)resultsUpdated:(NSNotification *)aNotification
{ {
[matches invalidateBuffers]; [matches invalidateBuffers];
} [matches invalidateMarkings];
/* Toolbar */
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
NSToolbarItem *tbi = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
if ([itemIdentifier isEqualTo:tbbDirectories])
{
[tbi setLabel: @"Directories"];
[tbi setToolTip: @"Show/Hide the directories panel."];
[tbi setImage: [NSImage imageNamed: @"folder32"]];
[tbi setTarget: app];
[tbi setAction: @selector(toggleDirectories:)];
}
else if ([itemIdentifier isEqualTo:tbbDetails])
{
[tbi setLabel: @"Details"];
[tbi setToolTip: @"Show/Hide the details panel."];
[tbi setImage: [NSImage imageNamed: @"details32"]];
[tbi setTarget: self];
[tbi setAction: @selector(toggleDetailsPanel:)];
}
else if ([itemIdentifier isEqualTo:tbbPreferences])
{
[tbi setLabel: @"Preferences"];
[tbi setToolTip: @"Show the preferences panel."];
[tbi setImage: [NSImage imageNamed: @"preferences32"]];
[tbi setTarget: self];
[tbi setAction: @selector(showPreferencesPanel:)];
}
else if ([itemIdentifier isEqualTo:tbbPowerMarker])
{
[tbi setLabel: @"Power Marker"];
[tbi setToolTip: @"When enabled, only the duplicates are shown, not the references."];
[tbi setView:pmSwitchView];
[tbi setMinSize:[pmSwitchView frame].size];
[tbi setMaxSize:[pmSwitchView frame].size];
}
else if ([itemIdentifier isEqualTo:tbbScan])
{
[tbi setLabel: @"Start Scanning"];
[tbi setToolTip: @"Start scanning for duplicates in the selected directories."];
[tbi setImage: [NSImage imageNamed:[self logoImageName]]];
[tbi setTarget: self];
[tbi setAction: @selector(startDuplicateScan:)];
}
else if ([itemIdentifier isEqualTo:tbbAction])
{
[tbi setLabel: @"Action"];
[tbi setView:actionMenuView];
[tbi setMinSize:[actionMenuView frame].size];
[tbi setMaxSize:[actionMenuView frame].size];
}
else if ([itemIdentifier isEqualTo:tbbDelta])
{
[tbi setLabel: @"Delta Values"];
[tbi setToolTip: @"When enabled, this option makes dupeGuru display, where applicable, delta values instead of absolute values."];
[tbi setView:deltaSwitchView];
[tbi setMinSize:[deltaSwitchView frame].size];
[tbi setMaxSize:[deltaSwitchView frame].size];
}
else if ([itemIdentifier isEqualTo:tbbFilter])
{
[tbi setLabel: @"Filter"];
[tbi setToolTip: @"Filters the results using regular expression."];
[tbi setView:filterFieldView];
[tbi setMinSize:[filterFieldView frame].size];
[tbi setMaxSize:NSMakeSize(1000, [filterFieldView frame].size.height)];
}
[tbi setPaletteLabel: [tbi label]];
return tbi;
}
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
return [NSArray arrayWithObjects:
tbbDirectories,
tbbDetails,
tbbPreferences,
tbbPowerMarker,
tbbScan,
tbbAction,
tbbDelta,
tbbFilter,
NSToolbarSeparatorItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarFlexibleSpaceItemIdentifier,
nil];
}
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
return [NSArray arrayWithObjects:
tbbScan,
tbbAction,
tbbDirectories,
tbbDetails,
tbbPowerMarker,
tbbDelta,
tbbFilter,
nil];
} }
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem - (BOOL)validateToolbarItem:(NSToolbarItem *)theItem

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4618
base/cocoa/xib/MainMenu.xib Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -70,12 +70,10 @@ class DupeGuru(RegistrableApplication):
def _do_delete_dupe(self, dupe): def _do_delete_dupe(self, dupe):
if not io.exists(dupe.path): if not io.exists(dupe.path):
dupe.parent = None
return True return True
self._recycle_dupe(dupe) self._recycle_dupe(dupe)
self.clean_empty_dirs(dupe.path[:-1]) self.clean_empty_dirs(dupe.path[:-1])
if not io.exists(dupe.path): if not io.exists(dupe.path):
dupe.parent = None
return True return True
logging.warning("Could not send {0} to trash.".format(unicode(dupe.path))) logging.warning("Could not send {0} to trash.".format(unicode(dupe.path)))
return False return False

View File

@@ -7,6 +7,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 objc
from Foundation import * from Foundation import *
from AppKit import * from AppKit import *
import logging import logging
@@ -53,18 +54,14 @@ class DupeGuru(app.DupeGuru):
#--- Override #--- Override
@staticmethod @staticmethod
def _recycle_dupe(dupe): def _recycle_dupe(dupe):
if not io.exists(dupe.path): directory = unicode(dupe.path[:-1])
dupe.parent = None
return True
directory = unicode(dupe.parent.path)
filename = dupe.name filename = dupe.name
result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_( if objc.__version__ == '1.4': # For a while, we have to support this.
NSWorkspaceRecycleOperation, directory, '', [filename]) result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
if not io.exists(dupe.path): NSWorkspaceRecycleOperation, directory, '', [filename])
dupe.parent = None else:
return True result, tag = NSWorkspace.sharedWorkspace().performFileOperation_source_destination_files_tag_(
logging.warning('Could not send %s to trash. tag: %d' % (unicode(dupe.path), tag)) NSWorkspaceRecycleOperation, directory, '', [filename], None)
return False
def _start_job(self, jobid, func): def _start_job(self, jobid, func):
try: try:

View File

@@ -208,7 +208,9 @@ def getmatches_by_contents(files, sizeattr='size', partial=False, j=job.nulljob)
j = j.start_subjob([2, 8]) j = j.start_subjob([2, 8])
size2files = defaultdict(set) size2files = defaultdict(set)
for file in j.iter_with_progress(files, 'Read size of %d/%d files'): for file in j.iter_with_progress(files, 'Read size of %d/%d files'):
size2files[getattr(file, sizeattr)].add(file) filesize = getattr(file, sizeattr)
if filesize:
size2files[filesize].add(file)
possible_matches = [files for files in size2files.values() if len(files) > 1] possible_matches = [files for files in size2files.values() if len(files) > 1]
del size2files del size2files
result = [] result = []

View File

@@ -10,7 +10,7 @@
import logging import logging
from hsutil import job from hsutil import job, io
from hsutil.misc import dedupe from hsutil.misc import dedupe
from hsutil.str import get_file_ext, rem_file_ext from hsutil.str import get_file_ext, rem_file_ext
@@ -80,9 +80,10 @@ class Scanner(object):
logging.info('Getting matches') logging.info('Getting matches')
matches = self._getmatches(files, j) matches = self._getmatches(files, j)
logging.info('Found %d matches' % len(matches)) logging.info('Found %d matches' % len(matches))
j.set_progress(100, 'Removing false matches')
if not self.mix_file_kind: if not self.mix_file_kind:
j.set_progress(100, 'Removing false matches')
matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)] matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
matches = [m for m in matches if io.exists(m.first.path) and io.exists(m.second.path)]
if self.ignore_list: if self.ignore_list:
j = j.start_subjob(2) j = j.start_subjob(2)
iter_matches = j.iter_with_progress(matches, 'Processed %d/%d matches against the ignore list') iter_matches = j.iter_with_progress(matches, 'Processed %d/%d matches against the ignore list')

View File

@@ -154,13 +154,13 @@ class TCDirectories(TestCase):
d.add_path(p) d.add_path(p)
d.set_state(p + 'dir1',STATE_REFERENCE) d.set_state(p + 'dir1',STATE_REFERENCE)
d.set_state(p + 'dir2',STATE_EXCLUDED) d.set_state(p + 'dir2',STATE_EXCLUDED)
files = d.get_files() files = list(d.get_files())
self.assertEqual(5, len(list(files))) self.assertEqual(5, len(files))
for f in files: for f in files:
if f.parent.path == p + 'dir1': if f.path[:-1] == p + 'dir1':
self.assert_(f.is_ref) assert f.is_ref
else: else:
self.assert_(not f.is_ref) assert not f.is_ref
def test_get_files_with_inherited_exclusion(self): def test_get_files_with_inherited_exclusion(self):
d = Directories() d = Directories()

View File

@@ -15,16 +15,21 @@ from hsutil import job
from hsutil.decorators import log_calls from hsutil.decorators import log_calls
from hsutil.testcase import TestCase from hsutil.testcase import TestCase
from .. import engine from .. import engine, fs
from ..engine import * from ..engine import *
class NamedObject(object): class NamedObject(object):
def __init__(self, name="foobar", with_words=False): def __init__(self, name="foobar", with_words=False, size=1):
self.name = name self.name = name
self.size = size
self.md5partial = name
self.md5 = name
if with_words: if with_words:
self.words = getwords(name) self.words = getwords(name)
no = NamedObject
def get_match_triangle(): def get_match_triangle():
o1 = NamedObject(with_words=True) o1 = NamedObject(with_words=True)
o2 = NamedObject(with_words=True) o2 = NamedObject(with_words=True)
@@ -486,6 +491,12 @@ class GetMatches(TestCase):
self.assertEqual(42, len(r)) self.assertEqual(42, len(r))
class GetMatchesByContents(TestCase):
def test_dont_compare_empty_files(self):
o1, o2 = no(size=0), no(size=0)
assert not getmatches_by_contents([o1, o2])
class TCGroup(TestCase): class TCGroup(TestCase):
def test_empy(self): def test_empy(self):
g = Group() g = Group()

View File

@@ -21,7 +21,6 @@ from .. import engine
from ..results import * from ..results import *
class NamedObject(engine_test.NamedObject): class NamedObject(engine_test.NamedObject):
size = 1
path = property(lambda x:Path('basepath') + x.name) path = property(lambda x:Path('basepath') + x.name)
is_ref = False is_ref = False

View File

@@ -9,9 +9,11 @@
from nose.tools import eq_ from nose.tools import eq_
from hsutil import job from hsutil import job, io
from hsutil.path import Path from hsutil.path import Path
from hsutil.testcase import TestCase
from .. import fs
from ..engine import getwords, Match from ..engine import getwords, Match
from ..ignore import IgnoreList from ..ignore import IgnoreList
from ..scanner import * from ..scanner import *
@@ -27,412 +29,439 @@ class NamedObject(object):
no = NamedObject no = NamedObject
#--- Scanner #--- Scanner
def test_empty(): class ScannerTestFakeFiles(TestCase):
s = Scanner() def setUp(self):
r = s.GetDupeGroups([]) # This is a hack to avoid invalidating all previous tests since the scanner started to test
eq_(r, []) # for file existence before doing the match grouping.
self.mock(io, 'exists', lambda _: True)
def test_default_settings():
s = Scanner()
eq_(s.min_match_percentage, 80)
eq_(s.scan_type, SCAN_TYPE_FILENAME)
eq_(s.mix_file_kind, True)
eq_(s.word_weighting, False)
eq_(s.match_similar_words, False)
assert isinstance(s.ignore_list, IgnoreList)
def test_simple_with_default_settings():
s = Scanner()
f = [no('foo bar'), no('foo bar'), no('foo bleh')]
r = s.GetDupeGroups(f)
eq_(len(r), 1)
g = r[0]
#'foo bleh' cannot be in the group because the default min match % is 80
eq_(len(g), 2)
assert g.ref in f[:2]
assert g.dupes[0] in f[:2]
def test_simple_with_lower_min_match():
s = Scanner()
s.min_match_percentage = 50
f = [no('foo bar'), no('foo bar'), no('foo bleh')]
r = s.GetDupeGroups(f)
eq_(len(r), 1)
g = r[0]
eq_(len(g), 3)
def test_trim_all_ref_groups():
# When all files of a group are ref, don't include that group in the results, but also don't
# count the files from that group as discarded.
s = Scanner()
f = [no('foo'), no('foo'), no('bar'), no('bar')]
f[2].is_ref = True
f[3].is_ref = True
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(s.discarded_file_count, 0)
def test_priorize():
s = Scanner()
f = [no('foo'), no('foo'), no('bar'), no('bar')]
f[1].size = 2
f[2].size = 3
f[3].is_ref = True
r = s.GetDupeGroups(f)
g1, g2 = r
assert f[1] in (g1.ref,g2.ref)
assert f[0] in (g1.dupes[0],g2.dupes[0])
assert f[3] in (g1.ref,g2.ref)
assert f[2] in (g1.dupes[0],g2.dupes[0])
def test_content_scan():
s = Scanner()
s.scan_type = SCAN_TYPE_CONTENT
f = [no('foo'), no('bar'), no('bleh')]
f[0].md5 = f[0].md5partial = 'foobar'
f[1].md5 = f[1].md5partial = 'foobar'
f[2].md5 = f[2].md5partial = 'bleh'
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(len(r[0]), 2)
eq_(s.discarded_file_count, 0) # don't count the different md5 as discarded!
def test_content_scan_compare_sizes_first():
class MyFile(no):
@property
def md5(file):
raise AssertionError()
s = Scanner() def test_empty(self):
s.scan_type = SCAN_TYPE_CONTENT s = Scanner()
f = [MyFile('foo', 1), MyFile('bar', 2)] r = s.GetDupeGroups([])
eq_(len(s.GetDupeGroups(f)), 0) eq_(r, [])
def test_min_match_perc_doesnt_matter_for_content_scan():
s = Scanner()
s.scan_type = SCAN_TYPE_CONTENT
f = [no('foo'), no('bar'), no('bleh')]
f[0].md5 = f[0].md5partial = 'foobar'
f[1].md5 = f[1].md5partial = 'foobar'
f[2].md5 = f[2].md5partial = 'bleh'
s.min_match_percentage = 101
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(len(r[0]), 2)
s.min_match_percentage = 0
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(len(r[0]), 2)
def test_content_scan_doesnt_put_md5_in_words_at_the_end():
s = Scanner()
s.scan_type = SCAN_TYPE_CONTENT
f = [no('foo'),no('bar')]
f[0].md5 = f[0].md5partial = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
f[1].md5 = f[1].md5partial = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
r = s.GetDupeGroups(f)
g = r[0]
def test_extension_is_not_counted_in_filename_scan():
s = Scanner()
s.min_match_percentage = 100
f = [no('foo.bar'), no('foo.bleh')]
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(len(r[0]), 2)
def test_job():
def do_progress(progress, desc=''):
log.append(progress)
return True
s = Scanner() def test_default_settings(self):
log = [] s = Scanner()
f = [no('foo bar'), no('foo bar'), no('foo bleh')] eq_(s.min_match_percentage, 80)
r = s.GetDupeGroups(f, job.Job(1, do_progress)) eq_(s.scan_type, SCAN_TYPE_FILENAME)
eq_(log[0], 0) eq_(s.mix_file_kind, True)
eq_(log[-1], 100) eq_(s.word_weighting, False)
eq_(s.match_similar_words, False)
def test_mix_file_kind(): assert isinstance(s.ignore_list, IgnoreList)
s = Scanner()
s.mix_file_kind = False def test_simple_with_default_settings(self):
f = [no('foo.1'), no('foo.2')] s = Scanner()
r = s.GetDupeGroups(f) f = [no('foo bar'), no('foo bar'), no('foo bleh')]
eq_(len(r), 0) r = s.GetDupeGroups(f)
eq_(len(r), 1)
def test_word_weighting(): g = r[0]
s = Scanner() #'foo bleh' cannot be in the group because the default min match % is 80
s.min_match_percentage = 75 eq_(len(g), 2)
s.word_weighting = True assert g.ref in f[:2]
f = [no('foo bar'), no('foo bar bleh')] assert g.dupes[0] in f[:2]
r = s.GetDupeGroups(f)
eq_(len(r), 1) def test_simple_with_lower_min_match(self):
g = r[0] s = Scanner()
m = g.get_match_of(g.dupes[0]) s.min_match_percentage = 50
eq_(m.percentage, 75) # 16 letters, 12 matching f = [no('foo bar'), no('foo bar'), no('foo bleh')]
r = s.GetDupeGroups(f)
def test_similar_words(): eq_(len(r), 1)
s = Scanner() g = r[0]
s.match_similar_words = True eq_(len(g), 3)
f = [no('The White Stripes'), no('The Whites Stripe'), no('Limp Bizkit'), no('Limp Bizkitt')]
r = s.GetDupeGroups(f) def test_trim_all_ref_groups(self):
eq_(len(r), 2) # When all files of a group are ref, don't include that group in the results, but also don't
# count the files from that group as discarded.
def test_fields(): s = Scanner()
s = Scanner() f = [no('foo'), no('foo'), no('bar'), no('bar')]
s.scan_type = SCAN_TYPE_FIELDS f[2].is_ref = True
f = [no('The White Stripes - Little Ghost'), no('The White Stripes - Little Acorn')] f[3].is_ref = True
r = s.GetDupeGroups(f) r = s.GetDupeGroups(f)
eq_(len(r), 0) eq_(len(r), 1)
eq_(s.discarded_file_count, 0)
def test_fields_no_order():
s = Scanner() def test_priorize(self):
s.scan_type = SCAN_TYPE_FIELDS_NO_ORDER s = Scanner()
f = [no('The White Stripes - Little Ghost'), no('Little Ghost - The White Stripes')] f = [no('foo'), no('foo'), no('bar'), no('bar')]
r = s.GetDupeGroups(f) f[1].size = 2
eq_(len(r), 1) f[2].size = 3
f[3].is_ref = True
def test_tag_scan(): r = s.GetDupeGroups(f)
s = Scanner() g1, g2 = r
s.scan_type = SCAN_TYPE_TAG assert f[1] in (g1.ref,g2.ref)
o1 = no('foo') assert f[0] in (g1.dupes[0],g2.dupes[0])
o2 = no('bar') assert f[3] in (g1.ref,g2.ref)
o1.artist = 'The White Stripes' assert f[2] in (g1.dupes[0],g2.dupes[0])
o1.title = 'The Air Near My Fingers'
o2.artist = 'The White Stripes' def test_content_scan(self):
o2.title = 'The Air Near My Fingers' s = Scanner()
r = s.GetDupeGroups([o1,o2]) s.scan_type = SCAN_TYPE_CONTENT
eq_(len(r), 1) f = [no('foo'), no('bar'), no('bleh')]
f[0].md5 = f[0].md5partial = 'foobar'
def test_tag_with_album_scan(): f[1].md5 = f[1].md5partial = 'foobar'
s = Scanner() f[2].md5 = f[2].md5partial = 'bleh'
s.scan_type = SCAN_TYPE_TAG r = s.GetDupeGroups(f)
s.scanned_tags = set(['artist', 'album', 'title']) eq_(len(r), 1)
o1 = no('foo') eq_(len(r[0]), 2)
o2 = no('bar') eq_(s.discarded_file_count, 0) # don't count the different md5 as discarded!
o3 = no('bleh')
o1.artist = 'The White Stripes' def test_content_scan_compare_sizes_first(self):
o1.title = 'The Air Near My Fingers' class MyFile(no):
o1.album = 'Elephant' @property
o2.artist = 'The White Stripes' def md5(file):
o2.title = 'The Air Near My Fingers' raise AssertionError()
o2.album = 'Elephant'
o3.artist = 'The White Stripes' s = Scanner()
o3.title = 'The Air Near My Fingers' s.scan_type = SCAN_TYPE_CONTENT
o3.album = 'foobar' f = [MyFile('foo', 1), MyFile('bar', 2)]
r = s.GetDupeGroups([o1,o2,o3]) eq_(len(s.GetDupeGroups(f)), 0)
eq_(len(r), 1)
def test_min_match_perc_doesnt_matter_for_content_scan(self):
def test_that_dash_in_tags_dont_create_new_fields(): s = Scanner()
s = Scanner() s.scan_type = SCAN_TYPE_CONTENT
s.scan_type = SCAN_TYPE_TAG f = [no('foo'), no('bar'), no('bleh')]
s.scanned_tags = set(['artist', 'album', 'title']) f[0].md5 = f[0].md5partial = 'foobar'
s.min_match_percentage = 50 f[1].md5 = f[1].md5partial = 'foobar'
o1 = no('foo') f[2].md5 = f[2].md5partial = 'bleh'
o2 = no('bar') s.min_match_percentage = 101
o1.artist = 'The White Stripes - a' r = s.GetDupeGroups(f)
o1.title = 'The Air Near My Fingers - a' eq_(len(r), 1)
o1.album = 'Elephant - a' eq_(len(r[0]), 2)
o2.artist = 'The White Stripes - b' s.min_match_percentage = 0
o2.title = 'The Air Near My Fingers - b' r = s.GetDupeGroups(f)
o2.album = 'Elephant - b' eq_(len(r), 1)
r = s.GetDupeGroups([o1,o2]) eq_(len(r[0]), 2)
eq_(len(r), 1)
def test_content_scan_doesnt_put_md5_in_words_at_the_end(self):
def test_tag_scan_with_different_scanned(): s = Scanner()
s = Scanner() s.scan_type = SCAN_TYPE_CONTENT
s.scan_type = SCAN_TYPE_TAG f = [no('foo'),no('bar')]
s.scanned_tags = set(['track', 'year']) f[0].md5 = f[0].md5partial = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
o1 = no('foo') f[1].md5 = f[1].md5partial = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
o2 = no('bar') r = s.GetDupeGroups(f)
o1.artist = 'The White Stripes' g = r[0]
o1.title = 'some title'
o1.track = 'foo' def test_extension_is_not_counted_in_filename_scan(self):
o1.year = 'bar' s = Scanner()
o2.artist = 'The White Stripes' s.min_match_percentage = 100
o2.title = 'another title' f = [no('foo.bar'), no('foo.bleh')]
o2.track = 'foo' r = s.GetDupeGroups(f)
o2.year = 'bar' eq_(len(r), 1)
r = s.GetDupeGroups([o1, o2]) eq_(len(r[0]), 2)
eq_(len(r), 1)
def test_job(self):
def test_tag_scan_only_scans_existing_tags(): def do_progress(progress, desc=''):
s = Scanner() log.append(progress)
s.scan_type = SCAN_TYPE_TAG return True
s.scanned_tags = set(['artist', 'foo'])
o1 = no('foo') s = Scanner()
o2 = no('bar') log = []
o1.artist = 'The White Stripes' f = [no('foo bar'), no('foo bar'), no('foo bleh')]
o1.foo = 'foo' r = s.GetDupeGroups(f, job.Job(1, do_progress))
o2.artist = 'The White Stripes' eq_(log[0], 0)
o2.foo = 'bar' eq_(log[-1], 100)
r = s.GetDupeGroups([o1, o2])
eq_(len(r), 1) # Because 'foo' is not scanned, they match def test_mix_file_kind(self):
s = Scanner()
def test_tag_scan_converts_to_str(): s.mix_file_kind = False
s = Scanner() f = [no('foo.1'), no('foo.2')]
s.scan_type = SCAN_TYPE_TAG r = s.GetDupeGroups(f)
s.scanned_tags = set(['track']) eq_(len(r), 0)
o1 = no('foo')
o2 = no('bar') def test_word_weighting(self):
o1.track = 42 s = Scanner()
o2.track = 42 s.min_match_percentage = 75
try: s.word_weighting = True
f = [no('foo bar'), no('foo bar bleh')]
r = s.GetDupeGroups(f)
eq_(len(r), 1)
g = r[0]
m = g.get_match_of(g.dupes[0])
eq_(m.percentage, 75) # 16 letters, 12 matching
def test_similar_words(self):
s = Scanner()
s.match_similar_words = True
f = [no('The White Stripes'), no('The Whites Stripe'), no('Limp Bizkit'), no('Limp Bizkitt')]
r = s.GetDupeGroups(f)
eq_(len(r), 2)
def test_fields(self):
s = Scanner()
s.scan_type = SCAN_TYPE_FIELDS
f = [no('The White Stripes - Little Ghost'), no('The White Stripes - Little Acorn')]
r = s.GetDupeGroups(f)
eq_(len(r), 0)
def test_fields_no_order(self):
s = Scanner()
s.scan_type = SCAN_TYPE_FIELDS_NO_ORDER
f = [no('The White Stripes - Little Ghost'), no('Little Ghost - The White Stripes')]
r = s.GetDupeGroups(f)
eq_(len(r), 1)
def test_tag_scan(self):
s = Scanner()
s.scan_type = SCAN_TYPE_TAG
o1 = no('foo')
o2 = no('bar')
o1.artist = 'The White Stripes'
o1.title = 'The Air Near My Fingers'
o2.artist = 'The White Stripes'
o2.title = 'The Air Near My Fingers'
r = s.GetDupeGroups([o1,o2])
eq_(len(r), 1)
def test_tag_with_album_scan(self):
s = Scanner()
s.scan_type = SCAN_TYPE_TAG
s.scanned_tags = set(['artist', 'album', 'title'])
o1 = no('foo')
o2 = no('bar')
o3 = no('bleh')
o1.artist = 'The White Stripes'
o1.title = 'The Air Near My Fingers'
o1.album = 'Elephant'
o2.artist = 'The White Stripes'
o2.title = 'The Air Near My Fingers'
o2.album = 'Elephant'
o3.artist = 'The White Stripes'
o3.title = 'The Air Near My Fingers'
o3.album = 'foobar'
r = s.GetDupeGroups([o1,o2,o3])
eq_(len(r), 1)
def test_that_dash_in_tags_dont_create_new_fields(self):
s = Scanner()
s.scan_type = SCAN_TYPE_TAG
s.scanned_tags = set(['artist', 'album', 'title'])
s.min_match_percentage = 50
o1 = no('foo')
o2 = no('bar')
o1.artist = 'The White Stripes - a'
o1.title = 'The Air Near My Fingers - a'
o1.album = 'Elephant - a'
o2.artist = 'The White Stripes - b'
o2.title = 'The Air Near My Fingers - b'
o2.album = 'Elephant - b'
r = s.GetDupeGroups([o1,o2])
eq_(len(r), 1)
def test_tag_scan_with_different_scanned(self):
s = Scanner()
s.scan_type = SCAN_TYPE_TAG
s.scanned_tags = set(['track', 'year'])
o1 = no('foo')
o2 = no('bar')
o1.artist = 'The White Stripes'
o1.title = 'some title'
o1.track = 'foo'
o1.year = 'bar'
o2.artist = 'The White Stripes'
o2.title = 'another title'
o2.track = 'foo'
o2.year = 'bar'
r = s.GetDupeGroups([o1, o2]) r = s.GetDupeGroups([o1, o2])
except TypeError: eq_(len(r), 1)
raise AssertionError()
eq_(len(r), 1) def test_tag_scan_only_scans_existing_tags(self):
s = Scanner()
def test_tag_scan_non_ascii(): s.scan_type = SCAN_TYPE_TAG
s = Scanner() s.scanned_tags = set(['artist', 'foo'])
s.scan_type = SCAN_TYPE_TAG o1 = no('foo')
s.scanned_tags = set(['title']) o2 = no('bar')
o1 = no('foo') o1.artist = 'The White Stripes'
o2 = no('bar') o1.foo = 'foo'
o1.title = u'foobar\u00e9' o2.artist = 'The White Stripes'
o2.title = u'foobar\u00e9' o2.foo = 'bar'
try:
r = s.GetDupeGroups([o1, o2]) r = s.GetDupeGroups([o1, o2])
except UnicodeEncodeError: eq_(len(r), 1) # Because 'foo' is not scanned, they match
raise AssertionError()
eq_(len(r), 1)
def test_audio_content_scan():
s = Scanner()
s.scan_type = SCAN_TYPE_CONTENT_AUDIO
f = [no('foo'), no('bar'), no('bleh')]
f[0].md5 = 'foo'
f[1].md5 = 'bar'
f[2].md5 = 'bleh'
f[0].md5partial = 'foo'
f[1].md5partial = 'foo'
f[2].md5partial = 'bleh'
f[0].audiosize = 1
f[1].audiosize = 1
f[2].audiosize = 1
r = s.GetDupeGroups(f)
eq_(len(r), 1)
eq_(len(r[0]), 2)
def test_audio_content_scan_compare_sizes_first(): def test_tag_scan_converts_to_str(self):
class MyFile(no): s = Scanner()
@property s.scan_type = SCAN_TYPE_TAG
def md5partial(file): s.scanned_tags = set(['track'])
o1 = no('foo')
o2 = no('bar')
o1.track = 42
o2.track = 42
try:
r = s.GetDupeGroups([o1, o2])
except TypeError:
raise AssertionError() raise AssertionError()
eq_(len(r), 1)
s = Scanner() def test_tag_scan_non_ascii(self):
s.scan_type = SCAN_TYPE_CONTENT_AUDIO s = Scanner()
f = [MyFile('foo'), MyFile('bar')] s.scan_type = SCAN_TYPE_TAG
f[0].audiosize = 1 s.scanned_tags = set(['title'])
f[1].audiosize = 2 o1 = no('foo')
eq_(len(s.GetDupeGroups(f)), 0) o2 = no('bar')
o1.title = u'foobar\u00e9'
def test_ignore_list(): o2.title = u'foobar\u00e9'
s = Scanner() try:
f1 = no('foobar') r = s.GetDupeGroups([o1, o2])
f2 = no('foobar') except UnicodeEncodeError:
f3 = no('foobar') raise AssertionError()
f1.path = Path('dir1/foobar') eq_(len(r), 1)
f2.path = Path('dir2/foobar')
f3.path = Path('dir3/foobar') def test_audio_content_scan(self):
s.ignore_list.Ignore(str(f1.path),str(f2.path)) s = Scanner()
s.ignore_list.Ignore(str(f1.path),str(f3.path)) s.scan_type = SCAN_TYPE_CONTENT_AUDIO
r = s.GetDupeGroups([f1,f2,f3]) f = [no('foo'), no('bar'), no('bleh')]
eq_(len(r), 1) f[0].md5 = 'foo'
g = r[0] f[1].md5 = 'bar'
eq_(len(g.dupes), 1) f[2].md5 = 'bleh'
assert f1 not in g f[0].md5partial = 'foo'
assert f2 in g f[1].md5partial = 'foo'
assert f3 in g f[2].md5partial = 'bleh'
# Ignored matches are not counted as discarded f[0].audiosize = 1
eq_(s.discarded_file_count, 0) f[1].audiosize = 1
f[2].audiosize = 1
def test_ignore_list_checks_for_unicode(): r = s.GetDupeGroups(f)
#scanner was calling path_str for ignore list checks. Since the Path changes, it must eq_(len(r), 1)
#be unicode(path) eq_(len(r[0]), 2)
s = Scanner()
f1 = no('foobar') def test_audio_content_scan_compare_sizes_first(self):
f2 = no('foobar') class MyFile(no):
f3 = no('foobar') @property
f1.path = Path(u'foo1\u00e9') def md5partial(file):
f2.path = Path(u'foo2\u00e9') raise AssertionError()
f3.path = Path(u'foo3\u00e9')
s.ignore_list.Ignore(unicode(f1.path),unicode(f2.path)) s = Scanner()
s.ignore_list.Ignore(unicode(f1.path),unicode(f3.path)) s.scan_type = SCAN_TYPE_CONTENT_AUDIO
r = s.GetDupeGroups([f1,f2,f3]) f = [MyFile('foo'), MyFile('bar')]
eq_(len(r), 1) f[0].audiosize = 1
g = r[0] f[1].audiosize = 2
eq_(len(g.dupes), 1) eq_(len(s.GetDupeGroups(f)), 0)
assert f1 not in g
assert f2 in g def test_ignore_list(self):
assert f3 in g s = Scanner()
f1 = no('foobar')
def test_file_evaluates_to_false(): f2 = no('foobar')
# A very wrong way to use any() was added at some point, causing resulting group list f3 = no('foobar')
# to be empty. f1.path = Path('dir1/foobar')
class FalseNamedObject(NamedObject): f2.path = Path('dir2/foobar')
def __nonzero__(self): f3.path = Path('dir3/foobar')
return False s.ignore_list.Ignore(str(f1.path),str(f2.path))
s.ignore_list.Ignore(str(f1.path),str(f3.path))
r = s.GetDupeGroups([f1,f2,f3])
eq_(len(r), 1)
g = r[0]
eq_(len(g.dupes), 1)
assert f1 not in g
assert f2 in g
assert f3 in g
# Ignored matches are not counted as discarded
eq_(s.discarded_file_count, 0)
def test_ignore_list_checks_for_unicode(self):
#scanner was calling path_str for ignore list checks. Since the Path changes, it must
#be unicode(path)
s = Scanner()
f1 = no('foobar')
f2 = no('foobar')
f3 = no('foobar')
f1.path = Path(u'foo1\u00e9')
f2.path = Path(u'foo2\u00e9')
f3.path = Path(u'foo3\u00e9')
s.ignore_list.Ignore(unicode(f1.path),unicode(f2.path))
s.ignore_list.Ignore(unicode(f1.path),unicode(f3.path))
r = s.GetDupeGroups([f1,f2,f3])
eq_(len(r), 1)
g = r[0]
eq_(len(g.dupes), 1)
assert f1 not in g
assert f2 in g
assert f3 in g
def test_file_evaluates_to_false(self):
# A very wrong way to use any() was added at some point, causing resulting group list
# to be empty.
class FalseNamedObject(NamedObject):
def __nonzero__(self):
return False
s = Scanner() s = Scanner()
f1 = FalseNamedObject('foobar') f1 = FalseNamedObject('foobar')
f2 = FalseNamedObject('foobar') f2 = FalseNamedObject('foobar')
r = s.GetDupeGroups([f1, f2]) r = s.GetDupeGroups([f1, f2])
eq_(len(r), 1) eq_(len(r), 1)
def test_size_threshold(self):
# Only file equal or higher than the size_threshold in size are scanned
s = Scanner()
f1 = no('foo', 1)
f2 = no('foo', 2)
f3 = no('foo', 3)
s.size_threshold = 2
groups = s.GetDupeGroups([f1,f2,f3])
eq_(len(groups), 1)
[group] = groups
eq_(len(group), 2)
assert f1 not in group
assert f2 in group
assert f3 in group
def test_tie_breaker_path_deepness(self):
# If there is a tie in prioritization, path deepness is used as a tie breaker
s = Scanner()
o1, o2 = no('foo'), no('foo')
o1.path = Path('foo')
o2.path = Path('foo/bar')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_tie_breaker_copy(self):
# if copy is in the words used (even if it has a deeper path), it becomes a dupe
s = Scanner()
o1, o2 = no('foo bar Copy'), no('foo bar')
o1.path = Path('deeper/path')
o2.path = Path('foo')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_tie_breaker_same_name_plus_digit(self):
# if ref has the same words as dupe, but has some just one extra word which is a digit, it
# becomes a dupe
s = Scanner()
o1, o2 = no('foo bar 42'), no('foo bar')
o1.path = Path('deeper/path')
o2.path = Path('foo')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_partial_group_match(self):
# Count the number od discarded matches (when a file doesn't match all other dupes of the
# group) in Scanner.discarded_file_count
s = Scanner()
o1, o2, o3 = no('a b'), no('a'), no('b')
s.min_match_percentage = 50
[group] = s.GetDupeGroups([o1, o2, o3])
eq_(len(group), 2)
assert o1 in group
assert o2 in group
assert o3 not in group
eq_(s.discarded_file_count, 1)
def test_size_threshold(): class ScannerTest(TestCase):
# Only file equal or higher than the size_threshold in size are scanned def test_dont_group_files_that_dont_exist(self):
s = Scanner() # when creating groups, check that files exist first. It's possible that these files have
f1 = no('foo', 1) # been moved during the scan by the user.
f2 = no('foo', 2) # In this test, we have to delete one of the files between the get_matches() part and the
f3 = no('foo', 3) # get_groups() part.
s.size_threshold = 2 s = Scanner()
groups = s.GetDupeGroups([f1,f2,f3]) s.scan_type = SCAN_TYPE_CONTENT
eq_(len(groups), 1) p = self.tmppath()
[group] = groups io.open(p + 'file1', 'w').write('foo')
eq_(len(group), 2) io.open(p + 'file2', 'w').write('foo')
assert f1 not in group file1, file2 = fs.get_files(p)
assert f2 in group def getmatches(*args, **kw):
assert f3 in group io.remove(file2.path)
return [Match(file1, file2, 100)]
def test_tie_breaker_path_deepness(): s._getmatches = getmatches
# If there is a tie in prioritization, path deepness is used as a tie breaker
s = Scanner() assert not s.GetDupeGroups([file1, file2])
o1, o2 = no('foo'), no('foo')
o1.path = Path('foo')
o2.path = Path('foo/bar')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_tie_breaker_copy():
# if copy is in the words used (even if it has a deeper path), it becomes a dupe
s = Scanner()
o1, o2 = no('foo bar Copy'), no('foo bar')
o1.path = Path('deeper/path')
o2.path = Path('foo')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_tie_breaker_same_name_plus_digit():
# if ref has the same words as dupe, but has some just one extra word which is a digit, it
# becomes a dupe
s = Scanner()
o1, o2 = no('foo bar 42'), no('foo bar')
o1.path = Path('deeper/path')
o2.path = Path('foo')
[group] = s.GetDupeGroups([o1, o2])
assert group.ref is o2
def test_partial_group_match():
# Count the number od discarded matches (when a file doesn't match all other dupes of the
# group) in Scanner.discarded_file_count
s = Scanner()
o1, o2, o3 = no('a b'), no('a'), no('b')
s.min_match_percentage = 50
[group] = s.GetDupeGroups([o1, o2, o3])
eq_(len(group), 2)
assert o1 in group
assert o2 in group
assert o3 not in group
eq_(s.discarded_file_count, 1)

View File

@@ -1,37 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-09
# $Id$
# Copyright 2009 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, QCoreApplication, SIGNAL
from PyQt4.QtGui import QDialog, QDialogButtonBox, QPixmap
from about_box_ui import Ui_AboutBox
class AboutBox(QDialog, Ui_AboutBox):
def __init__(self, parent, app):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.MSWindowsFixedSizeDialogHint
QDialog.__init__(self, parent, flags)
self.app = app
self._setupUi()
self.connect(self.buttonBox, SIGNAL('clicked(QAbstractButton*)'), self.buttonClicked)
def _setupUi(self):
self.setupUi(self)
# Stuff that can't be done in the Designer
self.setWindowTitle(u"About %s" % QCoreApplication.instance().applicationName())
self.nameLabel.setText(QCoreApplication.instance().applicationName())
self.versionLabel.setText('Version ' + QCoreApplication.instance().applicationVersion())
self.logoLabel.setPixmap(QPixmap(':/%s_big' % self.app.LOGO_NAME))
self.registerButton = self.buttonBox.addButton("Register", QDialogButtonBox.ActionRole)
#--- Events
def buttonClicked(self, button):
if button is self.registerButton:
self.app.ask_for_reg_code()

View File

@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AboutBox</class>
<widget class="QDialog" name="AboutBox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>190</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>About dupeGuru</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="logoLabel">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="dg.qrc">:/logo_me_big</pixmap>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="nameLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>dupeGuru</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionLabel">
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Copyright Hardcoded Software 2009</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Registered To:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="registeredEmailLabel">
<property name="text">
<string>UNREGISTERED</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="dg.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AboutBox</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AboutBox</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -23,14 +23,14 @@ from dupeguru import fs
from dupeguru.app import (DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY, from dupeguru.app import (DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY,
JOB_DELETE) JOB_DELETE)
from qtlib.about_box import AboutBox
from qtlib.progress import Progress from qtlib.progress import Progress
from qtlib.reg import Registration
from . import platform from . import platform
from .main_window import MainWindow from .main_window import MainWindow
from .directories_dialog import DirectoriesDialog from .directories_dialog import DirectoriesDialog
from .about_box import AboutBox
from .reg import Registration
JOBID2TITLE = { JOBID2TITLE = {
JOB_SCAN: "Scanning for duplicates", JOB_SCAN: "Scanning for duplicates",
@@ -54,6 +54,7 @@ class DupeGuru(DupeGuruBase, QObject):
LOGO_NAME = '<replace this>' LOGO_NAME = '<replace this>'
NAME = '<replace this>' NAME = '<replace this>'
DELTA_COLUMNS = frozenset() DELTA_COLUMNS = frozenset()
DEMO_LIMIT_DESC = "In the demo version, only 10 duplicates per session can be sent to the recycle bin, moved or copied."
def __init__(self, data_module, appid): def __init__(self, data_module, appid):
appdata = unicode(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) appdata = unicode(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
@@ -143,10 +144,8 @@ class DupeGuru(DupeGuruBase, QObject):
DupeGuruBase.apply_filter(self, filter) DupeGuruBase.apply_filter(self, filter)
self.emit(SIGNAL('resultsChanged()')) self.emit(SIGNAL('resultsChanged()'))
def ask_for_reg_code(self): def askForRegCode(self):
if self.reg.ask_for_code(): self.reg.ask_for_code()
#XXX bug???
self._setup_ui_as_registered()
@demo_method @demo_method
def copy_or_move_marked(self, copy): def copy_or_move_marked(self, copy):
@@ -198,7 +197,7 @@ class DupeGuru(DupeGuruBase, QObject):
def rename_dupe(self, dupe, newname): def rename_dupe(self, dupe, newname):
try: try:
dupe.move(dupe.parent, newname) dupe.rename(newname)
return True return True
except (IndexError, fs.FSError) as e: except (IndexError, fs.FSError) as e:
logging.warning("dupeGuru Warning: %s" % unicode(e)) logging.warning("dupeGuru Warning: %s" % unicode(e))

View File

@@ -8,7 +8,6 @@
<file alias="logo_se">images/dgse_logo_32.png</file> <file alias="logo_se">images/dgse_logo_32.png</file>
<file alias="logo_se_big">images/dgse_logo_128.png</file> <file alias="logo_se_big">images/dgse_logo_128.png</file>
<file alias="folder">images/folderwin32.png</file> <file alias="folder">images/folderwin32.png</file>
<file alias="gear">images/gear.png</file>
<file alias="preferences">images/preferences32.png</file> <file alias="preferences">images/preferences32.png</file>
<file alias="actions">images/actions32.png</file> <file alias="actions">images/actions32.png</file>
<file alias="delta">images/delta32.png</file> <file alias="delta">images/delta32.png</file>

View File

@@ -16,9 +16,18 @@
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QTreeView" name="treeView"> <widget class="QTreeView" name="treeView">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set> <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property> </property>
<property name="dragDropOverwriteMode">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DropOnly</enum>
</property>
<property name="uniformRowHeights"> <property name="uniformRowHeights">
<bool>true</bool> <bool>true</bool>
</property> </property>
@@ -59,6 +68,9 @@
<property name="text"> <property name="text">
<string>Remove</string> <string>Remove</string>
</property> </property>
<property name="shortcut">
<string>Del</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>

View File

@@ -7,8 +7,11 @@
# 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 PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint import urllib
from PyQt4.QtGui import QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush
from PyQt4.QtCore import QModelIndex, Qt, QRect, QEvent, QPoint, QUrl
from PyQt4.QtGui import (QComboBox, QStyledItemDelegate, QMouseEvent, QApplication, QBrush, QStyle,
QStyleOptionComboBox, QStyleOptionViewItemV4)
from qtlib.tree_model import TreeNode, TreeModel from qtlib.tree_model import TreeNode, TreeModel
@@ -21,6 +24,24 @@ class DirectoriesDelegate(QStyledItemDelegate):
editor.addItems(STATES) editor.addItems(STATES)
return editor return editor
def paint(self, painter, option, index):
self.initStyleOption(option, index)
# No idea why, but this cast is required if we want to have access to the V4 valuess
option = QStyleOptionViewItemV4(option)
if (index.column() == 1) and (option.state & QStyle.State_Selected):
cboption = QStyleOptionComboBox()
cboption.rect = option.rect
# On OS X (with Qt4.6.0), adding State_Enabled to the flags causes the whole drawing to
# fail (draw nothing), but it's an OS X only glitch. On Windows, it works alright.
cboption.state |= QStyle.State_Enabled
QApplication.style().drawComplexControl(QStyle.CC_ComboBox, cboption, painter)
painter.setBrush(option.palette.text())
rect = QRect(option.rect)
rect.setLeft(rect.left()+4)
painter.drawText(rect, Qt.AlignLeft, option.text)
else:
QStyledItemDelegate.paint(self, painter, option, index)
def setEditorData(self, editor, index): def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole) value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(value); editor.setCurrentIndex(value);
@@ -47,7 +68,7 @@ class DirectoryNode(TreeNode):
return DirectoryNode(self.model, self, ref, row) return DirectoryNode(self.model, self, ref, row)
def _getChildren(self): def _getChildren(self):
return self.model._dirs.get_subfolders(self.ref) return self.model.dirs.get_subfolders(self.ref)
@property @property
def name(self): def name(self):
@@ -59,14 +80,15 @@ class DirectoryNode(TreeNode):
class DirectoriesModel(TreeModel): class DirectoriesModel(TreeModel):
def __init__(self, app): def __init__(self, app):
self._dirs = app.directories self.app = app
self.dirs = app.directories
TreeModel.__init__(self) TreeModel.__init__(self)
def _createNode(self, ref, row): def _createNode(self, ref, row):
return DirectoryNode(self, None, ref, row) return DirectoryNode(self, None, ref, row)
def _getChildren(self): def _getChildren(self):
return self._dirs return self.dirs
def columnCount(self, parent): def columnCount(self, parent):
return 2 return 2
@@ -79,21 +101,35 @@ class DirectoriesModel(TreeModel):
if index.column() == 0: if index.column() == 0:
return node.name return node.name
else: else:
return STATES[self._dirs.get_state(node.ref)] return STATES[self.dirs.get_state(node.ref)]
elif role == Qt.EditRole and index.column() == 1: elif role == Qt.EditRole and index.column() == 1:
return self._dirs.get_state(node.ref) return self.dirs.get_state(node.ref)
elif role == Qt.ForegroundRole: elif role == Qt.ForegroundRole:
state = self._dirs.get_state(node.ref) state = self.dirs.get_state(node.ref)
if state == 1: if state == 1:
return QBrush(Qt.blue) return QBrush(Qt.blue)
elif state == 2: elif state == 2:
return QBrush(Qt.red) return QBrush(Qt.red)
return None return None
def dropMimeData(self, mimeData, action, row, column, parentIndex):
# the data in mimeData is urlencoded **in utf-8**!!! which means that urllib.unquote has
# to be called on the utf-8 encoded string, and *only then*, decoded to unicode.
if not mimeData.hasFormat('text/uri-list'):
return False
data = str(mimeData.data('text/uri-list'))
unquoted = urllib.unquote(data)
urls = unicode(unquoted, 'utf-8').split('\r\n')
paths = [unicode(QUrl(url).toLocalFile()) for url in urls if url]
for path in paths:
self.app.add_directory(path)
self.reset()
return True
def flags(self, index): def flags(self, index):
if not index.isValid(): if not index.isValid():
return 0 return Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
result = Qt.ItemIsEnabled | Qt.ItemIsSelectable result = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDropEnabled
if index.column() == 1: if index.column() == 1:
result |= Qt.ItemIsEditable result |= Qt.ItemIsEditable
return result return result
@@ -104,10 +140,18 @@ class DirectoriesModel(TreeModel):
return HEADERS[section] return HEADERS[section]
return None return None
def mimeTypes(self):
return ['text/uri-list']
def setData(self, index, value, role): def setData(self, index, value, role):
if not index.isValid() or role != Qt.EditRole or index.column() != 1: if not index.isValid() or role != Qt.EditRole or index.column() != 1:
return False return False
node = index.internalPointer() node = index.internalPointer()
self._dirs.set_state(node.ref, value) self.dirs.set_state(node.ref, value)
return True return True
def supportedDropActions(self):
# Normally, the correct action should be ActionLink, but the drop doesn't work. It doesn't
# work with ActionMove either. So screw that, and accept anything.
return Qt.ActionMask

View File

@@ -1,36 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-09
# $Id$
# Copyright 2009 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 hashlib import md5
from PyQt4.QtGui import QDialog
from reg_submit_dialog import RegSubmitDialog
from reg_demo_dialog import RegDemoDialog
class Registration(object):
def __init__(self, app):
self.app = app
def ask_for_code(self):
dialog = RegSubmitDialog(self.app.main_window, self.app.is_code_valid)
result = dialog.exec_()
code = unicode(dialog.codeEdit.text())
email = unicode(dialog.emailEdit.text())
dialog.setParent(None) # free it
if result == QDialog.Accepted and self.app.is_code_valid(code, email):
self.app.set_registration(code, email)
return True
return False
def show_nag(self):
dialog = RegDemoDialog(self.app.main_window, self)
dialog.exec_()
dialog.setParent(None) # free it

View File

@@ -1,47 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-10
# $Id$
# Copyright 2009 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 SIGNAL, Qt, QUrl, QCoreApplication
from PyQt4.QtGui import QDialog, QMessageBox, QDesktopServices
from reg_demo_dialog_ui import Ui_RegDemoDialog
class RegDemoDialog(QDialog, Ui_RegDemoDialog):
def __init__(self, parent, reg):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QDialog.__init__(self, parent, flags)
self.reg = reg
self._setupUi()
self.connect(self.enterCodeButton, SIGNAL('clicked()'), self.enterCodeClicked)
self.connect(self.purchaseButton, SIGNAL('clicked()'), self.purchaseClicked)
def _setupUi(self):
self.setupUi(self)
# Stuff that can't be setup in the Designer
appname = QCoreApplication.instance().applicationName()
title = self.windowTitle()
title = title.replace('$appname', appname)
self.setWindowTitle(title)
title = self.titleLabel.text()
title = title.replace('$appname', appname)
self.titleLabel.setText(title)
desc = self.demoDescLabel.text()
desc = desc.replace('$appname', appname)
self.demoDescLabel.setText(desc)
#--- Events
def enterCodeClicked(self):
if self.reg.ask_for_code():
self.accept()
def purchaseClicked(self):
url = QUrl('http://www.hardcoded.net/purchase.htm')
QDesktopServices.openUrl(url)

View File

@@ -1,140 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RegDemoDialog</class>
<widget class="QDialog" name="RegDemoDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>387</width>
<height>161</height>
</rect>
</property>
<property name="windowTitle">
<string>$appname Demo Version</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="titleLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>$appname Demo Version</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="demoDescLabel">
<property name="text">
<string>You are currently running a demo version of $appname. This version has limited functionalities, and you need to buy it to have access to these functionalities.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>In the demo version, only 10 duplicates per session can be sent to the recycle bin, moved or copied.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="tryButton">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Try Demo</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="enterCodeButton">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Enter Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="purchaseButton">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Purchase</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>tryButton</sender>
<signal>clicked()</signal>
<receiver>RegDemoDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>112</x>
<y>161</y>
</hint>
<hint type="destinationlabel">
<x>201</x>
<y>94</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,49 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-09
# $Id$
# Copyright 2009 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 SIGNAL, Qt, QUrl, QCoreApplication
from PyQt4.QtGui import QDialog, QMessageBox, QDesktopServices
from reg_submit_dialog_ui import Ui_RegSubmitDialog
class RegSubmitDialog(QDialog, Ui_RegSubmitDialog):
def __init__(self, parent, is_valid_func):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QDialog.__init__(self, parent, flags)
self._setupUi()
self.is_valid_func = is_valid_func
self.connect(self.submitButton, SIGNAL('clicked()'), self.submitClicked)
self.connect(self.purchaseButton, SIGNAL('clicked()'), self.purchaseClicked)
def _setupUi(self):
self.setupUi(self)
# Stuff that can't be setup in the Designer
appname = QCoreApplication.instance().applicationName()
prompt = self.promptLabel.text()
prompt = prompt.replace('$appname', appname)
self.promptLabel.setText(prompt)
#--- Events
def purchaseClicked(self):
url = QUrl('http://www.hardcoded.net/purchase.htm')
QDesktopServices.openUrl(url)
def submitClicked(self):
code = unicode(self.codeEdit.text())
email = unicode(self.emailEdit.text())
title = "Registration"
if self.is_valid_func(code, email):
msg = "This code is valid. Thanks!"
QMessageBox.information(self, title, msg)
self.accept()
else:
msg = "This code is invalid"
QMessageBox.warning(self, title, msg)

View File

@@ -1,149 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RegSubmitDialog</class>
<widget class="QDialog" name="RegSubmitDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>365</width>
<height>134</height>
</rect>
</property>
<property name="windowTitle">
<string>Enter your registration code</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="promptLabel">
<property name="text">
<string>Please enter your $appname registration code and registered e-mail (the e-mail you used for the purchase), then press &quot;Submit&quot;.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Registration code:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Registered e-mail:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="codeEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="emailEdit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="purchaseButton">
<property name="text">
<string>Purchase</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</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="cancelButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="submitButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Submit</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>cancelButton</sender>
<signal>clicked()</signal>
<receiver>RegSubmitDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>260</x>
<y>159</y>
</hint>
<hint type="destinationlabel">
<x>198</x>
<y>97</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -153,7 +153,7 @@ class ResultsModel(TreeModel):
if index.column() == 0: if index.column() == 0:
value = unicode(value.toString()) value = unicode(value.toString())
if self._app.rename_dupe(node.dupe, value): if self._app.rename_dupe(node.dupe, value):
node.reset() node.invalidate()
return True return True
return False return False

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 B

View File

@@ -13,17 +13,11 @@ http://www.hardcoded.net/licenses/hs_license
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase @interface AppDelegate : AppDelegateBase
{ {
IBOutlet NSButton *presetsButton;
IBOutlet NSPopUpButton *presetsPopup;
IBOutlet ResultWindow *result;
DirectoryPanel *_directoryPanel; DirectoryPanel *_directoryPanel;
} }
- (IBAction)openWebsite:(id)sender; - (IBAction)openWebsite:(id)sender;
- (IBAction)popupPresets:(id)sender;
- (IBAction)toggleDirectories:(id)sender; - (IBAction)toggleDirectories:(id)sender;
- (IBAction)usePreset:(id)sender;
- (DirectoryPanel *)directoryPanel; - (DirectoryPanel *)directoryPanel;
- (PyDupeGuru *)py; - (PyDupeGuru *)py;

View File

@@ -12,6 +12,7 @@ http://www.hardcoded.net/licenses/hs_license
#import "cocoalib/Utils.h" #import "cocoalib/Utils.h"
#import "cocoalib/ValueTransformers.h" #import "cocoalib/ValueTransformers.h"
#import "cocoalib/Dialogs.h" #import "cocoalib/Dialogs.h"
#import "DetailsPanel.h"
#import "Consts.h" #import "Consts.h"
@implementation AppDelegate @implementation AppDelegate
@@ -60,50 +61,17 @@ http://www.hardcoded.net/licenses/hs_license
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_me"]]; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_me"]];
} }
- (IBAction)popupPresets:(id)sender
{
[presetsPopup selectItem: nil];
[[presetsPopup cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
- (IBAction)toggleDirectories:(id)sender - (IBAction)toggleDirectories:(id)sender
{ {
[[self directoryPanel] toggleVisible:sender]; [[self directoryPanel] toggleVisible:sender];
} }
- (IBAction)usePreset:(id)sender
- (DetailsPanelBase *)detailsPanel
{ {
NSUserDefaultsController *ud = [NSUserDefaultsController sharedUserDefaultsController]; if (!_detailsPanel)
[ud revertToInitialValues:nil]; _detailsPanel = [[DetailsPanel alloc] initWithPy:py];
NSUserDefaults *d = [ud defaults]; return _detailsPanel;
switch ([sender tag])
{
case 0:
{
[d setInteger:5 forKey:@"scanType"];
break;
}
//case 1 is defaults
case 2:
{
[d setInteger:2 forKey:@"scanType"];
break;
}
case 3:
{
[d setInteger:0 forKey:@"scanType"];
[d setInteger:50 forKey:@"minMatchPercentage"];
break;
}
case 4:
{
[d setInteger:0 forKey:@"scanType"];
[d setInteger:50 forKey:@"minMatchPercentage"];
[d setBool:YES forKey:@"matchSimilarWords"];
[d setBool:YES forKey:@"wordWeighting"];
break;
}
}
} }
- (DirectoryPanel *)directoryPanel - (DirectoryPanel *)directoryPanel
@@ -115,23 +83,6 @@ http://www.hardcoded.net/licenses/hs_license
- (PyDupeGuru *)py { return (PyDupeGuru *)py; } - (PyDupeGuru *)py { return (PyDupeGuru *)py; }
//Delegate //Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[ProgressController mainProgressController] setWorker:py];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
//Restore Columns
NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"];
NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"];
if ([columnsOrder count])
[result restoreColumnsPosition:columnsOrder widths:columnsWidth];
//Reg stuff
if ([RegistrationInterface showNagWithApp:[self py] name:APPNAME limitDescription:LIMIT_DESC])
[unlockMenuItem setTitle:@"Thanks for buying dupeGuru ME!"];
//Restore results
[py loadIgnoreList];
[py loadResults];
}
- (void)applicationWillBecomeActive:(NSNotification *)aNotification - (void)applicationWillBecomeActive:(NSNotification *)aNotification
{ {
if (![[result window] isVisible]) if (![[result window] isVisible])

View File

@@ -1,18 +0,0 @@
{
IBClasses = (
{
CLASS = DetailsPanel;
LANGUAGE = ObjC;
OUTLETS = {detailsTable = NSTableView; };
SUPERCLASS = NSWindowController;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = TableView;
LANGUAGE = ObjC;
OUTLETS = {py = PyApp; };
SUPERCLASS = NSTableView;
}
);
IBVersion = 1;
}

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>432 54 356 240 0 0 1024 746 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8I127</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>addiTunes</key>
<string>id</string>
<key>askForDirectory</key>
<string>id</string>
<key>changeDirectoryState</key>
<string>id</string>
<key>popupAddDirectoryMenu</key>
<string>id</string>
<key>removeSelectedDirectory</key>
<string>id</string>
<key>toggleVisible</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>DirectoryPanel</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>addButtonPopUp</key>
<string>NSPopUpButton</string>
<key>directories</key>
<string>NSOutlineView</string>
<key>removeButton</key>
<string>NSButton</string>
</dict>
<key>SUPERCLASS</key>
<string>DirectoryPanelBase</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>9B18</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -1,257 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>NSSegmentedControl</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSControl</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>openWebsite</key>
<string>id</string>
<key>popupPresets</key>
<string>id</string>
<key>toggleDirectories</key>
<string>id</string>
<key>unlockApp</key>
<string>id</string>
<key>usePreset</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>AppDelegate</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>defaultsController</key>
<string>NSUserDefaultsController</string>
<key>presetsButton</key>
<string>NSButton</string>
<key>presetsPopup</key>
<string>NSPopUpButton</string>
<key>py</key>
<string>PyDupeGuru</string>
<key>recentDirectories</key>
<string>RecentDirectories</string>
<key>result</key>
<string>ResultWindow</string>
<key>unlockMenuItem</key>
<string>NSMenuItem</string>
</dict>
<key>SUPERCLASS</key>
<string>AppDelegateBase</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyApp</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>MatchesView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>OutlineView</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyDupeGuruBase</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>PyApp</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyDupeGuru</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>PyDupeGuruBase</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>changeDelta</key>
<string>id</string>
<key>changePowerMarker</key>
<string>id</string>
<key>clearIgnoreList</key>
<string>id</string>
<key>collapseAll</key>
<string>id</string>
<key>copyMarked</key>
<string>id</string>
<key>deleteMarked</key>
<string>id</string>
<key>expandAll</key>
<string>id</string>
<key>exportToXHTML</key>
<string>id</string>
<key>filter</key>
<string>id</string>
<key>ignoreSelected</key>
<string>id</string>
<key>markAll</key>
<string>id</string>
<key>markInvert</key>
<string>id</string>
<key>markNone</key>
<string>id</string>
<key>markSelected</key>
<string>id</string>
<key>markToggle</key>
<string>id</string>
<key>moveMarked</key>
<string>id</string>
<key>openSelected</key>
<string>id</string>
<key>refresh</key>
<string>id</string>
<key>removeDeadTracks</key>
<string>id</string>
<key>removeMarked</key>
<string>id</string>
<key>removeSelected</key>
<string>id</string>
<key>renameSelected</key>
<string>id</string>
<key>resetColumnsToDefault</key>
<string>id</string>
<key>revealSelected</key>
<string>id</string>
<key>showPreferencesPanel</key>
<string>id</string>
<key>startDuplicateScan</key>
<string>id</string>
<key>switchSelected</key>
<string>id</string>
<key>toggleColumn</key>
<string>id</string>
<key>toggleDelta</key>
<string>id</string>
<key>toggleDetailsPanel</key>
<string>id</string>
<key>togglePowerMarker</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>ResultWindow</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>actionMenu</key>
<string>NSPopUpButton</string>
<key>actionMenuView</key>
<string>NSView</string>
<key>app</key>
<string>id</string>
<key>columnsMenu</key>
<string>NSMenu</string>
<key>deltaSwitch</key>
<string>NSSegmentedControl</string>
<key>deltaSwitchView</key>
<string>NSView</string>
<key>filterField</key>
<string>NSSearchField</string>
<key>filterFieldView</key>
<string>NSView</string>
<key>matches</key>
<string>MatchesView</string>
<key>pmSwitch</key>
<string>NSSegmentedControl</string>
<key>pmSwitchView</key>
<string>NSView</string>
<key>preferencesPanel</key>
<string>NSWindow</string>
<key>py</key>
<string>PyDupeGuru</string>
<key>stats</key>
<string>NSTextField</string>
</dict>
<key>SUPERCLASS</key>
<string>ResultWindowBase</string>
</dict>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>checkForUpdates</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>SUUpdater</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>clearMenu</key>
<string>id</string>
<key>menuClick</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>RecentDirectories</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>delegate</key>
<string>id</string>
<key>menu</key>
<string>NSMenu</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>ResultWindowBase</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSWindowController</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>598</integer>
</array>
<key>IBSystem Version</key>
<string>9E17</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -23,11 +23,13 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>5.6.6</string> <string>5.7.0</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2009</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru_me.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru_me.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -9,19 +9,13 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "cocoalib/Outline.h" #import "cocoalib/Outline.h"
#import "dgbase/ResultWindow.h" #import "dgbase/ResultWindow.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"
@interface ResultWindow : ResultWindowBase @interface ResultWindow : ResultWindowBase
{ {
IBOutlet NSPopUpButton *actionMenu;
IBOutlet NSMenu *columnsMenu;
IBOutlet NSSearchField *filterField; IBOutlet NSSearchField *filterField;
IBOutlet NSWindow *preferencesPanel;
NSString *_lastAction; NSString *_lastAction;
DetailsPanel *_detailsPanel;
NSMutableArray *_resultColumns;
NSMutableIndexSet *_deltaColumns; NSMutableIndexSet *_deltaColumns;
} }
- (IBAction)clearIgnoreList:(id)sender; - (IBAction)clearIgnoreList:(id)sender;
@@ -38,15 +32,7 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)removeMarked:(id)sender; - (IBAction)removeMarked:(id)sender;
- (IBAction)removeSelected:(id)sender; - (IBAction)removeSelected:(id)sender;
- (IBAction)renameSelected:(id)sender; - (IBAction)renameSelected:(id)sender;
- (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)revealSelected:(id)sender; - (IBAction)revealSelected:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)startDuplicateScan:(id)sender; - (IBAction)startDuplicateScan:(id)sender;
- (IBAction)toggleColumn:(id)sender;
- (IBAction)toggleDelta:(id)sender; - (IBAction)toggleDelta:(id)sender;
- (IBAction)toggleDetailsPanel:(id)sender;
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn;
- (void)initResultColumns;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
@end @end

View File

@@ -19,7 +19,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib - (void)awakeFromNib
{ {
[super awakeFromNib]; [super awakeFromNib];
_detailsPanel = nil; [[self window] setTitle:@"dupeGuru Music Edition"];
_displayDelta = NO; _displayDelta = NO;
_powerMode = NO; _powerMode = NO;
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,7)] retain]; _deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,7)] retain];
@@ -29,23 +29,8 @@ http://www.hardcoded.net/licenses/hs_license
[py setDisplayDeltaValues:b2n(_displayDelta)]; [py setDisplayDeltaValues:b2n(_displayDelta)];
[matches setTarget:self]; [matches setTarget:self];
[matches setDoubleAction:@selector(openSelected:)]; [matches setDoubleAction:@selector(openSelected:)];
[[actionMenu itemAtIndex:0] setImage:[NSImage imageNamed: @"gear"]];
[self initResultColumns];
[self refreshStats]; [self refreshStats];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil];
NSToolbar *t = [[[NSToolbar alloc] initWithIdentifier:@"ResultWindowToolbar"] autorelease];
[t setAllowsUserCustomization:YES];
[t setAutosavesConfiguration:YES];
[t setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[t setDelegate:self];
[[self window] setToolbar:t];
}
/* Overrides */
- (NSString *)logoImageName
{
return @"dgme_logo_32";
} }
/* Actions */ /* Actions */
@@ -182,11 +167,6 @@ http://www.hardcoded.net/licenses/hs_license
[py revealSelected]; [py revealSelected];
} }
- (IBAction)showPreferencesPanel:(id)sender
{
[preferencesPanel makeKeyAndOrderFront:sender];
}
- (IBAction)startDuplicateScan:(id)sender - (IBAction)startDuplicateScan:(id)sender
{ {
if ([matches numberOfRows] > 0) if ([matches numberOfRows] > 0)
@@ -219,26 +199,6 @@ http://www.hardcoded.net/licenses/hs_license
} }
} }
- (IBAction)toggleColumn:(id)sender
{
NSMenuItem *mi = sender;
NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]];
NSTableColumn *col = [matches tableColumnWithIdentifier:colId];
if (col == nil)
{
//Add Column
col = [_resultColumns objectAtIndex:[mi tag]];
[matches addTableColumn:col];
[mi setState:NSOnState];
}
else
{
//Remove column
[matches removeTableColumn:col];
[mi setState:NSOffState];
}
}
- (IBAction)toggleDelta:(id)sender - (IBAction)toggleDelta:(id)sender
{ {
if ([deltaSwitch selectedSegment] == 1) if ([deltaSwitch selectedSegment] == 1)
@@ -248,39 +208,22 @@ http://www.hardcoded.net/licenses/hs_license
[self changeDelta:sender]; [self changeDelta:sender];
} }
- (IBAction)toggleDetailsPanel:(id)sender
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
if ([[_detailsPanel window] isVisible])
[[_detailsPanel window] close];
else
[[_detailsPanel window] orderFront:nil];
}
/* Public */ /* Public */
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn
{
NSNumber *n = [NSNumber numberWithInt:aIdentifier];
NSTableColumn *col = [[NSTableColumn alloc] initWithIdentifier:[n stringValue]];
[col setWidth:aWidth];
[col setEditable:NO];
[[col dataCell] setFont:[[aColumn dataCell] font]];
[[col headerCell] setStringValue:aTitle];
[col setResizingMask:NSTableColumnUserResizingMask];
[col setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:[n stringValue] ascending:YES]];
return col;
}
- (void)initResultColumns - (void)initResultColumns
{ {
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init]; _resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"2"]]; // Size NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (MB)" width:63 refCol:refCol];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"3"]]; // Time [[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"4"]]; // Bitrate [_resultColumns addObject:sizeCol];
NSTableColumn *timeCol = [self getColumnForIdentifier:3 title:@"Time" width:50 refCol:refCol];
[[timeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:timeCol];
NSTableColumn *brCol = [self getColumnForIdentifier:4 title:@"Bitrate" width:50 refCol:refCol];
[[brCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:brCol];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Sample Rate" width:60 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Sample Rate" width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Kind" width:40 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Creation" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Creation" width:120 refCol:refCol]];
@@ -292,40 +235,11 @@ http://www.hardcoded.net/licenses/hs_license
[_resultColumns addObject:[self getColumnForIdentifier:13 title:@"Year" width:40 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:13 title:@"Year" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:14 title:@"Track Number" width:40 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:14 title:@"Track Number" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:15 title:@"Comment" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:15 title:@"Comment" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"16"]]; // Match % [_resultColumns addObject:[self getColumnForIdentifier:16 title:@"Match %" width:57 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:17 title:@"Words Used" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:17 title:@"Words Used" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:18 title:@"Dupe Count" width:80 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:18 title:@"Dupe Count" width:80 refCol:refCol]];
} }
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth
{
NSTableColumn *col;
NSString *colId;
NSNumber *width;
NSMenuItem *mi;
//Remove all columns
NSEnumerator *e = [[columnsMenu itemArray] objectEnumerator];
while (mi = [e nextObject])
{
if ([mi state] == NSOnState)
[self toggleColumn:mi];
}
//Add columns and set widths
e = [aColumnsOrder objectEnumerator];
while (colId = [e nextObject])
{
if (![colId isEqual:@"mark"])
{
col = [_resultColumns objectAtIndex:[colId intValue]];
width = [aColumnsWidth objectForKey:[col identifier]];
mi = [columnsMenu itemWithTag:[colId intValue]];
if (width)
[col setWidth:[width floatValue]];
[self toggleColumn:mi];
}
}
}
/* Delegate */ /* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{ {

View File

@@ -19,8 +19,6 @@
/* End PBXAppleScriptBuildPhase section */ /* End PBXAppleScriptBuildPhase section */
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
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 */; };
@@ -29,7 +27,8 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; }; CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; }; CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; }; CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */ = {isa = PBXBuildFile; fileRef = CE3AA46509DB207900DB3A21 /* Directories.nib */; }; CE3FBDD31094637800B72D77 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3FBDD11094637800B72D77 /* DetailsPanel.xib */; };
CE3FBDD41094637800B72D77 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */; };
CE49DEF60FDFEB810098617B /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */; }; CE49DEF60FDFEB810098617B /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */; };
CE49DEF70FDFEB810098617B /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF50FDFEB810098617B /* NSCharacterSet_Extensions.m */; }; CE49DEF70FDFEB810098617B /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF50FDFEB810098617B /* NSCharacterSet_Extensions.m */; };
CE515DF30FC6C12E00EC695D /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DE10FC6C12E00EC695D /* Dialogs.m */; }; CE515DF30FC6C12E00EC695D /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515DE10FC6C12E00EC695D /* Dialogs.m */; };
@@ -51,13 +50,11 @@
CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; }; CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; };
CE6E0E9F1054EB97008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */; }; CE6E0E9F1054EB97008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; }; CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CEA7D2C50FDFED340037CD8C /* dgme_logo_32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEA7D2C40FDFED340037CD8C /* dgme_logo_32.png */; }; CE900AD2109B238600754048 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD1109B238600754048 /* Preferences.xib */; };
CECA899909DB12CA00A3D774 /* Details.nib in Resources */ = {isa = PBXBuildFile; fileRef = CECA899709DB12CA00A3D774 /* Details.nib */; }; CE900AD7109B2A9B00754048 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD6109B2A9B00754048 /* MainMenu.xib */; };
CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; }; CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; };
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; }; CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; };
CED2A6880A05102700AC4C3F /* power_marker32.png in Resources */ = {isa = PBXBuildFile; fileRef = CED2A6870A05102600AC4C3F /* power_marker32.png */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; }; CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEF7823809C8AA0200EF38FF /* gear.png in Resources */ = {isa = PBXBuildFile; fileRef = CEF7823709C8AA0200EF38FF /* gear.png */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; }; CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; }; CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; }; CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
@@ -79,11 +76,9 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
@@ -95,7 +90,8 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; }; CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; }; CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; }; CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3AA46609DB207900DB3A21 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Directories.nib; sourceTree = "<group>"; }; CE3FBDD11094637800B72D77 /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DetailsPanel.xib; sourceTree = "<group>"; };
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DirectoryPanel.xib; sourceTree = "<group>"; };
CE49DEF20FDFEB810098617B /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; }; CE49DEF20FDFEB810098617B /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; }; CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; };
CE49DEF40FDFEB810098617B /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSCharacterSet_Extensions.h; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.h; sourceTree = SOURCE_ROOT; }; CE49DEF40FDFEB810098617B /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSCharacterSet_Extensions.h; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.h; sourceTree = SOURCE_ROOT; };
@@ -136,13 +132,11 @@
CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; }; CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; };
CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; }; CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; };
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>"; };
CEA7D2C40FDFED340037CD8C /* dgme_logo_32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dgme_logo_32.png; path = images/dgme_logo_32.png; sourceTree = SOURCE_ROOT; }; CE900AD1109B238600754048 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = ../../xib/Preferences.xib; sourceTree = "<group>"; };
CECA899809DB12CA00A3D774 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Details.nib; sourceTree = "<group>"; }; CE900AD6109B2A9B00754048 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; 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>"; }; CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = "<group>"; };
CED2A6870A05102600AC4C3F /* power_marker32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = power_marker32.png; path = images/power_marker32.png; sourceTree = SOURCE_ROOT; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; }; CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEF7823709C8AA0200EF38FF /* gear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gear.png; path = images/gear.png; sourceTree = "<group>"; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; }; CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; }; CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; }; CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; };
@@ -231,16 +225,13 @@
29B97317FDCFA39411CA2CEA /* Resources */ = { 29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CE3FBDD01094637800B72D77 /* xib */,
CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */, CE073F5409CAE1A3005C1D2F /* dupeguru_me_help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */, CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */, CEFC294309C89E0000D9F998 /* images */,
CEEB135109C837A2004D2330 /* dupeguru.icns */, CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */, 8D1107310486CEB800E47090 /* Info.plist */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */, CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */,
CECA899709DB12CA00A3D774 /* Details.nib */,
CE3AA46509DB207900DB3A21 /* Directories.nib */,
29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
); );
name = Resources; name = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -254,6 +245,18 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
CE3FBDD01094637800B72D77 /* xib */ = {
isa = PBXGroup;
children = (
CE900AD6109B2A9B00754048 /* MainMenu.xib */,
CE3FBDD11094637800B72D77 /* DetailsPanel.xib */,
CE3FBDD21094637800B72D77 /* DirectoryPanel.xib */,
CE900AD1109B238600754048 /* Preferences.xib */,
);
name = xib;
path = dgbase/xib;
sourceTree = "<group>";
};
CE49DEF10FDFEB810098617B /* brsinglelineformatter */ = { CE49DEF10FDFEB810098617B /* brsinglelineformatter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -316,9 +319,6 @@
CEFC294309C89E0000D9F998 /* images */ = { CEFC294309C89E0000D9F998 /* images */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CEA7D2C40FDFED340037CD8C /* dgme_logo_32.png */,
CED2A6870A05102600AC4C3F /* power_marker32.png */,
CEF7823709C8AA0200EF38FF /* gear.png */,
CEFC295309C89FF200D9F998 /* details32.png */, CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */, CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */, CEFC294509C89E3D00D9F998 /* folder32.png */,
@@ -371,23 +371,20 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */, CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_me_help in Resources */, CE073F6309CAE1A3005C1D2F /* dupeguru_me_help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */, CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */, CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */, CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */, CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CEF7823809C8AA0200EF38FF /* gear.png in Resources */,
CECA899909DB12CA00A3D774 /* Details.nib in Resources */,
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */,
CED2A6880A05102700AC4C3F /* power_marker32.png in Resources */,
CE515E020FC6C13E00EC695D /* ErrorReportWindow.xib in Resources */, CE515E020FC6C13E00EC695D /* ErrorReportWindow.xib in Resources */,
CE515E030FC6C13E00EC695D /* progress.nib in Resources */, CE515E030FC6C13E00EC695D /* progress.nib in Resources */,
CE515E040FC6C13E00EC695D /* registration.nib in Resources */, CE515E040FC6C13E00EC695D /* registration.nib in Resources */,
CEA7D2C50FDFED340037CD8C /* dgme_logo_32.png in Resources */,
CE6E0E9F1054EB97008D9390 /* dsa_pub.pem in Resources */, CE6E0E9F1054EB97008D9390 /* dsa_pub.pem in Resources */,
CE3FBDD31094637800B72D77 /* DetailsPanel.xib in Resources */,
CE3FBDD41094637800B72D77 /* DirectoryPanel.xib in Resources */,
CE900AD2109B238600754048 /* Preferences.xib in Resources */,
CE900AD7109B2A9B00754048 /* MainMenu.xib in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -424,30 +421,6 @@
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C165DFE840E0CC02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
isa = PBXVariantGroup;
children = (
29B97319FDCFA39411CA2CEA /* English */,
);
name = MainMenu.nib;
sourceTree = SOURCE_ROOT;
};
CE3AA46509DB207900DB3A21 /* Directories.nib */ = {
isa = PBXVariantGroup;
children = (
CE3AA46609DB207900DB3A21 /* English */,
);
name = Directories.nib;
sourceTree = "<group>";
};
CE515DFC0FC6C13E00EC695D /* ErrorReportWindow.xib */ = { CE515DFC0FC6C13E00EC695D /* ErrorReportWindow.xib */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
children = ( children = (
@@ -472,38 +445,9 @@
name = registration.nib; name = registration.nib;
sourceTree = SOURCE_ROOT; sourceTree = SOURCE_ROOT;
}; };
CECA899709DB12CA00A3D774 /* Details.nib */ = {
isa = PBXVariantGroup;
children = (
CECA899809DB12CA00A3D774 /* English */,
);
name = Details.nib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */ /* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(FRAMEWORK_SEARCH_PATHS)",
"$(SRCROOT)/../../../cocoalib/build/Release",
"\"$(SRCROOT)/../../base/cocoa/build/Release\"",
);
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
PRODUCT_NAME = dupeGuru;
WRAPPER_EXTENSION = app;
ZERO_LINK = YES;
};
name = Debug;
};
C01FCF4C08A954540054247B /* Release */ = { C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@@ -521,32 +465,16 @@
}; };
name = Release; name = Release;
}; };
C01FCF4F08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4;
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
};
name = Debug;
};
C01FCF5008A954540054247B /* Release */ = { C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = c99; GCC_C_LANGUAGE_STANDARD = c99;
GCC_VERSION = 4.0;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4; MACOSX_DEPLOYMENT_TARGET = 10.5;
PREBINDING = NO; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
STRIP_INSTALLED_PRODUCT = NO;
}; };
name = Release; name = Release;
}; };
@@ -556,7 +484,6 @@
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = { C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4B08A954540054247B /* Debug */,
C01FCF4C08A954540054247B /* Release */, C01FCF4C08A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@@ -565,7 +492,6 @@
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = { C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
C01FCF5008A954540054247B /* Release */, C01FCF5008A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;

View File

@@ -5,13 +5,15 @@
# 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
sys.path.insert(0, 'py') # for hsutil and hsdocgen
import os import os
from help import gen
print "Generating help" print "Generating help"
os.chdir('help') gen.generate()
os.system('python -u gen.py') os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer help/dupeguru_me_help')
os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer dupeguru_me_help')
os.chdir('..')
print "Generating py plugin" print "Generating py plugin"
os.chdir('py') os.chdir('py')

View File

@@ -16,4 +16,5 @@ if op.exists('build'):
if op.exists('dist'): if op.exists('dist'):
shutil.rmtree('dist') shutil.rmtree('dist')
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.5'
print_and_do('python -u setup.py py2app') print_and_do('python -u setup.py py2app')

2611
me/cocoa/xib/Preferences.xib Normal file

File diff suppressed because it is too large Load Diff

0
me/help/__init__.py Normal file
View File

View File

@@ -1,3 +1,12 @@
- date: 2009-12-18
version: 5.7.0
description: |
* Added drag & drop support in the Directories panel. (#9)
* Fixed a bug causing dupeGuru to be confused if a scanned file was moved during the scan. (#72)
* Clarified how directories' state are set by painting a combo box in the state cells. [Windows]
(#76)
* Fixed some crashes. (#78 and #79)
* Dropped Mac OS X Tiger support.
- date: 2009-10-14 - date: 2009-10-14
version: 5.6.6 version: 5.6.6
description: | description: |

View File

@@ -5,10 +5,10 @@
# 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 os import os.path as op
from hsdocgen import generate_help, filters from hsdocgen import generate_help, filters
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}") def generate(windows=False):
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}")
generate_help.main('.', 'dupeguru_me_help', force_render=True, tix=tix) basepath = op.dirname(__file__)
generate_help.main(basepath, op.join(basepath, 'dupeguru_me_help'), force_render=True, tix=tix, windows=windows)

View File

@@ -64,4 +64,12 @@ If your comparison threshold is low enough, you will probably end up with live a
* **Mac OS X**: Type "[*]" in the "Filter" field in the toolbar. * **Mac OS X**: Type "[*]" in the "Filter" field in the toolbar.
* Click on **Mark --> Mark All**. * Click on **Mark --> Mark All**.
* Click on **Actions --> Remove Selected from Results**. * Click on **Actions --> Remove Selected from Results**.
### I tried to send my duplicates to Trash, but dupeGuru is telling me it can't do it. Why? What can I do?
Most of the time, the reason why dupeGuru can't send files to Trash is because of file permissions. You need *write* permissions on files you want to send to Trash. If you're not familiar with the command line, you can use utilities such as [BatChmod](http://macchampion.com/arbysoft/BatchMod) to fix your permissions.
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
</%text> </%text>

View File

@@ -17,7 +17,7 @@ from preferences_dialog import PreferencesDialog
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_me' LOGO_NAME = 'logo_me'
NAME = 'dupeGuru Music Edition' NAME = 'dupeGuru Music Edition'
VERSION = '5.6.6' VERSION = '5.7.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):

View File

@@ -13,10 +13,13 @@ import os.path as op
from hsutil.build import print_and_do, build_all_qt_ui from hsutil.build import print_and_do, build_all_qt_ui
from help import gen
build_all_qt_ui(op.join('qtlib', 'ui')) build_all_qt_ui(op.join('qtlib', 'ui'))
build_all_qt_ui('base') build_all_qt_ui('base')
build_all_qt_ui('.') build_all_qt_ui('.')
os.chdir('base')
os.chdir('help') print_and_do("pyrcc4 dg.qrc > dg_rc.py")
print_and_do('python gen.py')
os.chdir('..') os.chdir('..')
gen.generate(windows=True)

View File

@@ -8,20 +8,14 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "dgbase/AppDelegate.h" #import "dgbase/AppDelegate.h"
#import "ResultWindow.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"
#import "DetailsPanel.h"
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase @interface AppDelegate : AppDelegateBase
{ {
IBOutlet ResultWindow *result;
DetailsPanel *_detailsPanel;
DirectoryPanel *_directoryPanel; DirectoryPanel *_directoryPanel;
} }
- (IBAction)openWebsite:(id)sender; - (IBAction)openWebsite:(id)sender;
- (IBAction)toggleDetailsPanel:(id)sender;
- (IBAction)toggleDirectories:(id)sender; - (IBAction)toggleDirectories:(id)sender;
- (DirectoryPanel *)directoryPanel; - (DirectoryPanel *)directoryPanel;

View File

@@ -12,6 +12,7 @@ http://www.hardcoded.net/licenses/hs_license
#import "Utils.h" #import "Utils.h"
#import "ValueTransformers.h" #import "ValueTransformers.h"
#import "Consts.h" #import "Consts.h"
#import "DetailsPanel.h"
@implementation AppDelegate @implementation AppDelegate
+ (void)initialize + (void)initialize
@@ -36,29 +37,22 @@ http://www.hardcoded.net/licenses/hs_license
{ {
self = [super init]; self = [super init];
_directoryPanel = nil; _directoryPanel = nil;
_detailsPanel = nil;
_appName = APPNAME; _appName = APPNAME;
return self; return self;
} }
- (DetailsPanelBase *)detailsPanel
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
return _detailsPanel;
}
- (IBAction)openWebsite:(id)sender - (IBAction)openWebsite:(id)sender
{ {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_pe"]]; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/dupeguru_pe"]];
} }
- (IBAction)toggleDetailsPanel:(id)sender
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
if ([[_detailsPanel window] isVisible])
[[_detailsPanel window] close];
else
{
[[_detailsPanel window] orderFront:nil];
[_detailsPanel refresh];
}
}
- (IBAction)toggleDirectories:(id)sender - (IBAction)toggleDirectories:(id)sender
{ {
[[self directoryPanel] toggleVisible:sender]; [[self directoryPanel] toggleVisible:sender];
@@ -75,19 +69,12 @@ http://www.hardcoded.net/licenses/hs_license
//Delegate //Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{ {
[[ProgressController mainProgressController] setWorker:py]; NSMenu *actionsMenu = [[[NSApp mainMenu] itemWithTitle:@"Actions"] submenu];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; // index 2 is just after "Clear Ingore List"
//Restore Columns NSMenuItem *mi = [actionsMenu insertItemWithTitle:@"Clear Picture Cache" action:@selector(clearPictureCache:) keyEquivalent:@"P" atIndex:2];
NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"]; [mi setTarget:result];
NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"]; [mi setKeyEquivalentModifierMask:NSCommandKeyMask|NSShiftKeyMask];
if ([columnsOrder count]) [super applicationDidFinishLaunching:aNotification];
[result restoreColumnsPosition:columnsOrder widths:columnsWidth];
//Reg stuff
if ([RegistrationInterface showNagWithApp:[self py] name:APPNAME limitDescription:LIMIT_DESC])
[unlockMenuItem setTitle:@"Thanks for buying dupeGuru Picture Edition!"];
//Restore results
[py loadIgnoreList];
[py loadResults];
} }
- (void)applicationWillBecomeActive:(NSNotification *)aNotification - (void)applicationWillBecomeActive:(NSNotification *)aNotification

View File

@@ -1,24 +0,0 @@
{
IBClasses = (
{
CLASS = DetailsPanel;
LANGUAGE = ObjC;
OUTLETS = {
detailsTable = NSTableView;
dupeImage = NSImageView;
dupeProgressIndicator = NSProgressIndicator;
refImage = NSImageView;
refProgressIndicator = NSProgressIndicator;
};
SUPERCLASS = NSWindowController;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = TableView;
LANGUAGE = ObjC;
OUTLETS = {py = PyApp; };
SUPERCLASS = NSTableView;
}
);
IBVersion = 1;
}

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>701 68 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>446.1</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8R2232</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>askForDirectory</key>
<string>id</string>
<key>changeDirectoryState</key>
<string>id</string>
<key>popupAddDirectoryMenu</key>
<string>id</string>
<key>removeSelectedDirectory</key>
<string>id</string>
<key>toggleVisible</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>DirectoryPanel</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>addButtonPopUp</key>
<string>NSPopUpButton</string>
<key>directories</key>
<string>NSOutlineView</string>
<key>removeButton</key>
<string>NSButton</string>
</dict>
<key>SUPERCLASS</key>
<string>DirectoryPanelBase</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>9B18</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -1,235 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>NSSegmentedControl</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSControl</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>openWebsite</key>
<string>id</string>
<key>toggleDetailsPanel</key>
<string>id</string>
<key>toggleDirectories</key>
<string>id</string>
<key>unlockApp</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>AppDelegate</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyDupeGuru</string>
<key>recentDirectories</key>
<string>RecentDirectories</string>
<key>result</key>
<string>ResultWindow</string>
<key>unlockMenuItem</key>
<string>NSMenuItem</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyApp</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>MatchesView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>OutlineView</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyDupeGuru</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>PyApp</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>changeDelta</key>
<string>id</string>
<key>changePowerMarker</key>
<string>id</string>
<key>clearIgnoreList</key>
<string>id</string>
<key>clearPictureCache</key>
<string>id</string>
<key>collapseAll</key>
<string>id</string>
<key>copyMarked</key>
<string>id</string>
<key>deleteMarked</key>
<string>id</string>
<key>expandAll</key>
<string>id</string>
<key>exportToXHTML</key>
<string>id</string>
<key>filter</key>
<string>id</string>
<key>ignoreSelected</key>
<string>id</string>
<key>markAll</key>
<string>id</string>
<key>markInvert</key>
<string>id</string>
<key>markNone</key>
<string>id</string>
<key>markSelected</key>
<string>id</string>
<key>markToggle</key>
<string>id</string>
<key>moveMarked</key>
<string>id</string>
<key>openSelected</key>
<string>id</string>
<key>refresh</key>
<string>id</string>
<key>removeMarked</key>
<string>id</string>
<key>removeSelected</key>
<string>id</string>
<key>renameSelected</key>
<string>id</string>
<key>resetColumnsToDefault</key>
<string>id</string>
<key>revealSelected</key>
<string>id</string>
<key>showPreferencesPanel</key>
<string>id</string>
<key>startDuplicateScan</key>
<string>id</string>
<key>switchSelected</key>
<string>id</string>
<key>toggleColumn</key>
<string>id</string>
<key>toggleDelta</key>
<string>id</string>
<key>toggleDetailsPanel</key>
<string>id</string>
<key>toggleDirectories</key>
<string>id</string>
<key>togglePowerMarker</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>ResultWindow</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>actionMenu</key>
<string>NSPopUpButton</string>
<key>actionMenuView</key>
<string>NSView</string>
<key>app</key>
<string>id</string>
<key>columnsMenu</key>
<string>NSMenu</string>
<key>deltaSwitch</key>
<string>NSSegmentedControl</string>
<key>deltaSwitchView</key>
<string>NSView</string>
<key>filterField</key>
<string>NSSearchField</string>
<key>filterFieldView</key>
<string>NSView</string>
<key>matches</key>
<string>MatchesView</string>
<key>pmSwitch</key>
<string>NSSegmentedControl</string>
<key>pmSwitchView</key>
<string>NSView</string>
<key>preferencesPanel</key>
<string>NSWindow</string>
<key>py</key>
<string>PyDupeGuru</string>
<key>stats</key>
<string>NSTextField</string>
</dict>
<key>SUPERCLASS</key>
<string>NSWindowController</string>
</dict>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>checkForUpdates</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>SUUpdater</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>clearMenu</key>
<string>id</string>
<key>menuClick</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>RecentDirectories</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>delegate</key>
<string>id</string>
<key>menu</key>
<string>NSMenu</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>4</integer>
<key>IBOpenObjects</key>
<array>
<integer>524</integer>
</array>
<key>IBSystem Version</key>
<string>9B18</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -23,11 +23,13 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.7.7</string> <string>1.8.0</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2009</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru_pe.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru_pe.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -9,16 +9,11 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "Outline.h" #import "Outline.h"
#import "dgbase/ResultWindow.h" #import "dgbase/ResultWindow.h"
#import "DirectoryPanel.h"
@interface ResultWindow : ResultWindowBase @interface ResultWindow : ResultWindowBase
{ {
IBOutlet NSPopUpButton *actionMenu;
IBOutlet NSMenu *columnsMenu;
IBOutlet NSSearchField *filterField; IBOutlet NSSearchField *filterField;
IBOutlet NSWindow *preferencesPanel;
NSMutableArray *_resultColumns;
NSMutableIndexSet *_deltaColumns; NSMutableIndexSet *_deltaColumns;
} }
- (IBAction)clearIgnoreList:(id)sender; - (IBAction)clearIgnoreList:(id)sender;
@@ -35,16 +30,8 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)removeMarked:(id)sender; - (IBAction)removeMarked:(id)sender;
- (IBAction)removeSelected:(id)sender; - (IBAction)removeSelected:(id)sender;
- (IBAction)renameSelected:(id)sender; - (IBAction)renameSelected:(id)sender;
- (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)revealSelected:(id)sender; - (IBAction)revealSelected:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)startDuplicateScan:(id)sender; - (IBAction)startDuplicateScan:(id)sender;
- (IBAction)toggleColumn:(id)sender;
- (IBAction)toggleDelta:(id)sender; - (IBAction)toggleDelta:(id)sender;
- (IBAction)toggleDetailsPanel:(id)sender;
- (IBAction)toggleDirectories:(id)sender; - (IBAction)toggleDirectories:(id)sender;
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn;
- (void)initResultColumns;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
@end @end

View File

@@ -19,6 +19,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib - (void)awakeFromNib
{ {
[super awakeFromNib]; [super awakeFromNib];
[[self window] setTitle:@"dupeGuru Picture Edition"];
_displayDelta = NO; _displayDelta = NO;
_powerMode = NO; _powerMode = NO;
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,5)] retain]; _deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,5)] retain];
@@ -29,23 +30,8 @@ http://www.hardcoded.net/licenses/hs_license
[py setDisplayDeltaValues:b2n(_displayDelta)]; [py setDisplayDeltaValues:b2n(_displayDelta)];
[matches setTarget:self]; [matches setTarget:self];
[matches setDoubleAction:@selector(openSelected:)]; [matches setDoubleAction:@selector(openSelected:)];
[[actionMenu itemAtIndex:0] setImage:[NSImage imageNamed: @"gear"]];
[self initResultColumns];
[self refreshStats]; [self refreshStats];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil];
NSToolbar *t = [[[NSToolbar alloc] initWithIdentifier:@"ResultWindowToolbar"] autorelease];
[t setAllowsUserCustomization:YES];
[t setAutosavesConfiguration:YES];
[t setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[t setDelegate:self];
[[self window] setToolbar:t];
}
/* Overrides */
- (NSString *)logoImageName
{
return @"dgpe_logo_32";
} }
/* Actions */ /* Actions */
@@ -170,7 +156,7 @@ http://www.hardcoded.net/licenses/hs_license
[columnsOrder addObject:@"4"]; [columnsOrder addObject:@"4"];
[columnsOrder addObject:@"7"]; [columnsOrder addObject:@"7"];
NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary]; NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary];
[columnsWidth setObject:i2n(125) forKey:@"0"]; [columnsWidth setObject:i2n(121) forKey:@"0"];
[columnsWidth setObject:i2n(120) forKey:@"1"]; [columnsWidth setObject:i2n(120) forKey:@"1"];
[columnsWidth setObject:i2n(63) forKey:@"2"]; [columnsWidth setObject:i2n(63) forKey:@"2"];
[columnsWidth setObject:i2n(73) forKey:@"4"]; [columnsWidth setObject:i2n(73) forKey:@"4"];
@@ -184,11 +170,6 @@ http://www.hardcoded.net/licenses/hs_license
[py revealSelected]; [py revealSelected];
} }
- (IBAction)showPreferencesPanel:(id)sender
{
[preferencesPanel makeKeyAndOrderFront:sender];
}
- (IBAction)startDuplicateScan:(id)sender - (IBAction)startDuplicateScan:(id)sender
{ {
if ([matches numberOfRows] > 0) if ([matches numberOfRows] > 0)
@@ -215,26 +196,6 @@ http://www.hardcoded.net/licenses/hs_license
} }
} }
- (IBAction)toggleColumn:(id)sender
{
NSMenuItem *mi = sender;
NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]];
NSTableColumn *col = [matches tableColumnWithIdentifier:colId];
if (col == nil)
{
//Add Column
col = [_resultColumns objectAtIndex:[mi tag]];
[matches addTableColumn:col];
[mi setState:NSOnState];
}
else
{
//Remove column
[matches removeTableColumn:col];
[mi setState:NSOffState];
}
}
- (IBAction)toggleDelta:(id)sender - (IBAction)toggleDelta:(id)sender
{ {
if ([deltaSwitch selectedSegment] == 1) if ([deltaSwitch selectedSegment] == 1)
@@ -244,75 +205,29 @@ http://www.hardcoded.net/licenses/hs_license
[self changeDelta:sender]; [self changeDelta:sender];
} }
- (IBAction)toggleDetailsPanel:(id)sender
{
[(AppDelegate *)app toggleDetailsPanel:sender];
}
- (IBAction)toggleDirectories:(id)sender - (IBAction)toggleDirectories:(id)sender
{ {
[(AppDelegate *)app toggleDirectories:sender]; [(AppDelegate *)app toggleDirectories:sender];
} }
/* Public */ /* Public */
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn
{
NSNumber *n = [NSNumber numberWithInt:aIdentifier];
NSTableColumn *col = [[NSTableColumn alloc] initWithIdentifier:[n stringValue]];
[col setWidth:aWidth];
[col setEditable:NO];
[[col dataCell] setFont:[[aColumn dataCell] font]];
[[col headerCell] setStringValue:aTitle];
[col setResizingMask:NSTableColumnUserResizingMask];
[col setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:[n stringValue] ascending:YES]];
return col;
}
- (void)initResultColumns - (void)initResultColumns
{ {
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init]; _resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"1"]]; // Directory [_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"2"]]; // Size NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (KB)" width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Dimensions" width:80 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Dimensions" width:80 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Creation" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Creation" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Modification" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Modification" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"7"]]; // Match % [_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Match %" width:58 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:8 title:@"Dupe Count" width:80 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:8 title:@"Dupe Count" width:80 refCol:refCol]];
} }
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth
{
NSTableColumn *col;
NSString *colId;
NSNumber *width;
NSMenuItem *mi;
//Remove all columns
NSEnumerator *e = [[columnsMenu itemArray] objectEnumerator];
while (mi = [e nextObject])
{
if ([mi state] == NSOnState)
[self toggleColumn:mi];
}
//Add columns and set widths
e = [aColumnsOrder objectEnumerator];
while (colId = [e nextObject])
{
if (![colId isEqual:@"mark"])
{
col = [_resultColumns objectAtIndex:[colId intValue]];
width = [aColumnsWidth objectForKey:[col identifier]];
mi = [columnsMenu itemWithTag:[colId intValue]];
if (width)
[col setWidth:[width floatValue]];
[self toggleColumn:mi];
}
}
}
/* Delegate */ /* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{ {

View File

@@ -3,14 +3,14 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 42; objectVersion = 44;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
CE031751109B340A00517EE6 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031750109B340A00517EE6 /* Preferences.xib */; };
CE031754109B345200517EE6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031753109B345200517EE6 /* MainMenu.xib */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */; }; CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */; };
CE0C46AA0FA0647E000BE99B /* PictureBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C46A90FA0647E000BE99B /* PictureBlocks.m */; }; CE0C46AA0FA0647E000BE99B /* PictureBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C46A90FA0647E000BE99B /* PictureBlocks.m */; };
CE15C8A80ADEB8B50061D4A5 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; }; CE15C8A80ADEB8B50061D4A5 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; };
@@ -18,10 +18,11 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; }; CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; }; CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; }; CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */ = {isa = PBXBuildFile; fileRef = CE3AA46509DB207900DB3A21 /* Directories.nib */; };
CE6044EC0FE6796200B71262 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6044EB0FE6796200B71262 /* DetailsPanel.m */; }; CE6044EC0FE6796200B71262 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6044EB0FE6796200B71262 /* DetailsPanel.m */; };
CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; }; CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; };
CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */; }; CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */; };
CE77C89E10946C6D0078B0DB /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */; };
CE77C8A810946CE20078B0DB /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE77C8A710946CE20078B0DB /* DetailsPanel.xib */; };
CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1C0FC192D60086DCA6 /* Dialogs.m */; }; CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1C0FC192D60086DCA6 /* Dialogs.m */; };
CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */; }; CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB1E0FC192D60086DCA6 /* HSErrorReportWindow.m */; };
CE80DB300FC192D60086DCA6 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB200FC192D60086DCA6 /* Outline.m */; }; CE80DB300FC192D60086DCA6 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB200FC192D60086DCA6 /* Outline.m */; };
@@ -42,11 +43,9 @@
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; }; CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CEBAE4270FDA97E000B7887D /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */; }; CEBAE4270FDA97E000B7887D /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */; };
CEBAE4280FDA97E000B7887D /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBAE4260FDA97E000B7887D /* NSCharacterSet_Extensions.m */; }; CEBAE4280FDA97E000B7887D /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBAE4260FDA97E000B7887D /* NSCharacterSet_Extensions.m */; };
CECA899909DB12CA00A3D774 /* Details.nib in Resources */ = {isa = PBXBuildFile; fileRef = CECA899709DB12CA00A3D774 /* Details.nib */; };
CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; }; CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; };
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; }; CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; }; CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEF7823809C8AA0200EF38FF /* gear.png in Resources */ = {isa = PBXBuildFile; fileRef = CEF7823709C8AA0200EF38FF /* gear.png */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; }; CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; }; CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; }; CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
@@ -69,15 +68,15 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
8D1107320486CEB800E47090 /* dupeGuru PE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "dupeGuru PE.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 8D1107320486CEB800E47090 /* dupeGuru PE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "dupeGuru PE.app"; sourceTree = BUILT_PRODUCTS_DIR; };
CE031750109B340A00517EE6 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = ../../xib/Preferences.xib; sourceTree = "<group>"; };
CE031753109B345200517EE6 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_pe_help; path = help/dupeguru_pe_help; sourceTree = SOURCE_ROOT; }; CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_pe_help; path = help/dupeguru_pe_help; sourceTree = SOURCE_ROOT; };
CE0C46A80FA0647E000BE99B /* PictureBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PictureBlocks.h; sourceTree = "<group>"; }; CE0C46A80FA0647E000BE99B /* PictureBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PictureBlocks.h; sourceTree = "<group>"; };
CE0C46A90FA0647E000BE99B /* PictureBlocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PictureBlocks.m; sourceTree = "<group>"; }; CE0C46A90FA0647E000BE99B /* PictureBlocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PictureBlocks.m; sourceTree = "<group>"; };
@@ -87,12 +86,13 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; }; CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; }; CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; }; CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3AA46609DB207900DB3A21 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Directories.nib; sourceTree = "<group>"; };
CE6044EA0FE6796200B71262 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = dgbase/DetailsPanel.h; sourceTree = SOURCE_ROOT; }; CE6044EA0FE6796200B71262 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = dgbase/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE6044EB0FE6796200B71262 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = dgbase/DetailsPanel.m; sourceTree = SOURCE_ROOT; }; CE6044EB0FE6796200B71262 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = dgbase/DetailsPanel.m; sourceTree = SOURCE_ROOT; };
CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; }; CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; };
CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; }; CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; };
CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; }; CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; };
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DirectoryPanel.xib; sourceTree = "<group>"; };
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DetailsPanel.xib; path = ../../xib/DetailsPanel.xib; sourceTree = "<group>"; };
CE80DB1B0FC192D60086DCA6 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; }; CE80DB1B0FC192D60086DCA6 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
CE80DB1C0FC192D60086DCA6 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; }; CE80DB1C0FC192D60086DCA6 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; }; CE80DB1D0FC192D60086DCA6 /* HSErrorReportWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSErrorReportWindow.h; path = cocoalib/HSErrorReportWindow.h; sourceTree = SOURCE_ROOT; };
@@ -132,11 +132,9 @@
CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; }; CEBAE4240FDA97E000B7887D /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; };
CEBAE4250FDA97E000B7887D /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSCharacterSet_Extensions.h; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.h; sourceTree = SOURCE_ROOT; }; CEBAE4250FDA97E000B7887D /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSCharacterSet_Extensions.h; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.h; sourceTree = SOURCE_ROOT; };
CEBAE4260FDA97E000B7887D /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSCharacterSet_Extensions.m; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.m; sourceTree = SOURCE_ROOT; }; CEBAE4260FDA97E000B7887D /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSCharacterSet_Extensions.m; path = cocoalib/brsinglelineformatter/NSCharacterSet_Extensions.m; sourceTree = SOURCE_ROOT; };
CECA899809DB12CA00A3D774 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Details.nib; sourceTree = "<group>"; };
CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; 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>"; }; CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = "<group>"; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; }; CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEF7823709C8AA0200EF38FF /* gear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gear.png; path = images/gear.png; sourceTree = "<group>"; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; }; CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; }; CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; }; CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; };
@@ -228,16 +226,13 @@
29B97317FDCFA39411CA2CEA /* Resources */ = { 29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CE77C89A10946C6D0078B0DB /* xib */,
CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */, CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */, CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */, CEFC294309C89E0000D9F998 /* images */,
CEEB135109C837A2004D2330 /* dupeguru.icns */, CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */, 8D1107310486CEB800E47090 /* Info.plist */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */, CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */,
CECA899709DB12CA00A3D774 /* Details.nib */,
CE3AA46509DB207900DB3A21 /* Directories.nib */,
29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
); );
name = Resources; name = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -251,6 +246,18 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
CE77C89A10946C6D0078B0DB /* xib */ = {
isa = PBXGroup;
children = (
CE031753109B345200517EE6 /* MainMenu.xib */,
CE77C8A710946CE20078B0DB /* DetailsPanel.xib */,
CE77C89C10946C6D0078B0DB /* DirectoryPanel.xib */,
CE031750109B340A00517EE6 /* Preferences.xib */,
);
name = xib;
path = dgbase/xib;
sourceTree = "<group>";
};
CE80DB1A0FC192AB0086DCA6 /* cocoalib */ = { CE80DB1A0FC192AB0086DCA6 /* cocoalib */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -318,7 +325,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CEFCDE2C0AB0418600C33A93 /* dgpe_logo_32.png */, CEFCDE2C0AB0418600C33A93 /* dgpe_logo_32.png */,
CEF7823709C8AA0200EF38FF /* gear.png */,
CEFC295309C89FF200D9F998 /* details32.png */, CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */, CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */, CEFC294509C89E3D00D9F998 /* folder32.png */,
@@ -354,7 +360,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */;
compatibilityVersion = "Xcode 2.4"; compatibilityVersion = "Xcode 3.0";
hasScannedForEncodings = 1; hasScannedForEncodings = 1;
mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */; mainGroup = 29B97314FDCFA39411CA2CEA /* dupeguru */;
projectDirPath = ""; projectDirPath = "";
@@ -370,22 +376,21 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */, CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */, CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */, CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */, CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */, CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */, CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CEF7823809C8AA0200EF38FF /* gear.png in Resources */,
CECA899909DB12CA00A3D774 /* Details.nib in Resources */,
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */,
CEFCDE2D0AB0418600C33A93 /* dgpe_logo_32.png in Resources */, CEFCDE2D0AB0418600C33A93 /* dgpe_logo_32.png in Resources */,
CE80DB760FC194760086DCA6 /* ErrorReportWindow.xib in Resources */, CE80DB760FC194760086DCA6 /* ErrorReportWindow.xib in Resources */,
CE80DB770FC194760086DCA6 /* progress.nib in Resources */, CE80DB770FC194760086DCA6 /* progress.nib in Resources */,
CE80DB780FC194760086DCA6 /* registration.nib in Resources */, CE80DB780FC194760086DCA6 /* registration.nib in Resources */,
CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */, CE6E0F3D1054EC62008D9390 /* dsa_pub.pem in Resources */,
CE77C89E10946C6D0078B0DB /* DirectoryPanel.xib in Resources */,
CE77C8A810946CE20078B0DB /* DetailsPanel.xib in Resources */,
CE031751109B340A00517EE6 /* Preferences.xib in Resources */,
CE031754109B345200517EE6 /* MainMenu.xib in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -425,30 +430,6 @@
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C165DFE840E0CC02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
isa = PBXVariantGroup;
children = (
29B97319FDCFA39411CA2CEA /* English */,
);
name = MainMenu.nib;
sourceTree = SOURCE_ROOT;
};
CE3AA46509DB207900DB3A21 /* Directories.nib */ = {
isa = PBXVariantGroup;
children = (
CE3AA46609DB207900DB3A21 /* English */,
);
name = Directories.nib;
sourceTree = "<group>";
};
CE80DB700FC194760086DCA6 /* ErrorReportWindow.xib */ = { CE80DB700FC194760086DCA6 /* ErrorReportWindow.xib */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
children = ( children = (
@@ -473,39 +454,9 @@
name = registration.nib; name = registration.nib;
sourceTree = SOURCE_ROOT; sourceTree = SOURCE_ROOT;
}; };
CECA899709DB12CA00A3D774 /* Details.nib */ = {
isa = PBXVariantGroup;
children = (
CECA899809DB12CA00A3D774 /* English */,
);
name = Details.nib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */ /* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(FRAMEWORK_SEARCH_PATHS)",
"$(SRCROOT)/cocoalib/build/Release",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
);
FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/dgbase/build/Release\"";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
PRODUCT_NAME = dupeGuru;
WRAPPER_EXTENSION = app;
ZERO_LINK = YES;
};
name = Debug;
};
C01FCF4C08A954540054247B /* Release */ = { C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@@ -526,31 +477,16 @@
}; };
name = Release; name = Release;
}; };
C01FCF4F08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
name = Debug;
};
C01FCF5008A954540054247B /* Release */ = { C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386";
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = c99; GCC_C_LANGUAGE_STANDARD = c99;
GCC_VERSION = 4.0;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4; MACOSX_DEPLOYMENT_TARGET = 10.5;
PREBINDING = NO; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
}; };
name = Release; name = Release;
}; };
@@ -560,7 +496,6 @@
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = { C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4B08A954540054247B /* Debug */,
C01FCF4C08A954540054247B /* Release */, C01FCF4C08A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@@ -569,7 +504,6 @@
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = { C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
C01FCF5008A954540054247B /* Release */, C01FCF5008A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;

View File

@@ -5,13 +5,15 @@
# 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
sys.path.insert(0, 'py') # for hsutil and hsdocgen
import os import os
from help import gen
print "Generating help" print "Generating help"
os.chdir('help') gen.generate()
os.system('python -u gen.py') os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer help/dupeguru_pe_help')
os.system('/Developer/Applications/Utilities/Help\\ Indexer.app/Contents/MacOS/Help\\ Indexer dupeguru_pe_help')
os.chdir('..')
print "Generating py plugin" print "Generating py plugin"
os.chdir('py') os.chdir('py')

File diff suppressed because it is too large Load Diff

1650
pe/cocoa/xib/Preferences.xib Normal file

File diff suppressed because it is too large Load Diff

0
pe/help/__init__.py Normal file
View File

View File

@@ -1,3 +1,12 @@
- date: 2009-12-16
version: 1.8.0
description: |
* Added drag & drop support in the Directories panel. (#9)
* Fixed a bug causing dupeGuru to be confused if a scanned file was moved during the scan. (#72)
* Clarified how directories' state are set by painting a combo box in the state cells. [Windows]
(#76)
* Fixed some crashes. (#78 and #79)
* Dropped Mac OS X Tiger support.
- date: 2009-10-24 - date: 2009-10-24
version: 1.7.8 version: 1.7.8
description: | description: |

View File

@@ -5,10 +5,10 @@
# 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 os import os.path as op
from hsdocgen import generate_help, filters from hsdocgen import generate_help, filters
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}") def generate(windows=False):
tix = filters.tixgen("https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}")
generate_help.main('.', 'dupeguru_pe_help', force_render=True, tix=tix) basepath = op.dirname(__file__)
generate_help.main(basepath, op.join(basepath, 'dupeguru_pe_help'), force_render=True, tix=tix, windows=windows)

View File

@@ -61,4 +61,14 @@ Enable the [Power Marker](power_marker.htm) mode and click on the Directory colu
* **Windows**: Click on **Actions --> Apply Filter**, then type "copy", then click OK. * **Windows**: Click on **Actions --> Apply Filter**, then type "copy", then click OK.
* **Mac OS X**: Type "copy" in the "Filter" field in the toolbar. * **Mac OS X**: Type "copy" in the "Filter" field in the toolbar.
* Click on **Mark --> Mark All**. * Click on **Mark --> Mark All**.
### I tried to send my duplicates to Trash, but dupeGuru is telling me it can't do it. Why? What can I do?
Most of the time, the reason why dupeGuru can't send files to Trash is because of file permissions. You need *write* permissions on files you want to send to Trash. If you're not familiar with the command line, you can use utilities such as [BatChmod](http://macchampion.com/arbysoft/BatchMod) to fix your permissions.
If dupeGuru still gives you troubles after fixing your permissions, there have been some cases where using "Move Marked to..." as a workaround did the trick. So instead of sending your files to Trash, you send them to a temporary folder with the "Move Marked to..." action, and then you delete that temporary folder manually.
If you're trying to delete *iPhoto* pictures, then the reason for the failure is different. The deletion fails because dupeGuru can't communicate with iPhoto. Be aware that for the deletion to work correctly, you're not supposed to play around iPhoto while dupeGuru is working. Also, sometimes, the Applescript system doesn't seem to know where to find iPhoto to launch it. It might help in these cases to launch iPhoto *before* you send your duplicates to Trash.
If all of this fail, [contact HS support](http://www.hardcoded.net/support), we'll figure it out.
</%text> </%text>

View File

@@ -14,7 +14,7 @@ import re
from Foundation import * from Foundation import *
from AppKit import * from AppKit import *
from appscript import app, k from appscript import app, k, CommandError
from hsutil import io from hsutil import io
from hsutil.str import get_file_ext from hsutil.str import get_file_ext
@@ -66,6 +66,8 @@ class IPhoto(Photo):
def get_iphoto_database_path(): def get_iphoto_database_path():
ud = NSUserDefaults.standardUserDefaults() ud = NSUserDefaults.standardUserDefaults()
prefs = ud.persistentDomainForName_('com.apple.iApps') prefs = ud.persistentDomainForName_('com.apple.iApps')
if prefs is None:
raise directories.InvalidPathError()
if 'iPhotoRecentDatabases' not in prefs: if 'iPhotoRecentDatabases' not in prefs:
raise directories.InvalidPathError() raise directories.InvalidPathError()
plisturl = NSURL.URLWithString_(prefs['iPhotoRecentDatabases'][0]) plisturl = NSURL.URLWithString_(prefs['iPhotoRecentDatabases'][0])
@@ -96,11 +98,16 @@ def get_iphoto_pictures(plistpath):
class Directories(directories.Directories): class Directories(directories.Directories):
def __init__(self): def __init__(self):
directories.Directories.__init__(self, fileclasses=[Photo]) directories.Directories.__init__(self, fileclasses=[Photo])
self.iphoto_libpath = get_iphoto_database_path() try:
self.set_state(self.iphoto_libpath[:-1], directories.STATE_EXCLUDED) self.iphoto_libpath = get_iphoto_database_path()
self.set_state(self.iphoto_libpath[:-1], directories.STATE_EXCLUDED)
except directories.InvalidPathError:
self.iphoto_libpath = None
def _get_files(self, from_path): def _get_files(self, from_path):
if from_path == Path('iPhoto Library'): if from_path == Path('iPhoto Library'):
if self.iphoto_libpath is None:
return []
is_ref = self.get_state(from_path) == directories.STATE_REFERENCE is_ref = self.get_state(from_path) == directories.STATE_REFERENCE
photos = get_iphoto_pictures(self.iphoto_libpath) photos = get_iphoto_pictures(self.iphoto_libpath)
for photo in photos: for photo in photos:
@@ -142,12 +149,18 @@ class DupeGuruPE(app_cocoa.DupeGuru):
self.path2iphoto = {} self.path2iphoto = {}
if any(isinstance(dupe, IPhoto) for dupe in marked): if any(isinstance(dupe, IPhoto) for dupe in marked):
j = j.start_subjob([6, 4], "Probing iPhoto. Don\'t touch it during the operation!") j = j.start_subjob([6, 4], "Probing iPhoto. Don\'t touch it during the operation!")
a = app('iPhoto') try:
a.activate(timeout=0) a = app('iPhoto')
a.select(a.photo_library_album(timeout=0), timeout=0) a.activate(timeout=0)
photos = as_fetch(a.photo_library_album().photos, k.item) a.select(a.photo_library_album(timeout=0), timeout=0)
for photo in j.iter_with_progress(photos): photos = as_fetch(a.photo_library_album().photos, k.item)
self.path2iphoto[unicode(photo.image_path(timeout=0))] = photo for photo in j.iter_with_progress(photos):
try:
self.path2iphoto[unicode(photo.image_path(timeout=0))] = photo
except CommandError:
pass
except (CommandError, RuntimeError):
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.last_op_error_count = self.results.perform_on_marked(op, True)
del self.path2iphoto del self.path2iphoto
@@ -156,11 +169,15 @@ class DupeGuruPE(app_cocoa.DupeGuru):
if isinstance(dupe, IPhoto): if isinstance(dupe, IPhoto):
if unicode(dupe.path) in self.path2iphoto: if unicode(dupe.path) in self.path2iphoto:
photo = self.path2iphoto[unicode(dupe.path)] photo = self.path2iphoto[unicode(dupe.path)]
a = app('iPhoto') try:
a.remove(photo, timeout=0) a = app('iPhoto')
return True a.remove(photo, timeout=0)
return True
except (CommandError, RuntimeError):
return False
else: else:
logging.warning("Could not find photo {0} in iPhoto Library", unicode(dupe.path)) logging.warning(u"Could not find photo %s in iPhoto Library", unicode(dupe.path))
return False
else: else:
return app_cocoa.DupeGuru._do_delete_dupe(self, dupe) return app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
@@ -170,7 +187,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
def _get_file(self, str_path): def _get_file(self, str_path):
p = Path(str_path) p = Path(str_path)
if p in self.directories.iphoto_libpath[:-1]: if (self.directories.iphoto_libpath is not None) and (p in self.directories.iphoto_libpath[:-1]):
return IPhoto(p) return IPhoto(p)
return app_cocoa.DupeGuru._get_file(self, str_path) return app_cocoa.DupeGuru._get_file(self, str_path)
@@ -188,5 +205,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
if not self.selected_dupes: if not self.selected_dupes:
return None return None
ref = self.results.get_group_of_duplicate(self.selected_dupes[0]).ref ref = self.results.get_group_of_duplicate(self.selected_dupes[0]).ref
if ref is self.selected_dupes[0]: # we don't want the same pic to be displayed on both sides
return None
return ref.path return ref.path

View File

@@ -8,6 +8,7 @@
# 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
from PyQt4.QtGui import QImage from PyQt4.QtGui import QImage
import PIL.Image import PIL.Image
@@ -40,8 +41,12 @@ class File(fs.File):
def _read_info(self, field): def _read_info(self, field):
fs.File._read_info(self, field) fs.File._read_info(self, field)
if field == 'dimensions': if field == 'dimensions':
im = PIL.Image.open(unicode(self.path)) try:
self.dimensions = im.size im = PIL.Image.open(unicode(self.path))
self.dimensions = im.size
except IOError:
self.dimensions = (0, 0)
logging.warning(u"Could not read image '%s'", unicode(self.path))
def get_blocks(self, block_count_per_side): def get_blocks(self, block_count_per_side):
image = QImage(unicode(self.path)) image = QImage(unicode(self.path))
@@ -52,7 +57,7 @@ class File(fs.File):
class DupeGuru(DupeGuruBase): class DupeGuru(DupeGuruBase):
LOGO_NAME = 'logo_pe' LOGO_NAME = 'logo_pe'
NAME = 'dupeGuru Picture Edition' NAME = 'dupeGuru Picture Edition'
VERSION = '1.7.7' VERSION = '1.8.0'
DELTA_COLUMNS = frozenset([2, 5, 6]) DELTA_COLUMNS = frozenset([2, 5, 6])
def __init__(self): def __init__(self):

View File

@@ -13,10 +13,14 @@ import os.path as op
from hsutil.build import print_and_do, build_all_qt_ui from hsutil.build import print_and_do, build_all_qt_ui
from help import gen
build_all_qt_ui(op.join('qtlib', 'ui')) build_all_qt_ui(op.join('qtlib', 'ui'))
build_all_qt_ui('base') build_all_qt_ui('base')
build_all_qt_ui('.') build_all_qt_ui('.')
print_and_do("pyrcc4 base\\dg.qrc > base\\dg_rc.py") os.chdir('base')
print_and_do("pyrcc4 dg.qrc > dg_rc.py")
os.chdir('..')
def move(src, dst): def move(src, dst):
if not op.exists(src): if not op.exists(src):
@@ -39,5 +43,5 @@ move(op.join('modules', 'block', '_block.so'), op.join('.', '_block.so'))
move(op.join('modules', 'block', '_block.pyd'), op.join('.', '_block.pyd')) move(op.join('modules', 'block', '_block.pyd'), op.join('.', '_block.pyd'))
os.chdir('help') os.chdir('help')
print_and_do('python gen.py') gen.generate(windows=True)
os.chdir('..') os.chdir('..')

View File

@@ -8,14 +8,11 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "dgbase/AppDelegate.h" #import "dgbase/AppDelegate.h"
#import "ResultWindow.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"
#import "PyDupeGuru.h" #import "PyDupeGuru.h"
@interface AppDelegate : AppDelegateBase @interface AppDelegate : AppDelegateBase
{ {
IBOutlet ResultWindow *result;
DirectoryPanel *_directoryPanel; DirectoryPanel *_directoryPanel;
} }
- (IBAction)openWebsite:(id)sender; - (IBAction)openWebsite:(id)sender;

View File

@@ -11,6 +11,7 @@ http://www.hardcoded.net/licenses/hs_license
#import "cocoalib/RegistrationInterface.h" #import "cocoalib/RegistrationInterface.h"
#import "cocoalib/Utils.h" #import "cocoalib/Utils.h"
#import "cocoalib/ValueTransformers.h" #import "cocoalib/ValueTransformers.h"
#import "DetailsPanel.h"
#import "Consts.h" #import "Consts.h"
@implementation AppDelegate @implementation AppDelegate
@@ -62,26 +63,17 @@ http://www.hardcoded.net/licenses/hs_license
_directoryPanel = [[DirectoryPanel alloc] initWithParentApp:self]; _directoryPanel = [[DirectoryPanel alloc] initWithParentApp:self];
return _directoryPanel; return _directoryPanel;
} }
- (DetailsPanelBase *)detailsPanel
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
return _detailsPanel;
}
- (PyDupeGuru *)py { return (PyDupeGuru *)py; } - (PyDupeGuru *)py { return (PyDupeGuru *)py; }
//Delegate //Delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[ProgressController mainProgressController] setWorker:py];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
//Restore Columns
NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"];
NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"];
if ([columnsOrder count])
[result restoreColumnsPosition:columnsOrder widths:columnsWidth];
//Reg stuff
if ([RegistrationInterface showNagWithApp:[self py] name:APPNAME limitDescription:LIMIT_DESC])
[unlockMenuItem setTitle:@"Thanks for buying dupeGuru!"];
//Restore results
[py loadIgnoreList];
[py loadResults];
}
- (void)applicationWillBecomeActive:(NSNotification *)aNotification - (void)applicationWillBecomeActive:(NSNotification *)aNotification
{ {
if (![[result window] isVisible]) if (![[result window] isVisible])

View File

@@ -1,18 +0,0 @@
{
IBClasses = (
{
CLASS = DetailsPanel;
LANGUAGE = ObjC;
OUTLETS = {detailsTable = NSTableView; };
SUPERCLASS = NSWindowController;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = TableView;
LANGUAGE = ObjC;
OUTLETS = {py = PyApp; };
SUPERCLASS = NSTableView;
}
);
IBVersion = 1;
}

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>432 54 356 240 0 0 1024 746 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8I127</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>askForDirectory</key>
<string>id</string>
<key>changeDirectoryState</key>
<string>id</string>
<key>popupAddDirectoryMenu</key>
<string>id</string>
<key>removeSelectedDirectory</key>
<string>id</string>
<key>toggleVisible</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>DirectoryPanel</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>addButtonPopUp</key>
<string>NSPopUpButton</string>
<key>directories</key>
<string>NSOutlineView</string>
<key>removeButton</key>
<string>NSButton</string>
</dict>
<key>SUPERCLASS</key>
<string>DirectoryPanelBase</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>6</integer>
</array>
<key>IBSystem Version</key>
<string>9B18</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -1,229 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBClasses</key>
<array>
<dict>
<key>CLASS</key>
<string>NSSegmentedControl</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSControl</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>openWebsite</key>
<string>id</string>
<key>toggleDirectories</key>
<string>id</string>
<key>unlockApp</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>AppDelegate</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyDupeGuru</string>
<key>recentDirectories</key>
<string>RecentDirectories</string>
<key>result</key>
<string>ResultWindow</string>
<key>unlockMenuItem</key>
<string>NSMenuItem</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyApp</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>MatchesView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>OutlineView</string>
</dict>
<dict>
<key>CLASS</key>
<string>PyDupeGuru</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>PyApp</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>changeDelta</key>
<string>id</string>
<key>changePowerMarker</key>
<string>id</string>
<key>clearIgnoreList</key>
<string>id</string>
<key>collapseAll</key>
<string>id</string>
<key>copyMarked</key>
<string>id</string>
<key>deleteMarked</key>
<string>id</string>
<key>expandAll</key>
<string>id</string>
<key>exportToXHTML</key>
<string>id</string>
<key>filter</key>
<string>id</string>
<key>ignoreSelected</key>
<string>id</string>
<key>markAll</key>
<string>id</string>
<key>markInvert</key>
<string>id</string>
<key>markNone</key>
<string>id</string>
<key>markSelected</key>
<string>id</string>
<key>markToggle</key>
<string>id</string>
<key>moveMarked</key>
<string>id</string>
<key>openSelected</key>
<string>id</string>
<key>refresh</key>
<string>id</string>
<key>removeMarked</key>
<string>id</string>
<key>removeSelected</key>
<string>id</string>
<key>renameSelected</key>
<string>id</string>
<key>resetColumnsToDefault</key>
<string>id</string>
<key>revealSelected</key>
<string>id</string>
<key>showPreferencesPanel</key>
<string>id</string>
<key>startDuplicateScan</key>
<string>id</string>
<key>switchSelected</key>
<string>id</string>
<key>toggleColumn</key>
<string>id</string>
<key>toggleDelta</key>
<string>id</string>
<key>toggleDetailsPanel</key>
<string>id</string>
<key>togglePowerMarker</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>ResultWindow</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>actionMenu</key>
<string>NSPopUpButton</string>
<key>actionMenuView</key>
<string>NSView</string>
<key>app</key>
<string>id</string>
<key>columnsMenu</key>
<string>NSMenu</string>
<key>deltaSwitch</key>
<string>NSSegmentedControl</string>
<key>deltaSwitchView</key>
<string>NSView</string>
<key>filterField</key>
<string>NSSearchField</string>
<key>filterFieldView</key>
<string>NSView</string>
<key>matches</key>
<string>MatchesView</string>
<key>pmSwitch</key>
<string>NSSegmentedControl</string>
<key>pmSwitchView</key>
<string>NSView</string>
<key>preferencesPanel</key>
<string>NSWindow</string>
<key>py</key>
<string>PyDupeGuru</string>
<key>stats</key>
<string>NSTextField</string>
</dict>
<key>SUPERCLASS</key>
<string>NSWindowController</string>
</dict>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>checkForUpdates</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>SUUpdater</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>ACTIONS</key>
<dict>
<key>clearMenu</key>
<string>id</string>
<key>menuClick</key>
<string>id</string>
</dict>
<key>CLASS</key>
<string>RecentDirectories</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>delegate</key>
<string>id</string>
<key>menu</key>
<string>NSMenu</string>
</dict>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
<dict>
<key>CLASS</key>
<string>OutlineView</string>
<key>LANGUAGE</key>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
<key>py</key>
<string>PyApp</string>
</dict>
<key>SUPERCLASS</key>
<string>NSOutlineView</string>
</dict>
</array>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>629</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../dupeguru.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>524</integer>
</array>
<key>IBSystem Version</key>
<string>9E17</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
</plist>

View File

@@ -23,11 +23,13 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>hsft</string> <string>hsft</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2.8.2</string> <string>2.9.0</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
<string>© Hardcoded Software, 2009</string>
<key>SUFeedURL</key> <key>SUFeedURL</key>
<string>http://www.hardcoded.net/updates/dupeguru.appcast</string> <string>http://www.hardcoded.net/updates/dupeguru.appcast</string>
<key>SUPublicDSAKeyFile</key> <key>SUPublicDSAKeyFile</key>

View File

@@ -9,19 +9,13 @@ http://www.hardcoded.net/licenses/hs_license
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "cocoalib/Outline.h" #import "cocoalib/Outline.h"
#import "dgbase/ResultWindow.h" #import "dgbase/ResultWindow.h"
#import "DetailsPanel.h"
#import "DirectoryPanel.h" #import "DirectoryPanel.h"
@interface ResultWindow : ResultWindowBase @interface ResultWindow : ResultWindowBase
{ {
IBOutlet NSPopUpButton *actionMenu;
IBOutlet NSMenu *columnsMenu;
IBOutlet NSSearchField *filterField; IBOutlet NSSearchField *filterField;
IBOutlet NSWindow *preferencesPanel;
NSString *_lastAction; NSString *_lastAction;
DetailsPanel *_detailsPanel;
NSMutableArray *_resultColumns;
NSMutableIndexSet *_deltaColumns; NSMutableIndexSet *_deltaColumns;
} }
- (IBAction)clearIgnoreList:(id)sender; - (IBAction)clearIgnoreList:(id)sender;
@@ -39,13 +33,6 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)renameSelected:(id)sender; - (IBAction)renameSelected:(id)sender;
- (IBAction)resetColumnsToDefault:(id)sender; - (IBAction)resetColumnsToDefault:(id)sender;
- (IBAction)revealSelected:(id)sender; - (IBAction)revealSelected:(id)sender;
- (IBAction)showPreferencesPanel:(id)sender;
- (IBAction)startDuplicateScan:(id)sender; - (IBAction)startDuplicateScan:(id)sender;
- (IBAction)toggleColumn:(id)sender;
- (IBAction)toggleDelta:(id)sender; - (IBAction)toggleDelta:(id)sender;
- (IBAction)toggleDetailsPanel:(id)sender;
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn;
- (void)initResultColumns;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
@end @end

View File

@@ -18,7 +18,6 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib - (void)awakeFromNib
{ {
[super awakeFromNib]; [super awakeFromNib];
_detailsPanel = nil;
_displayDelta = NO; _displayDelta = NO;
_powerMode = NO; _powerMode = NO;
_deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)] retain]; _deltaColumns = [[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,4)] retain];
@@ -28,23 +27,8 @@ http://www.hardcoded.net/licenses/hs_license
[py setDisplayDeltaValues:b2n(_displayDelta)]; [py setDisplayDeltaValues:b2n(_displayDelta)];
[matches setTarget:self]; [matches setTarget:self];
[matches setDoubleAction:@selector(openSelected:)]; [matches setDoubleAction:@selector(openSelected:)];
[[actionMenu itemAtIndex:0] setImage:[NSImage imageNamed: @"gear"]];
[self initResultColumns];
[self refreshStats]; [self refreshStats];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resultsMarkingChanged:) name:ResultsMarkingChangedNotification object:nil];
NSToolbar *t = [[[NSToolbar alloc] initWithIdentifier:@"ResultWindowToolbar"] autorelease];
[t setAllowsUserCustomization:YES];
[t setAutosavesConfiguration:YES];
[t setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[t setDelegate:self];
[[self window] setToolbar:t];
}
/* Override */
- (NSString *)logoImageName
{
return @"dgse_logo_32";
} }
/* Actions */ /* Actions */
@@ -174,11 +158,6 @@ http://www.hardcoded.net/licenses/hs_license
[py revealSelected]; [py revealSelected];
} }
- (IBAction)showPreferencesPanel:(id)sender
{
[preferencesPanel makeKeyAndOrderFront:sender];
}
- (IBAction)startDuplicateScan:(id)sender - (IBAction)startDuplicateScan:(id)sender
{ {
if ([matches numberOfRows] > 0) if ([matches numberOfRows] > 0)
@@ -211,26 +190,6 @@ http://www.hardcoded.net/licenses/hs_license
} }
- (IBAction)toggleColumn:(id)sender
{
NSMenuItem *mi = sender;
NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]];
NSTableColumn *col = [matches tableColumnWithIdentifier:colId];
if (col == nil)
{
//Add Column
col = [_resultColumns objectAtIndex:[mi tag]];
[matches addTableColumn:col];
[mi setState:NSOnState];
}
else
{
//Remove column
[matches removeTableColumn:col];
[mi setState:NSOffState];
}
}
- (IBAction)toggleDelta:(id)sender - (IBAction)toggleDelta:(id)sender
{ {
if ([deltaSwitch selectedSegment] == 1) if ([deltaSwitch selectedSegment] == 1)
@@ -240,74 +199,24 @@ http://www.hardcoded.net/licenses/hs_license
[self changeDelta:sender]; [self changeDelta:sender];
} }
- (IBAction)toggleDetailsPanel:(id)sender
{
if (!_detailsPanel)
_detailsPanel = [[DetailsPanel alloc] initWithPy:py];
if ([[_detailsPanel window] isVisible])
[[_detailsPanel window] close];
else
[[_detailsPanel window] orderFront:nil];
}
/* Public */ /* Public */
- (NSTableColumn *)getColumnForIdentifier:(int)aIdentifier title:(NSString *)aTitle width:(int)aWidth refCol:(NSTableColumn *)aColumn
{
NSNumber *n = [NSNumber numberWithInt:aIdentifier];
NSTableColumn *col = [[NSTableColumn alloc] initWithIdentifier:[n stringValue]];
[col setWidth:aWidth];
[col setEditable:NO];
[[col dataCell] setFont:[[aColumn dataCell] font]];
[[col headerCell] setStringValue:aTitle];
[col setResizingMask:NSTableColumnUserResizingMask];
[col setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:[n stringValue] ascending:YES]];
return col;
}
- (void)initResultColumns - (void)initResultColumns
{ {
NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"];
_resultColumns = [[NSMutableArray alloc] init]; _resultColumns = [[NSMutableArray alloc] init];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"1"]]; // Directory [_resultColumns addObject:[self getColumnForIdentifier:1 title:@"Directory" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"2"]]; // Size NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:@"Size (KB)" width:63 refCol:refCol];
[[sizeCol dataCell] setAlignment:NSRightTextAlignment];
[_resultColumns addObject:sizeCol];
[_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:3 title:@"Kind" width:40 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Creation" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:4 title:@"Creation" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Modification" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:5 title:@"Modification" width:120 refCol:refCol]];
[_resultColumns addObject:[matches tableColumnWithIdentifier:@"6"]]; // Match % [_resultColumns addObject:[self getColumnForIdentifier:6 title:@"Match %" width:60 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Words Used" width:120 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:7 title:@"Words Used" width:120 refCol:refCol]];
[_resultColumns addObject:[self getColumnForIdentifier:8 title:@"Dupe Count" width:80 refCol:refCol]]; [_resultColumns addObject:[self getColumnForIdentifier:8 title:@"Dupe Count" width:80 refCol:refCol]];
} }
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth
{
NSTableColumn *col;
NSString *colId;
NSNumber *width;
NSMenuItem *mi;
//Remove all columns
NSEnumerator *e = [[columnsMenu itemArray] objectEnumerator];
while (mi = [e nextObject])
{
if ([mi state] == NSOnState)
[self toggleColumn:mi];
}
//Add columns and set widths
e = [aColumnsOrder objectEnumerator];
while (colId = [e nextObject])
{
if (![colId isEqual:@"mark"])
{
col = [_resultColumns objectAtIndex:[colId intValue]];
width = [aColumnsWidth objectForKey:[col identifier]];
mi = [columnsMenu itemWithTag:[colId intValue]];
if (width)
[col setWidth:[width floatValue]];
[self toggleColumn:mi];
}
}
}
/* Delegate */ /* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{ {

View File

@@ -7,32 +7,30 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_help */; }; CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_help */; };
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; }; CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; }; CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; }; CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */ = {isa = PBXBuildFile; fileRef = CE3AA46509DB207900DB3A21 /* Directories.nib */; }; 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 */; };
CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; }; CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; };
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 */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; }; CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CECA899909DB12CA00A3D774 /* Details.nib in Resources */ = {isa = PBXBuildFile; fileRef = CECA899709DB12CA00A3D774 /* Details.nib */; }; CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; };
CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; }; CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; };
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; }; CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; };
CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; }; CEDD92DA0FDD01640031C7B7 /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D70FDD01640031C7B7 /* BRSingleLineFormatter.m */; };
CEDD92DB0FDD01640031C7B7 /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D90FDD01640031C7B7 /* NSCharacterSet_Extensions.m */; }; CEDD92DB0FDD01640031C7B7 /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDD92D90FDD01640031C7B7 /* NSCharacterSet_Extensions.m */; };
CEE7EA130FE675C80004E467 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE7EA120FE675C80004E467 /* DetailsPanel.m */; }; CEE7EA130FE675C80004E467 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE7EA120FE675C80004E467 /* DetailsPanel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; }; CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEF7823809C8AA0200EF38FF /* gear.png in Resources */ = {isa = PBXBuildFile; fileRef = CEF7823709C8AA0200EF38FF /* gear.png */; }; CEEFC0F810945D9F001F3A39 /* DirectoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */; };
CEEFC0FB10945E37001F3A39 /* DetailsPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; }; CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; }; CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; }; CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
CEFC295E09C8A0B000D9F998 /* dgse_logo_32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295D09C8A0B000D9F998 /* dgse_logo_32.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 */; }; CEFC7FA00FC9517500CD5728 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFC7F8F0FC9517500CD5728 /* Outline.m */; };
@@ -66,11 +64,9 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
@@ -81,13 +77,13 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; }; CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; }; CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; }; CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dg_cocoa.plugin; path = py/dist/dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE3AA46609DB207900DB3A21 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Directories.nib; sourceTree = "<group>"; }; CE3A46F9109B212E002ABFD5 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = dgbase/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>"; };
CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; }; CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; };
CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; }; CE68EE6609ABC48000971085 /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = SOURCE_ROOT; };
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; }; CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = dgbase/dsa_pub.pem; sourceTree = "<group>"; };
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>"; };
CECA899809DB12CA00A3D774 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Details.nib; sourceTree = "<group>"; }; CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; 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>"; }; CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = "<group>"; };
CEDD92D60FDD01640031C7B7 /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; }; CEDD92D60FDD01640031C7B7 /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
@@ -97,11 +93,11 @@
CEE7EA110FE675C80004E467 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = dgbase/DetailsPanel.h; sourceTree = SOURCE_ROOT; }; CEE7EA110FE675C80004E467 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = dgbase/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
CEE7EA120FE675C80004E467 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = dgbase/DetailsPanel.m; sourceTree = SOURCE_ROOT; }; CEE7EA120FE675C80004E467 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = dgbase/DetailsPanel.m; sourceTree = SOURCE_ROOT; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; }; CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEF7823709C8AA0200EF38FF /* gear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gear.png; path = images/gear.png; sourceTree = "<group>"; }; CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DirectoryPanel.xib; path = dgbase/xib/DirectoryPanel.xib; sourceTree = "<group>"; };
CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = DetailsPanel.xib; path = dgbase/xib/DetailsPanel.xib; sourceTree = "<group>"; };
CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; }; CEFC294509C89E3D00D9F998 /* folder32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = folder32.png; path = images/folder32.png; sourceTree = SOURCE_ROOT; };
CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; }; CEFC295309C89FF200D9F998 /* details32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = details32.png; path = images/details32.png; sourceTree = SOURCE_ROOT; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; }; CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = images/preferences32.png; sourceTree = SOURCE_ROOT; };
CEFC295D09C8A0B000D9F998 /* dgse_logo_32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dgse_logo_32.png; path = images/dgse_logo_32.png; sourceTree = "<group>"; };
CEFC7F8A0FC9517500CD5728 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; }; CEFC7F8A0FC9517500CD5728 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
CEFC7F8B0FC9517500CD5728 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; }; 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; };
@@ -213,13 +209,10 @@
CE073F5409CAE1A3005C1D2F /* dupeguru_help */, CE073F5409CAE1A3005C1D2F /* dupeguru_help */,
CE381CF509915304003581CE /* dg_cocoa.plugin */, CE381CF509915304003581CE /* dg_cocoa.plugin */,
CEFC294309C89E0000D9F998 /* images */, CEFC294309C89E0000D9F998 /* images */,
CEEFC0CA10943849001F3A39 /* xib */,
CEEB135109C837A2004D2330 /* dupeguru.icns */, CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */, 8D1107310486CEB800E47090 /* Info.plist */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */, CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */,
CECA899709DB12CA00A3D774 /* Details.nib */,
CE3AA46509DB207900DB3A21 /* Directories.nib */,
29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
); );
name = Resources; name = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -245,11 +238,20 @@
path = cocoalib/brsinglelineformatter; path = cocoalib/brsinglelineformatter;
sourceTree = SOURCE_ROOT; sourceTree = SOURCE_ROOT;
}; };
CEEFC0CA10943849001F3A39 /* xib */ = {
isa = PBXGroup;
children = (
CE3A46F9109B212E002ABFD5 /* MainMenu.xib */,
CEAC6810109B0B7E00B43C85 /* Preferences.xib */,
CEEFC0F710945D9F001F3A39 /* DirectoryPanel.xib */,
CEEFC0FA10945E37001F3A39 /* DetailsPanel.xib */,
);
name = xib;
sourceTree = "<group>";
};
CEFC294309C89E0000D9F998 /* images */ = { CEFC294309C89E0000D9F998 /* images */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CEF7823709C8AA0200EF38FF /* gear.png */,
CEFC295D09C8A0B000D9F998 /* dgse_logo_32.png */,
CEFC295309C89FF200D9F998 /* details32.png */, CEFC295309C89FF200D9F998 /* details32.png */,
CEFC295409C89FF200D9F998 /* preferences32.png */, CEFC295409C89FF200D9F998 /* preferences32.png */,
CEFC294509C89E3D00D9F998 /* folder32.png */, CEFC294509C89E3D00D9F998 /* folder32.png */,
@@ -352,22 +354,20 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */, CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */,
CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */, CE073F6309CAE1A3005C1D2F /* dupeguru_help in Resources */,
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */, CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */,
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */, CEFC294609C89E3D00D9F998 /* folder32.png in Resources */,
CEFC295509C89FF200D9F998 /* details32.png in Resources */, CEFC295509C89FF200D9F998 /* details32.png in Resources */,
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */, CEFC295609C89FF200D9F998 /* preferences32.png in Resources */,
CEFC295E09C8A0B000D9F998 /* dgse_logo_32.png in Resources */,
CEF7823809C8AA0200EF38FF /* gear.png in Resources */,
CECA899909DB12CA00A3D774 /* Details.nib in Resources */,
CE3AA46709DB207900DB3A21 /* Directories.nib in Resources */,
CEFC7FAD0FC9518A00CD5728 /* ErrorReportWindow.xib in Resources */, CEFC7FAD0FC9518A00CD5728 /* ErrorReportWindow.xib in Resources */,
CEFC7FAE0FC9518A00CD5728 /* progress.nib in Resources */, CEFC7FAE0FC9518A00CD5728 /* progress.nib in Resources */,
CEFC7FAF0FC9518A00CD5728 /* registration.nib in Resources */, CEFC7FAF0FC9518A00CD5728 /* registration.nib in Resources */,
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */, CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */,
CEEFC0F810945D9F001F3A39 /* DirectoryPanel.xib in Resources */,
CEEFC0FB10945E37001F3A39 /* DetailsPanel.xib in Resources */,
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */,
CE3A46FA109B212E002ABFD5 /* MainMenu.xib in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -404,38 +404,6 @@
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C165DFE840E0CC02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
isa = PBXVariantGroup;
children = (
29B97319FDCFA39411CA2CEA /* English */,
);
name = MainMenu.nib;
sourceTree = SOURCE_ROOT;
};
CE3AA46509DB207900DB3A21 /* Directories.nib */ = {
isa = PBXVariantGroup;
children = (
CE3AA46609DB207900DB3A21 /* English */,
);
name = Directories.nib;
sourceTree = "<group>";
};
CECA899709DB12CA00A3D774 /* Details.nib */ = {
isa = PBXVariantGroup;
children = (
CECA899809DB12CA00A3D774 /* English */,
);
name = Details.nib;
sourceTree = "<group>";
};
CEFC7FA70FC9518A00CD5728 /* ErrorReportWindow.xib */ = { CEFC7FA70FC9518A00CD5728 /* ErrorReportWindow.xib */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
children = ( children = (
@@ -463,28 +431,6 @@
/* End PBXVariantGroup section */ /* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(FRAMEWORK_SEARCH_PATHS)",
"$(SRCROOT)/../../../cocoalib/build/Release",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
);
FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../base/cocoa/build/Release\"";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
PRODUCT_NAME = dupeGuru;
WRAPPER_EXTENSION = app;
ZERO_LINK = YES;
};
name = Debug;
};
C01FCF4C08A954540054247B /* Release */ = { C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
@@ -507,31 +453,16 @@
}; };
name = Release; name = Release;
}; };
C01FCF4F08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4;
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
};
name = Debug;
};
C01FCF5008A954540054247B /* Release */ = { C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386";
FRAMEWORK_SEARCH_PATHS = "@executable_path/../Frameworks";
GCC_C_LANGUAGE_STANDARD = c99; GCC_C_LANGUAGE_STANDARD = c99;
GCC_VERSION = 4.0;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.4; MACOSX_DEPLOYMENT_TARGET = 10.5;
PREBINDING = NO; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
}; };
name = Release; name = Release;
}; };
@@ -541,7 +472,6 @@
C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = { C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4B08A954540054247B /* Debug */,
C01FCF4C08A954540054247B /* Release */, C01FCF4C08A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
@@ -550,7 +480,6 @@
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = { C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dupeguru" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
C01FCF5008A954540054247B /* Release */, C01FCF5008A954540054247B /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;

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