Initial commit.

--HG--
extra : convert_revision : svn%3Ac306627e-7827-47d3-bdf0-9a457c9553a1/trunk%402
This commit is contained in:
hsoft 2009-06-01 09:55:11 +00:00
parent 4f197ffd5a
commit e9a97afdf8
354 changed files with 38083 additions and 0 deletions

17
base/cocoa/AppDelegate.h Normal file
View File

@ -0,0 +1,17 @@
#import <Cocoa/Cocoa.h>
#import "RecentDirectories.h"
#import "PyDupeGuru.h"
@interface AppDelegateBase : NSObject
{
IBOutlet PyDupeGuruBase *py;
IBOutlet RecentDirectories *recentDirectories;
IBOutlet NSMenuItem *unlockMenuItem;
NSString *_appName;
}
- (IBAction)unlockApp:(id)sender;
- (PyDupeGuruBase *)py;
- (RecentDirectories *)recentDirectories;
@end

30
base/cocoa/AppDelegate.m Normal file
View File

@ -0,0 +1,30 @@
#import "AppDelegate.h"
#import "ProgressController.h"
#import "RegistrationInterface.h"
#import "Utils.h"
#import "Consts.h"
@implementation AppDelegateBase
- (id)init
{
self = [super init];
_appName = @"";
return self;
}
- (IBAction)unlockApp:(id)sender
{
if ([[self py] isRegistered])
return;
RegistrationInterface *ri = [[RegistrationInterface alloc] initWithApp:[self py] name:_appName limitDescription:LIMIT_DESC];
if ([ri enterCode] == NSOKButton)
{
NSString *menuTitle = [NSString stringWithFormat:@"Thanks for buying %@",_appName];
[unlockMenuItem setTitle:menuTitle];
}
[ri release];
}
- (PyDupeGuruBase *)py { return py; }
- (RecentDirectories *)recentDirectories { return recentDirectories; }
@end

17
base/cocoa/Consts.h Normal file
View File

@ -0,0 +1,17 @@
#import <Cocoa/Cocoa.h>
#define DuplicateSelectionChangedNotification @"DuplicateSelectionChangedNotification"
#define ResultsChangedNotification @"ResultsChangedNotification"
#define ResultsMarkingChangedNotification @"ResultsMarkingChangedNotification"
#define RegistrationRequired @"RegistrationRequired"
#define JobStarted @"JobStarted"
#define JobInProgress @"JobInProgress"
#define jobLoad @"job_load"
#define jobScan @"job_scan"
#define jobCopy @"job_copy"
#define jobMove @"job_move"
#define jobDelete @"job_delete"
#define DEMO_MAX_ACTION_COUNT 10
#define LIMIT_DESC @"In the demo version, only 10 duplicates per session can be sent to Trash, moved or copied."

View File

@ -0,0 +1,25 @@
#import <Cocoa/Cocoa.h>
#import "RecentDirectories.h"
#import "Outline.h"
#import "PyDupeGuru.h"
@interface DirectoryPanelBase : NSWindowController
{
IBOutlet NSPopUpButton *addButtonPopUp;
IBOutlet OutlineView *directories;
IBOutlet NSButton *removeButton;
PyDupeGuruBase *_py;
RecentDirectories *_recentDirectories;
}
- (id)initWithParentApp:(id)aParentApp;
- (IBAction)askForDirectory:(id)sender;
- (IBAction)changeDirectoryState:(id)sender;
- (IBAction)popupAddDirectoryMenu:(id)sender;
- (IBAction)removeSelectedDirectory:(id)sender;
- (IBAction)toggleVisible:(id)sender;
- (void)addDirectory:(NSString *)directory;
- (void)refreshRemoveButtonText;
@end

178
base/cocoa/DirectoryPanel.m Normal file
View File

@ -0,0 +1,178 @@
#import "DirectoryPanel.h"
#import "Dialogs.h"
#import "Utils.h"
#import "AppDelegate.h"
@implementation DirectoryPanelBase
- (id)initWithParentApp:(id)aParentApp
{
self = [super initWithWindowNibName:@"Directories"];
[self window];
AppDelegateBase *app = aParentApp;
_py = [app py];
_recentDirectories = [app recentDirectories];
[directories setPy:_py];
NSPopUpButtonCell *cell = [[directories tableColumnWithIdentifier:@"1"] dataCell];
[cell addItemWithTitle:@"Normal"];
[cell addItemWithTitle:@"Reference"];
[cell addItemWithTitle:@"Excluded"];
for (int i=0;i<[[cell itemArray] count];i++)
{
NSMenuItem *mi = [[cell itemArray] objectAtIndex:i];
[mi setTarget:self];
[mi setAction:@selector(changeDirectoryState:)];
[mi setTag:i];
}
[self refreshRemoveButtonText];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(directorySelectionChanged:) name:NSOutlineViewSelectionDidChangeNotification object:directories];
return self;
}
/* Actions */
- (IBAction)askForDirectory:(id)sender
{
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:YES];
[op setCanChooseDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setTitle:@"Select a directory to add to the scanning list"];
[op setDelegate:self];
if ([op runModalForTypes:nil] == NSOKButton)
{
NSString *directory = [[op filenames] objectAtIndex:0];
[self addDirectory:directory];
}
}
- (IBAction)changeDirectoryState:(id)sender
{
OVNode *node = [directories itemAtRow:[directories clickedRow]];
[_py setDirectory:p2a([node indexPath]) state:i2n([sender tag])];
[node resetAllBuffers];
[directories display];
}
- (IBAction)popupAddDirectoryMenu:(id)sender
{
if ([[_recentDirectories directories] count] == 0)
{
[self askForDirectory:sender];
return;
}
NSMenu *m = [addButtonPopUp menu];
while ([m numberOfItems] > 0)
[m removeItemAtIndex:0];
NSMenuItem *mi = [m addItemWithTitle:@"Add New Directory..." action:@selector(askForDirectory:) keyEquivalent:@""];
[mi setTarget:self];
[m addItem:[NSMenuItem separatorItem]];
[_recentDirectories fillMenu:m];
[addButtonPopUp selectItem:nil];
[[addButtonPopUp cell] performClickWithFrame:[sender frame] inView:[sender superview]];
}
- (IBAction)removeSelectedDirectory:(id)sender
{
[[self window] makeKeyAndOrderFront:nil];
if ([directories selectedRow] < 0)
return;
OVNode *node = [directories itemAtRow:[directories selectedRow]];
if ([node level] == 1)
{
[_py removeDirectory:i2n([node index])];
[directories reloadData];
}
else
{
int state = n2i([[node buffer] objectAtIndex:1]);
int newState = state == 2 ? 0 : 2; // If excluded, put it back
[_py setDirectory:p2a([node indexPath]) state:i2n(newState)];
[node resetAllBuffers];
[directories display];
}
[self refreshRemoveButtonText];
}
- (IBAction)toggleVisible:(id)sender
{
if ([[self window] isVisible])
[[self window] close];
else
[[self window] makeKeyAndOrderFront:nil];
}
/* Public */
- (void)addDirectory:(NSString *)directory
{
int r = [[_py addDirectory:directory] intValue];
if (r)
{
NSString *m;
switch (r)
{
case 1:
{
m = @"This directory already is in the list.";
break;
}
case 2:
{
m = @"This directory does not exist.";
break;
}
}
[Dialogs showMessage:m];
}
[directories reloadData];
[_recentDirectories addDirectory:directory];
[[self window] makeKeyAndOrderFront:nil];
}
- (void)refreshRemoveButtonText
{
if ([directories selectedRow] < 0)
{
[removeButton setEnabled:NO];
return;
}
[removeButton setEnabled:YES];
OVNode *node = [directories itemAtRow:[directories selectedRow]];
int state = n2i([[node buffer] objectAtIndex:1]);
NSString *buttonText = state == 2 ? @"Put Back" : @"Remove";
[removeButton setTitle:buttonText];
}
/* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
OVNode *node = item;
int state = n2i([[node buffer] objectAtIndex:1]);
if ([cell isKindOfClass:[NSTextFieldCell class]])
{
NSTextFieldCell *textCell = cell;
if (state == 1)
[textCell setTextColor:[NSColor blueColor]];
else if (state == 2)
[textCell setTextColor:[NSColor redColor]];
else
[textCell setTextColor:[NSColor blackColor]];
}
}
- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)path
{
BOOL isdir;
[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isdir];
return isdir;
}
/* Notifications */
- (void)directorySelectionChanged:(NSNotification *)aNotification
{
[self refreshRemoveButtonText];
}
@end

Binary file not shown.

26
base/cocoa/Info.plist Normal file
View File

@ -0,0 +1,26 @@
<?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>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.yourcocoaframework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

56
base/cocoa/PyDupeGuru.h Normal file
View File

@ -0,0 +1,56 @@
#import <Cocoa/Cocoa.h>
#import "PyApp.h"
@interface PyDupeGuruBase : PyApp
//Actions
- (NSNumber *)addDirectory:(NSString *)name;
- (void)removeDirectory:(NSNumber *)index;
- (void)setDirectory:(NSArray *)indexPath state:(NSNumber *)state;
- (void)loadResults;
- (void)saveResults;
- (void)loadIgnoreList;
- (void)saveIgnoreList;
- (void)clearIgnoreList;
- (void)purgeIgnoreList;
- (NSString *)exportToXHTMLwithColumns:(NSArray *)aColIds xslt:(NSString *)xsltPath css:(NSString *)cssPath;
- (NSNumber *)doScan;
- (void)selectPowerMarkerNodePaths:(NSArray *)aIndexPaths;
- (void)selectResultNodePaths:(NSArray *)aIndexPaths;
- (void)toggleSelectedMark;
- (void)markAll;
- (void)markInvert;
- (void)markNone;
- (void)addSelectedToIgnoreList;
- (void)refreshDetailsWithSelected;
- (void)removeSelected;
- (void)openSelected;
- (NSNumber *)renameSelected:(NSString *)aNewName;
- (void)revealSelected;
- (void)makeSelectedReference;
- (void)applyFilter:(NSString *)filter;
- (void)sortGroupsBy:(NSNumber *)aIdentifier ascending:(NSNumber *)aAscending;
- (void)sortDupesBy:(NSNumber *)aIdentifier ascending:(NSNumber *)aAscending;
- (void)copyOrMove:(NSNumber *)aCopy markedTo:(NSString *)destination recreatePath:(NSNumber *)aRecreateType;
- (void)deleteMarked;
- (void)removeMarked;
//Data
- (NSNumber *)getIgnoreListCount;
- (NSNumber *)getMarkCount;
- (NSString *)getStatLine;
- (NSNumber *)getOperationalErrorCount;
//Scanning options
- (void)setMinMatchPercentage:(NSNumber *)percentage;
- (void)setMixFileKind:(NSNumber *)mix_file_kind;
- (void)setDisplayDeltaValues:(NSNumber *)display_delta_values;
- (void)setEscapeFilterRegexp:(NSNumber *)escape_filter_regexp;
- (void)setRemoveEmptyFolders:(NSNumber *)remove_empty_folders;
- (void)setSizeThreshold:(int)size_threshold;
@end

34
base/cocoa/ResultWindow.h Normal file
View File

@ -0,0 +1,34 @@
#import <Cocoa/Cocoa.h>
#import "Outline.h"
#import "DirectoryPanel.h"
#import "PyDupeGuru.h"
@interface MatchesView : OutlineView
- (void)keyDown:(NSEvent *)theEvent;
@end
@interface ResultWindowBase : NSWindowController
{
@protected
IBOutlet PyDupeGuruBase *py;
IBOutlet id app;
IBOutlet NSView *actionMenuView;
IBOutlet NSSegmentedControl *deltaSwitch;
IBOutlet NSView *deltaSwitchView;
IBOutlet NSView *filterFieldView;
IBOutlet MatchesView *matches;
IBOutlet NSView *pmSwitchView;
BOOL _powerMode;
BOOL _displayDelta;
}
- (NSString *)logoImageName;
/* Actions */
- (IBAction)changeDelta:(id)sender;
- (IBAction)copyMarked:(id)sender;
- (IBAction)deleteMarked:(id)sender;
- (IBAction)expandAll:(id)sender;
- (IBAction)moveMarked:(id)sender;
/* Notifications */
- (void)jobCompleted:(NSNotification *)aNotification;
@end

316
base/cocoa/ResultWindow.m Normal file
View File

@ -0,0 +1,316 @@
#import "ResultWindow.h"
#import "Dialogs.h"
#import "ProgressController.h"
#import "Utils.h"
#import "RegistrationInterface.h"
#import "AppDelegate.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
- (void)keyDown:(NSEvent *)theEvent
{
unichar key = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
// get flags and strip the lower 16 (device dependant) bits
unsigned int flags = ( [theEvent modifierFlags] & 0x00FF );
if (((key == NSDeleteFunctionKey) || (key == NSDeleteCharacter)) && (flags == 0))
[self sendAction:@selector(removeSelected:) to:[self delegate]];
else
if ((key == 0x20) && (flags == 0)) // Space
[self sendAction:@selector(markSelected:) to:[self delegate]];
else
[super keyDown:theEvent];
}
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if (![[tableColumn identifier] isEqual:@"0"])
return; //We only want to cover renames.
OVNode *node = item;
NSString *oldName = [[node buffer] objectAtIndex:0];
NSString *newName = object;
if (![newName isEqual:oldName])
{
BOOL renamed = n2b([(PyDupeGuruBase *)py renameSelected:newName]);
if (renamed)
[[NSNotificationCenter defaultCenter] postNotificationName:ResultsChangedNotification object:self];
else
[Dialogs showMessage:[NSString stringWithFormat:@"The name '%@' already exists.",newName]];
}
}
@end
@implementation ResultWindowBase
- (void)awakeFromNib
{
[self window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registrationRequired:) name:RegistrationRequired object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobStarted:) name:JobStarted object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobInProgress:) name:JobInProgress object:nil];
}
/* Virtual */
- (NSString *)logoImageName
{
return @"dg_logo32";
}
/* Actions */
- (IBAction)changeDelta:(id)sender
{
_displayDelta = [deltaSwitch selectedSegment] == 1;
[py setDisplayDeltaValues:b2n(_displayDelta)];
[matches reloadData];
[self expandAll:nil];
}
- (IBAction)copyMarked:(id)sender
{
int mark_count = [[py getMarkCount] intValue];
if (!mark_count)
return;
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:NO];
[op setCanChooseDirectories:YES];
[op setCanCreateDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setTitle:@"Select a directory to copy marked files to"];
if ([op runModalForTypes:nil] == NSOKButton)
{
NSString *directory = [[op filenames] objectAtIndex:0];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py copyOrMove:b2n(YES) markedTo:directory recreatePath:[ud objectForKey:@"recreatePathType"]];
}
}
- (IBAction)deleteMarked:(id)sender
{
int mark_count = [[py getMarkCount] intValue];
if (!mark_count)
return;
if ([Dialogs askYesNo:[NSString stringWithFormat:@"You are about to send %d files to Trash. Continue?",mark_count]] == NSAlertSecondButtonReturn) // NO
return;
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setRemoveEmptyFolders:[ud objectForKey:@"removeEmptyFolders"]];
[py deleteMarked];
}
- (IBAction)expandAll:(id)sender
{
for (int i=0;i < [matches numberOfRows];i++)
[matches expandItem:[matches itemAtRow:i]];
}
- (IBAction)moveMarked:(id)sender
{
int mark_count = [[py getMarkCount] intValue];
if (!mark_count)
return;
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:NO];
[op setCanChooseDirectories:YES];
[op setCanCreateDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setTitle:@"Select a directory to move marked files to"];
if ([op runModalForTypes:nil] == NSOKButton)
{
NSString *directory = [[op filenames] objectAtIndex:0];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setRemoveEmptyFolders:[ud objectForKey:@"removeEmptyFolders"]];
[py copyOrMove:b2n(NO) markedTo:directory recreatePath:[ud objectForKey:@"recreatePathType"]];
}
}
/* Delegate */
- (void)outlineView:(NSOutlineView *)outlineView didClickTableColumn:(NSTableColumn *)tableColumn
{
if ([[outlineView sortDescriptors] count] < 1)
return;
NSSortDescriptor *sd = [[outlineView sortDescriptors] objectAtIndex:0];
if (_powerMode)
[py sortDupesBy:i2n([[sd key] intValue]) ascending:b2n([sd ascending])];
else
[py sortGroupsBy:i2n([[sd key] intValue]) ascending:b2n([sd ascending])];
[matches reloadData];
[self expandAll:nil];
}
/* Notifications */
- (void)windowWillClose:(NSNotification *)aNotification
{
[NSApp hide:NSApp];
}
- (void)jobCompleted:(NSNotification *)aNotification
{
[[NSNotificationCenter defaultCenter] postNotificationName:ResultsChangedNotification object:self];
int r = n2i([py getOperationalErrorCount]);
id lastAction = [[ProgressController mainProgressController] jobId];
if ([lastAction isEqualTo:jobCopy])
{
if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be copied.",r]];
else
[Dialogs showMessage:@"All marked files were copied sucessfully."];
}
if ([lastAction isEqualTo:jobMove])
{
if (r > 0)
[Dialogs showMessage:[NSString stringWithFormat:@"%d file(s) couldn't be moved. They were kept in the results, and still are marked.",r]];
else
[Dialogs showMessage:@"All marked files were moved sucessfully."];
}
if ([lastAction isEqualTo:jobDelete])
{
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]];
else
[Dialogs showMessage:@"All marked files were sucessfully sent to Trash."];
}
// Re-activate toolbar items right after the progress bar stops showing instead of waiting until
// a mouse-over is performed
[[[self window] toolbar] validateVisibleItems];
}
- (void)jobInProgress:(NSNotification *)aNotification
{
[Dialogs showMessage:@"A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."];
}
- (void)jobStarted:(NSNotification *)aNotification
{
NSDictionary *ui = [aNotification userInfo];
NSString *desc = [ui valueForKey:@"desc"];
[[ProgressController mainProgressController] setJobDesc:desc];
NSString *jobid = [ui valueForKey:@"jobid"];
// NSLog(jobid);
[[ProgressController mainProgressController] setJobId:jobid];
[[ProgressController mainProgressController] showSheetForParent:[self window]];
}
- (void)registrationRequired:(NSNotification *)aNotification
{
NSString *msg = @"This is a demo version, which only allows you 10 delete/copy/move actions per session. You cannot continue.";
[Dialogs showMessage:msg];
}
/* 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
{
return ![[ProgressController mainProgressController] isShown];
}
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
return ![[ProgressController mainProgressController] isShown];
}
@end

View File

@ -0,0 +1,408 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 44;
objects = {
/* Begin PBXBuildFile section */
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
CE62CA730CFAF80D0001B6E0 /* ResultWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CE62CA710CFAF80D0001B6E0 /* ResultWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE62CA740CFAF80D0001B6E0 /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE62CA720CFAF80D0001B6E0 /* ResultWindow.m */; };
CE70A0FC0CF8C2560048C314 /* PyDupeGuru.h in Headers */ = {isa = PBXBuildFile; fileRef = CE70A0FB0CF8C2560048C314 /* PyDupeGuru.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE7D77050CF8987800BA287E /* Consts.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7D77030CF8987800BA287E /* Consts.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE80DA190FC191320086DCA6 /* RecentDirectories.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA170FC191320086DCA6 /* RecentDirectories.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA1A0FC191320086DCA6 /* RecentDirectories.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA180FC191320086DCA6 /* RecentDirectories.m */; };
CE80DA2E0FC191980086DCA6 /* Dialogs.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA250FC191980086DCA6 /* Dialogs.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA2F0FC191980086DCA6 /* Dialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA260FC191980086DCA6 /* Dialogs.m */; };
CE80DA300FC191980086DCA6 /* ProgressController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA270FC191980086DCA6 /* ProgressController.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA310FC191980086DCA6 /* ProgressController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA280FC191980086DCA6 /* ProgressController.m */; };
CE80DA320FC191980086DCA6 /* PyApp.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA290FC191980086DCA6 /* PyApp.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA330FC191980086DCA6 /* RegistrationInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA2A0FC191980086DCA6 /* RegistrationInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA340FC191980086DCA6 /* RegistrationInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA2B0FC191980086DCA6 /* RegistrationInterface.m */; };
CE80DA350FC191980086DCA6 /* Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA2C0FC191980086DCA6 /* Utils.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA360FC191980086DCA6 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA2D0FC191980086DCA6 /* Utils.m */; };
CE80DA3B0FC191C40086DCA6 /* Outline.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA370FC191C40086DCA6 /* Outline.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA3C0FC191C40086DCA6 /* Outline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA380FC191C40086DCA6 /* Outline.m */; };
CE80DA3D0FC191C40086DCA6 /* Table.h in Headers */ = {isa = PBXBuildFile; fileRef = CE80DA390FC191C40086DCA6 /* Table.h */; settings = {ATTRIBUTES = (Private, ); }; };
CE80DA3E0FC191C40086DCA6 /* Table.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DA3A0FC191C40086DCA6 /* Table.m */; };
CE80DB6D0FC194560086DCA6 /* progress.nib in Resources */ = {isa = PBXBuildFile; fileRef = CE80DB690FC194560086DCA6 /* progress.nib */; };
CE80DB6E0FC194560086DCA6 /* registration.nib in Resources */ = {isa = PBXBuildFile; fileRef = CE80DB6B0FC194560086DCA6 /* registration.nib */; };
CE895B5F0CFAE78300B5ADEA /* AppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CE895B5D0CFAE78300B5ADEA /* AppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE895B600CFAE78300B5ADEA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE895B5E0CFAE78300B5ADEA /* AppDelegate.m */; };
CE895C150CFAF0C900B5ADEA /* DirectoryPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = CE895C130CFAF0C900B5ADEA /* DirectoryPanel.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE895C160CFAF0C900B5ADEA /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE895C140CFAF0C900B5ADEA /* DirectoryPanel.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* dgbase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = dgbase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CE62CA710CFAF80D0001B6E0 /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = "<group>"; };
CE62CA720CFAF80D0001B6E0 /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = "<group>"; };
CE70A0FB0CF8C2560048C314 /* PyDupeGuru.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyDupeGuru.h; sourceTree = "<group>"; };
CE7D77030CF8987800BA287E /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE80DA170FC191320086DCA6 /* RecentDirectories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecentDirectories.h; path = ../../../cocoalib/RecentDirectories.h; sourceTree = SOURCE_ROOT; };
CE80DA180FC191320086DCA6 /* RecentDirectories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RecentDirectories.m; path = ../../../cocoalib/RecentDirectories.m; sourceTree = SOURCE_ROOT; };
CE80DA250FC191980086DCA6 /* Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Dialogs.h; path = ../../../cocoalib/Dialogs.h; sourceTree = SOURCE_ROOT; };
CE80DA260FC191980086DCA6 /* Dialogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Dialogs.m; path = ../../../cocoalib/Dialogs.m; sourceTree = SOURCE_ROOT; };
CE80DA270FC191980086DCA6 /* ProgressController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressController.h; path = ../../../cocoalib/ProgressController.h; sourceTree = SOURCE_ROOT; };
CE80DA280FC191980086DCA6 /* ProgressController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressController.m; path = ../../../cocoalib/ProgressController.m; sourceTree = SOURCE_ROOT; };
CE80DA290FC191980086DCA6 /* PyApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyApp.h; path = ../../../cocoalib/PyApp.h; sourceTree = SOURCE_ROOT; };
CE80DA2A0FC191980086DCA6 /* RegistrationInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegistrationInterface.h; path = ../../../cocoalib/RegistrationInterface.h; sourceTree = SOURCE_ROOT; };
CE80DA2B0FC191980086DCA6 /* RegistrationInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RegistrationInterface.m; path = ../../../cocoalib/RegistrationInterface.m; sourceTree = SOURCE_ROOT; };
CE80DA2C0FC191980086DCA6 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = ../../../cocoalib/Utils.h; sourceTree = SOURCE_ROOT; };
CE80DA2D0FC191980086DCA6 /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = ../../../cocoalib/Utils.m; sourceTree = SOURCE_ROOT; };
CE80DA370FC191C40086DCA6 /* Outline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Outline.h; path = ../../../cocoalib/Outline.h; sourceTree = SOURCE_ROOT; };
CE80DA380FC191C40086DCA6 /* Outline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Outline.m; path = ../../../cocoalib/Outline.m; sourceTree = SOURCE_ROOT; };
CE80DA390FC191C40086DCA6 /* Table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Table.h; path = ../../../cocoalib/Table.h; sourceTree = SOURCE_ROOT; };
CE80DA3A0FC191C40086DCA6 /* Table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Table.m; path = ../../../cocoalib/Table.m; sourceTree = SOURCE_ROOT; };
CE80DB6A0FC194560086DCA6 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = ../../../cocoalib/English.lproj/progress.nib; sourceTree = SOURCE_ROOT; };
CE80DB6C0FC194560086DCA6 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = ../../../cocoalib/English.lproj/registration.nib; sourceTree = SOURCE_ROOT; };
CE895B5D0CFAE78300B5ADEA /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
CE895B5E0CFAE78300B5ADEA /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
CE895C130CFAF0C900B5ADEA /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = "<group>"; };
CE895C140CFAF0C900B5ADEA /* DirectoryPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryPanel.m; sourceTree = "<group>"; };
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DC2EF560486A6940098B216 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
8DC2EF5B0486A6940098B216 /* dgbase.framework */,
);
name = Products;
sourceTree = "<group>";
};
0867D691FE84028FC02AAC07 /* dgbase */ = {
isa = PBXGroup;
children = (
08FB77AEFE84172EC02AAC07 /* Classes */,
CE80DA160FC1910F0086DCA6 /* cocoalib */,
32C88DFF0371C24200C91783 /* Other Sources */,
089C1665FE841158C02AAC07 /* Resources */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
034768DFFF38A50411DB9C8B /* Products */,
);
name = dgbase;
sourceTree = "<group>";
};
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
089C1665FE841158C02AAC07 /* Resources */ = {
isa = PBXGroup;
children = (
CE80DB690FC194560086DCA6 /* progress.nib */,
CE80DB6B0FC194560086DCA6 /* registration.nib */,
8DC2EF5A0486A6940098B216 /* Info.plist */,
089C1666FE841158C02AAC07 /* InfoPlist.strings */,
);
name = Resources;
sourceTree = "<group>";
};
08FB77AEFE84172EC02AAC07 /* Classes */ = {
isa = PBXGroup;
children = (
CE62CA710CFAF80D0001B6E0 /* ResultWindow.h */,
CE62CA720CFAF80D0001B6E0 /* ResultWindow.m */,
CE895C130CFAF0C900B5ADEA /* DirectoryPanel.h */,
CE895C140CFAF0C900B5ADEA /* DirectoryPanel.m */,
CE895B5D0CFAE78300B5ADEA /* AppDelegate.h */,
CE895B5E0CFAE78300B5ADEA /* AppDelegate.m */,
);
name = Classes;
sourceTree = "<group>";
};
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
isa = PBXGroup;
children = (
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
);
name = "Linked Frameworks";
sourceTree = "<group>";
};
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
isa = PBXGroup;
children = (
0867D6A5FE840307C02AAC07 /* AppKit.framework */,
D2F7E79907B2D74100F64583 /* CoreData.framework */,
0867D69BFE84028FC02AAC07 /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
32C88DFF0371C24200C91783 /* Other Sources */ = {
isa = PBXGroup;
children = (
CE70A0FB0CF8C2560048C314 /* PyDupeGuru.h */,
CE7D77030CF8987800BA287E /* Consts.h */,
);
name = "Other Sources";
sourceTree = "<group>";
};
CE80DA160FC1910F0086DCA6 /* cocoalib */ = {
isa = PBXGroup;
children = (
CE80DA370FC191C40086DCA6 /* Outline.h */,
CE80DA380FC191C40086DCA6 /* Outline.m */,
CE80DA390FC191C40086DCA6 /* Table.h */,
CE80DA3A0FC191C40086DCA6 /* Table.m */,
CE80DA250FC191980086DCA6 /* Dialogs.h */,
CE80DA260FC191980086DCA6 /* Dialogs.m */,
CE80DA270FC191980086DCA6 /* ProgressController.h */,
CE80DA280FC191980086DCA6 /* ProgressController.m */,
CE80DA290FC191980086DCA6 /* PyApp.h */,
CE80DA2A0FC191980086DCA6 /* RegistrationInterface.h */,
CE80DA2B0FC191980086DCA6 /* RegistrationInterface.m */,
CE80DA2C0FC191980086DCA6 /* Utils.h */,
CE80DA2D0FC191980086DCA6 /* Utils.m */,
CE80DA170FC191320086DCA6 /* RecentDirectories.h */,
CE80DA180FC191320086DCA6 /* RecentDirectories.m */,
);
name = cocoalib;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8DC2EF500486A6940098B216 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
CE7D77050CF8987800BA287E /* Consts.h in Headers */,
CE70A0FC0CF8C2560048C314 /* PyDupeGuru.h in Headers */,
CE895B5F0CFAE78300B5ADEA /* AppDelegate.h in Headers */,
CE895C150CFAF0C900B5ADEA /* DirectoryPanel.h in Headers */,
CE62CA730CFAF80D0001B6E0 /* ResultWindow.h in Headers */,
CE80DA190FC191320086DCA6 /* RecentDirectories.h in Headers */,
CE80DA2E0FC191980086DCA6 /* Dialogs.h in Headers */,
CE80DA300FC191980086DCA6 /* ProgressController.h in Headers */,
CE80DA320FC191980086DCA6 /* PyApp.h in Headers */,
CE80DA330FC191980086DCA6 /* RegistrationInterface.h in Headers */,
CE80DA350FC191980086DCA6 /* Utils.h in Headers */,
CE80DA3B0FC191C40086DCA6 /* Outline.h in Headers */,
CE80DA3D0FC191C40086DCA6 /* Table.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8DC2EF4F0486A6940098B216 /* dgbase */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "dgbase" */;
buildPhases = (
8DC2EF500486A6940098B216 /* Headers */,
8DC2EF520486A6940098B216 /* Resources */,
8DC2EF540486A6940098B216 /* Sources */,
8DC2EF560486A6940098B216 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = dgbase;
productInstallPath = "$(HOME)/Library/Frameworks";
productName = dgbase;
productReference = 8DC2EF5B0486A6940098B216 /* dgbase.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "dgbase" */;
compatibilityVersion = "Xcode 3.0";
hasScannedForEncodings = 1;
mainGroup = 0867D691FE84028FC02AAC07 /* dgbase */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8DC2EF4F0486A6940098B216 /* dgbase */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8DC2EF520486A6940098B216 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
CE80DB6D0FC194560086DCA6 /* progress.nib in Resources */,
CE80DB6E0FC194560086DCA6 /* registration.nib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8DC2EF540486A6940098B216 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE895B600CFAE78300B5ADEA /* AppDelegate.m in Sources */,
CE895C160CFAF0C900B5ADEA /* DirectoryPanel.m in Sources */,
CE62CA740CFAF80D0001B6E0 /* ResultWindow.m in Sources */,
CE80DA1A0FC191320086DCA6 /* RecentDirectories.m in Sources */,
CE80DA2F0FC191980086DCA6 /* Dialogs.m in Sources */,
CE80DA310FC191980086DCA6 /* ProgressController.m in Sources */,
CE80DA340FC191980086DCA6 /* RegistrationInterface.m in Sources */,
CE80DA360FC191980086DCA6 /* Utils.m in Sources */,
CE80DA3C0FC191C40086DCA6 /* Outline.m in Sources */,
CE80DA3E0FC191C40086DCA6 /* Table.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C1667FE841158C02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
CE80DB690FC194560086DCA6 /* progress.nib */ = {
isa = PBXVariantGroup;
children = (
CE80DB6A0FC194560086DCA6 /* English */,
);
name = progress.nib;
sourceTree = SOURCE_ROOT;
};
CE80DB6B0FC194560086DCA6 /* registration.nib */ = {
isa = PBXVariantGroup;
children = (
CE80DB6C0FC194560086DCA6 /* English */,
);
name = registration.nib;
sourceTree = SOURCE_ROOT;
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
1DEB91AE08733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../cocoalib/build/Release\"",
);
FRAMEWORK_VERSION = A;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Frameworks";
PRODUCT_NAME = dgbase;
WRAPPER_EXTENSION = framework;
ZERO_LINK = YES;
};
name = Debug;
};
1DEB91AF08733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../cocoalib/build/Release\"",
);
FRAMEWORK_VERSION = A;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@executable_path/../Frameworks";
PRODUCT_NAME = dgbase;
WRAPPER_EXTENSION = framework;
};
name = Release;
};
1DEB91B208733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
};
name = Debug;
};
1DEB91B308733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
ppc,
i386,
);
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "dgbase" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91AE08733DA50010E9CD /* Debug */,
1DEB91AF08733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "dgbase" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91B208733DA50010E9CD /* Debug */,
1DEB91B308733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}

0
base/qt/__init__.py Normal file
View File

35
base/qt/about_box.py Normal file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env python
# Unit Name: about_box
# Created By: Virgil Dupras
# Created On: 2009-05-09
# $Id$
# Copyright 2009 Hardcoded Software (http://www.hardcoded.net)
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()

133
base/qt/about_box.ui Normal file
View File

@ -0,0 +1,133 @@
<?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>

269
base/qt/app.py Normal file
View File

@ -0,0 +1,269 @@
#!/usr/bin/env python
# Unit Name: app
# Created By: Virgil Dupras
# Created On: 2009-04-25
# $Id$
# Copyright 2009 Hardcoded Software (http://www.hardcoded.net)
import logging
import os.path as op
import traceback
from PyQt4.QtCore import Qt, QTimer, QObject, QCoreApplication, QUrl, SIGNAL
from PyQt4.QtGui import QProgressDialog, QDesktopServices, QFileDialog, QDialog, QMessageBox
from hsutil import job
from hsutil.reg import RegistrationRequired
from dupeguru import data_pe
from dupeguru.app import (DupeGuru as DupeGuruBase, JOB_SCAN, JOB_LOAD, JOB_MOVE, JOB_COPY,
JOB_DELETE)
from main_window import MainWindow
from directories_dialog import DirectoriesDialog
from about_box import AboutBox
from reg import Registration
from error_report_dialog import ErrorReportDialog
JOBID2TITLE = {
JOB_SCAN: "Scanning for duplicates",
JOB_LOAD: "Loading",
JOB_MOVE: "Moving",
JOB_COPY: "Copying",
JOB_DELETE: "Sending files to the recycle bin",
}
class Progress(QProgressDialog, job.ThreadedJobPerformer):
def __init__(self, parent):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
QProgressDialog.__init__(self, '', u"Cancel", 0, 100, parent, flags)
self.setModal(True)
self.setAutoReset(False)
self.setAutoClose(False)
self._timer = QTimer()
self._jobid = ''
self.connect(self._timer, SIGNAL('timeout()'), self.updateProgress)
def updateProgress(self):
# the values might change before setValue happens
last_progress = self.last_progress
last_desc = self.last_desc
if not self._job_running or last_progress is None:
self._timer.stop()
self.close()
self.emit(SIGNAL('finished(QString)'), self._jobid)
if self._last_error is not None:
s = ''.join(traceback.format_exception(*self._last_error))
dialog = ErrorReportDialog(self.parent(), s)
dialog.exec_()
return
if self.wasCanceled():
self.job_cancelled = True
return
if last_desc:
self.setLabelText(last_desc)
self.setValue(last_progress)
def run(self, jobid, title, target, args=()):
self._jobid = jobid
self.reset()
self.setLabelText('')
self.run_threaded(target, args)
self.setWindowTitle(title)
self.show()
self._timer.start(500)
def demo_method(method):
def wrapper(self, *args, **kwargs):
try:
return method(self, *args, **kwargs)
except RegistrationRequired:
msg = "The demo version of dupeGuru only allows 10 actions (delete/move/copy) per session."
QMessageBox.information(self.main_window, 'Demo', msg)
return wrapper
class DupeGuru(DupeGuruBase, QObject):
LOGO_NAME = '<replace this>'
NAME = '<replace this>'
DELTA_COLUMNS = frozenset()
def __init__(self, data_module, appid):
appdata = unicode(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
DupeGuruBase.__init__(self, data_module, appdata, appid)
QObject.__init__(self)
self._setup()
#--- Private
def _setup(self):
self.selected_dupe = None
self.prefs = self._create_preferences()
self.prefs.load()
self._update_options()
self.main_window = self._create_main_window()
self._progress = Progress(self.main_window)
self.directories_dialog = DirectoriesDialog(self.main_window, self)
self.details_dialog = self._create_details_dialog(self.main_window)
self.preferences_dialog = self._create_preferences_dialog(self.main_window)
self.about_box = AboutBox(self.main_window, self)
self.reg = Registration(self)
self.set_registration(self.prefs.registration_code, self.prefs.registration_email)
if not self.registered:
self.reg.show_nag()
self.main_window.show()
self.load()
self.connect(QCoreApplication.instance(), SIGNAL('aboutToQuit()'), self.application_will_terminate)
self.connect(self._progress, SIGNAL('finished(QString)'), self.job_finished)
def _setup_as_registered(self):
self.prefs.registration_code = self.registration_code
self.prefs.registration_email = self.registration_email
self.main_window.actionRegister.setVisible(False)
self.about_box.registerButton.hide()
self.about_box.registeredEmailLabel.setText(self.prefs.registration_email)
def _update_options(self):
self.scanner.mix_file_kind = self.prefs.mix_file_kind
self.options['escape_filter_regexp'] = self.prefs.use_regexp
self.options['clean_empty_dirs'] = self.prefs.remove_empty_folders
#--- Virtual
def _create_details_dialog(self, parent):
raise NotImplementedError()
def _create_main_window(self):
return MainWindow(app=self)
def _create_preferences(self):
raise NotImplementedError()
def _create_preferences_dialog(self, parent):
raise NotImplementedError()
#--- Override
def _start_job(self, jobid, func):
title = JOBID2TITLE[jobid]
try:
j = self._progress.create_job()
self._progress.run(jobid, title, func, args=(j, ))
except job.JobInProgressError:
msg = "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."
QMessageBox.information(self.main_window, 'Action in progress', msg)
#--- Public
def add_dupes_to_ignore_list(self, duplicates):
for dupe in duplicates:
self.AddToIgnoreList(dupe)
self.remove_duplicates(duplicates)
def ApplyFilter(self, filter):
DupeGuruBase.ApplyFilter(self, filter)
self.emit(SIGNAL('resultsChanged()'))
def ask_for_reg_code(self):
if self.reg.ask_for_code():
self._setup_ui_as_registered()
@demo_method
def copy_or_move_marked(self, copy):
opname = 'copy' if copy else 'move'
title = "Select a directory to {0} marked files to".format(opname)
flags = QFileDialog.ShowDirsOnly
destination = unicode(QFileDialog.getExistingDirectory(self.main_window, title, '', flags))
if not destination:
return
recreate_path = self.prefs.destination_type
DupeGuruBase.copy_or_move_marked(self, copy, destination, recreate_path)
delete_marked = demo_method(DupeGuruBase.delete_marked)
def make_reference(self, duplicates):
DupeGuruBase.make_reference(self, duplicates)
self.emit(SIGNAL('resultsChanged()'))
def mark_all(self):
self.results.mark_all()
self.emit(SIGNAL('dupeMarkingChanged()'))
def mark_invert(self):
self.results.mark_invert()
self.emit(SIGNAL('dupeMarkingChanged()'))
def mark_none(self):
self.results.mark_none()
self.emit(SIGNAL('dupeMarkingChanged()'))
def open_selected(self):
if self.selected_dupe is None