1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-24 23:51:38 +00:00

Compare commits

..

20 Commits

Author SHA1 Message Date
Virgil Dupras
96ef2f2dd3 Added tag me5.10.0 for changeset d3fe0d0dcda1 2010-09-27 15:13:36 +02:00
Virgil Dupras
2542af17b6 Adjusted default column widths so it fits better with the revamped UI. 2010-09-27 12:25:31 +02:00
Virgil Dupras
c86bc649ff pe 1.11.0 and me 5.10.0. 2010-09-27 11:56:02 +02:00
Virgil Dupras
4b8e48ed88 Added tag se2.12.0 for changeset dbfee3ee2fa5 2010-09-26 14:26:06 +02:00
Virgil Dupras
a1addfd416 Fixed typo in changelog. 2010-09-26 14:25:53 +02:00
Virgil Dupras
a1a57d8933 Adjusted default column widths to fit better with UI revamp. 2010-09-26 12:50:45 +02:00
Virgil Dupras
864970b860 se2.12.0 2010-09-26 12:33:39 +02:00
Virgil Dupras
a056be0842 Fixed UI glitch introduced by the move from outline to table for results (the selected row would not be kept visible after refreshes). 2010-09-26 12:09:50 +02:00
Virgil Dupras
c672e75739 Updated subrepo. 2010-09-26 02:20:18 -07:00
Virgil Dupras
7b5dd3f964 Adjusted the height of the pref pane in SE under Linux. 2010-09-26 02:17:29 -07:00
Virgil Dupras
a6072f608b [#105 state:fixed] Allow multiple selection in Add Directory. 2010-09-25 16:12:20 +02:00
Virgil Dupras
06462c65a5 Updated help files. 2010-09-25 15:49:19 +02:00
Virgil Dupras
359f9c0680 [#92 state:fixed] Added an action to delete duplicates and then create hardlinks to group ref. 2010-09-25 15:37:18 +02:00
Virgil Dupras
01db7c4948 Fixed a py3k-induced bug when drag & dropping directories in the directories panel. 2010-09-25 15:34:42 +02:00
Virgil Dupras
f67f14a78d Fixed compilation warning under cocoa. 2010-09-25 12:35:51 +02:00
Virgil Dupras
0a64d653e1 [#92 state:fixed] Added an option to ignore duplicates hardlinking to the same file. 2010-09-25 12:28:34 +02:00
Virgil Dupras
456a835285 Made the main window under cocoa a little cuter. 2010-09-24 16:01:38 +02:00
Virgil Dupras
0d8ed92a68 Converted the result tree into a result table.
--HG--
rename : cocoa/base/PyResultTree.h => cocoa/base/PyResultTable.h
rename : cocoa/base/ResultOutline.h => cocoa/base/ResultTable.h
rename : cocoa/base/ResultOutline.m => cocoa/base/ResultTable.m
rename : core/gui/result_tree.py => core/gui/result_table.py
2010-09-24 15:48:59 +02:00
Virgil Dupras
9bd093a03c [#106 state:fixed] I couldn't find the root cause of the problem, but I wrapped it anyway... 2010-09-24 09:56:08 +02:00
Virgil Dupras
361d4698a9 Added tag se2.11.1 for changeset 9735a5218d2b 2010-08-26 13:39:42 +02:00
56 changed files with 1231 additions and 840 deletions

View File

@@ -28,3 +28,6 @@ f71d405e62badcfdc1b037facaac043cece40ee5 se2.10.1
b56fe4dd8c95bca270b078a09e86848df77e2b2d me5.9.0
618a7365457d56fdc6920c70843a244762e2ea00 pe1.10.0
95b3a4b564c6222b414f2b40182dde2bd6d0e8a4 me5.9.1
9735a5218d2b5b3b1e1dfe17f2f874177cf8f61c se2.11.1
dbfee3ee2fa5cbb9e7ab36570659c17cd5b8561f se2.12.0
d3fe0d0dcda1e0bf1100d02f117503d3bf6baacf me5.10.0

1
README
View File

@@ -13,7 +13,6 @@ There are also other sub-folder that comes from external repositories (automatic
with svn:externals):
- hscommon: A collection of helpers used across HS applications.
- hsdocgen: An ad-hoc document generation used across HS project (used for help files)
- cocoalib: A collection of helpers used across Cocoa UI codebases of HS applications.
- qtlib: A collection of helpers used across Qt UI codebases of HS applications.

View File

@@ -39,14 +39,14 @@ http://www.hardcoded.net/licenses/hs_license
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setCanChooseFiles:YES];
[op setCanChooseDirectories:YES];
[op setAllowsMultipleSelection:NO];
[op setAllowsMultipleSelection:YES];
[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];
if ([op runModal] == NSOKButton) {
for (NSString *directory in [op filenames]) {
[self addDirectory:directory];
}
}
}
- (IBAction)popupAddDirectoryMenu:(id)sender
@@ -95,18 +95,14 @@ http://www.hardcoded.net/licenses/hs_license
{
NSInteger r = [[_py addDirectory:directory] intValue];
if (r) {
NSString *m;
switch (r) {
case 1: {
m = @"This directory already is in the list.";
break;
NSString *m = @"";
if (r == 1) {
m = @"'%@' already is in the list.";
}
case 2: {
m = @"This directory does not exist.";
break;
else if (r == 2) {
m = @"'%@' does not exist.";
}
}
[Dialogs showMessage:m];
[Dialogs showMessage:[NSString stringWithFormat:m,directory]];
}
[_recentDirectories addDirectory:directory];
[[self window] makeKeyAndOrderFront:nil];

View File

@@ -39,6 +39,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)copyOrMove:(NSNumber *)aCopy markedTo:(NSString *)destination recreatePath:(NSNumber *)aRecreateType;
- (void)deleteMarked;
- (void)hardlinkMarked;
- (void)removeMarked;
//Data
@@ -48,8 +49,9 @@ http://www.hardcoded.net/licenses/hs_license
//Scanning options
- (void)setMinMatchPercentage:(NSNumber *)percentage;
- (void)setMixFileKind:(NSNumber *)mix_file_kind;
- (void)setEscapeFilterRegexp:(NSNumber *)escape_filter_regexp;
- (void)setRemoveEmptyFolders:(NSNumber *)remove_empty_folders;
- (void)setMixFileKind:(BOOL)mix_file_kind;
- (void)setEscapeFilterRegexp:(BOOL)escape_filter_regexp;
- (void)setRemoveEmptyFolders:(BOOL)remove_empty_folders;
- (void)setIgnoreHardlinkMatches:(BOOL)ignore_hardlink_matches;
- (void)setSizeThreshold:(NSInteger)size_threshold;
@end

View File

@@ -7,18 +7,18 @@ http://www.hardcoded.net/licenses/hs_license
*/
#import <Cocoa/Cocoa.h>
#import "PyOutline.h"
#import "PyTable.h"
@interface PyResultTree : PyOutline
@interface PyResultTable : PyTable
- (BOOL)powerMarkerMode;
- (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode;
- (BOOL)deltaValuesMode;
- (void)setDeltaValuesMode:(BOOL)aDeltaValuesMode;
- (NSString *)valueForPath:(NSArray *)aPath column:(NSInteger)aColumn;
- (NSString *)valueForRow:(NSInteger)rowIndex column:(NSInteger)aColumn;
- (BOOL)renameSelected:(NSString *)aNewName;
- (void)sortBy:(NSInteger)aIdentifier ascending:(BOOL)aAscending;
- (void)markSelected;
- (void)removeSelected;
- (NSArray *)rootChildrenCounts;
- (NSInteger)selectedDupeCount;
@end

View File

@@ -1,207 +0,0 @@
/*
Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "HS" License as described in the "LICENSE" file,
which should be included with this package. The terms are also available at
http://www.hardcoded.net/licenses/hs_license
*/
#import "ResultOutline.h"
#import "Dialogs.h"
#import "Utils.h"
#import "Consts.h"
@implementation ResultOutline
- (id)initWithPyParent:(id)aPyParent view:(HSOutlineView *)aOutlineView
{
self = [super initWithPyClassName:@"PyResultOutline" pyParent:aPyParent view:aOutlineView];
_rootChildrenCounts = nil;
[self connect];
return self;
}
- (void)dealloc
{
[self disconnect];
[_deltaColumns release];
[super dealloc];
}
- (PyResultTree *)py
{
return (PyResultTree *)py;
}
/* Public */
- (BOOL)powerMarkerMode
{
return [[self py] powerMarkerMode];
}
- (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode
{
[[self py] setPowerMarkerMode:aPowerMarkerMode];
}
- (BOOL)deltaValuesMode
{
return [[self py] deltaValuesMode];
}
- (void)setDeltaValuesMode:(BOOL)aDeltaValuesMode
{
[[self py] setDeltaValuesMode:aDeltaValuesMode];
}
- (void)setDeltaColumns:(NSIndexSet *)aDeltaColumns
{
[_deltaColumns release];
_deltaColumns = [aDeltaColumns retain];
}
- (NSInteger)selectedDupeCount
{
NSArray *selected = [self selectedIndexPaths];
if ([self powerMarkerMode]) {
return [selected count];
}
else {
NSInteger r = 0;
for (NSIndexPath *path in selected) {
if ([path length] == 2) {
r++;
}
}
return r;
}
}
- (void)removeSelected
{
NSInteger selectedDupeCount = [self selectedDupeCount];
if (!selectedDupeCount)
return;
NSString *msg = [NSString stringWithFormat:@"You are about to remove %d files from results. Continue?",selectedDupeCount];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[[self py] removeSelected];
}
/* Datasource */
- (NSInteger)outlineView:(NSOutlineView *)aOutlineView numberOfChildrenOfItem:(id)item
{
NSIndexPath *path = item;
if ((path != nil) && ([path length] == 1)) {
if (_rootChildrenCounts == nil) {
_rootChildrenCounts = [[[self py] rootChildrenCounts] retain];
}
NSInteger index = [path indexAtPosition:0];
return n2i([_rootChildrenCounts objectAtIndex:index]);
}
return [super outlineView:aOutlineView numberOfChildrenOfItem:item];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)column byItem:(id)item
{
NSIndexPath *path = item;
NSString *identifier = [column identifier];
if ([identifier isEqual:@"marked"]) {
return b2n([self boolProperty:@"marked" valueAtPath:path]);
}
NSInteger columnId = [identifier integerValue];
return [[self py] valueForPath:p2a(path) column:columnId];
}
- (void)outlineView:(NSOutlineView *)aOutlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if ([[tableColumn identifier] isEqual:@"0"]) {
NSIndexPath *path = item;
NSString *oldName = [[self py] valueForPath:p2a(path) column:0];
NSString *newName = object;
if (![newName isEqual:oldName]) {
BOOL renamed = [[self py] renameSelected:newName];
if (!renamed) {
[Dialogs showMessage:[NSString stringWithFormat:@"The name '%@' already exists.", newName]];
}
else {
[self refreshItemAtPath:path];
}
}
}
else {
[super outlineView:aOutlineView setObjectValue:object forTableColumn:tableColumn byItem:item];
}
}
/* Delegate */
- (void)outlineView:(NSOutlineView *)aOutlineView didClickTableColumn:(NSTableColumn *)tableColumn
{
if ([[outlineView sortDescriptors] count] < 1)
return;
NSSortDescriptor *sd = [[outlineView sortDescriptors] objectAtIndex:0];
[[self py] sortBy:[[sd key] integerValue] ascending:[sd ascending]];
}
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSIndexPath *path = item;
BOOL isMarkable = [self boolProperty:@"markable" valueAtPath:path];
if ([[tableColumn identifier] isEqual:@"marked"]) {
[cell setEnabled:isMarkable];
}
if ([cell isKindOfClass:[NSTextFieldCell class]]) {
// Determine if the text color will be blue due to directory being reference.
NSTextFieldCell *textCell = cell;
if (isMarkable) {
[textCell setTextColor:[NSColor blackColor]];
}
else {
[textCell setTextColor:[NSColor blueColor]];
}
if (([self deltaValuesMode]) && ([self powerMarkerMode] || ([path length] > 1))) {
NSInteger i = [[tableColumn identifier] integerValue];
if ([_deltaColumns containsIndex:i]) {
[textCell setTextColor:[NSColor orangeColor]];
}
}
}
}
- (BOOL)tableViewHadDeletePressed:(NSTableView *)tableView
{
[self removeSelected];
return YES;
}
- (BOOL)tableViewHadSpacePressed:(NSTableView *)tableView
{
[[self py] markSelected];
return YES;
}
/* don't calls saveEdits and cancelEdits */
- (void)outlineViewDidEndEditing:(HSOutlineView *)outlineView
{
}
- (void)outlineViewCancelsEdition:(HSOutlineView *)outlineView
{
}
/* Python --> Cocoa */
- (void)refresh /* Override */
{
[_rootChildrenCounts release];
_rootChildrenCounts = nil;
[super refresh];
[outlineView expandItem:nil expandChildren:YES];
}
- (void)invalidateMarkings
{
for (NSMutableDictionary *props in [itemData objectEnumerator]) {
[props removeObjectForKey:@"marked"];
}
[outlineView setNeedsDisplay:YES];
}
@end

View File

@@ -7,15 +7,15 @@ http://www.hardcoded.net/licenses/hs_license
*/
#import <Cocoa/Cocoa.h>
#import "HSOutline.h"
#import "PyResultTree.h"
#import "HSTable.h"
#import "PyResultTable.h"
@interface ResultOutline : HSOutline
@interface ResultTable : HSTable
{
NSIndexSet *_deltaColumns;
NSArray *_rootChildrenCounts;
}
- (PyResultTree *)py;
- (id)initWithPyParent:(id)aPyParent view:(NSTableView *)aTableView;
- (PyResultTable *)py;
- (BOOL)powerMarkerMode;
- (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode;
- (BOOL)deltaValuesMode;

162
cocoa/base/ResultTable.m Normal file
View File

@@ -0,0 +1,162 @@
/*
Copyright 2010 Hardcoded Software (http://www.hardcoded.net)
This software is licensed under the "HS" License as described in the "LICENSE" file,
which should be included with this package. The terms are also available at
http://www.hardcoded.net/licenses/hs_license
*/
#import "ResultTable.h"
#import "Dialogs.h"
#import "Utils.h"
#import "Consts.h"
@implementation ResultTable
- (id)initWithPyParent:(id)aPyParent view:(NSTableView *)aTableView
{
self = [super initWithPyClassName:@"PyResultTable" pyParent:aPyParent view:aTableView];
[self connect];
return self;
}
- (void)dealloc
{
[self disconnect];
[_deltaColumns release];
[super dealloc];
}
- (PyResultTable *)py
{
return (PyResultTable *)py;
}
/* Public */
- (BOOL)powerMarkerMode
{
return [[self py] powerMarkerMode];
}
- (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode
{
[[self py] setPowerMarkerMode:aPowerMarkerMode];
}
- (BOOL)deltaValuesMode
{
return [[self py] deltaValuesMode];
}
- (void)setDeltaValuesMode:(BOOL)aDeltaValuesMode
{
[[self py] setDeltaValuesMode:aDeltaValuesMode];
}
- (void)setDeltaColumns:(NSIndexSet *)aDeltaColumns
{
[_deltaColumns release];
_deltaColumns = [aDeltaColumns retain];
}
- (NSInteger)selectedDupeCount
{
return [[self py] selectedDupeCount];
}
- (void)removeSelected
{
NSInteger selectedDupeCount = [self selectedDupeCount];
if (!selectedDupeCount)
return;
NSString *msg = [NSString stringWithFormat:@"You are about to remove %d files from results. Continue?",selectedDupeCount];
if ([Dialogs askYesNo:msg] == NSAlertSecondButtonReturn) // NO
return;
[[self py] removeSelected];
}
/* Datasource */
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row
{
NSString *identifier = [column identifier];
if ([identifier isEqual:@"marked"]) {
return [[self py] valueForColumn:@"marked" row:row];
}
NSInteger columnId = [identifier integerValue];
return [[self py] valueForRow:row column:columnId];
}
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)column row:(NSInteger)row
{
NSString *identifier = [column identifier];
if ([identifier isEqual:@"marked"]) {
[[self py] setValue:object forColumn:identifier row:row];
}
else if ([identifier isEqual:@"0"]) {
NSString *oldName = [[self py] valueForRow:row column:0];
NSString *newName = object;
if (![newName isEqual:oldName]) {
BOOL renamed = [[self py] renameSelected:newName];
if (!renamed) {
[Dialogs showMessage:[NSString stringWithFormat:@"The name '%@' already exists.", newName]];
}
else {
[tableView setNeedsDisplay:YES];
}
}
}
}
/* Delegate */
- (void)tableView:(NSTableView *)aTableView didClickTableColumn:(NSTableColumn *)tableColumn
{
if ([[tableView sortDescriptors] count] < 1)
return;
NSSortDescriptor *sd = [[tableView sortDescriptors] objectAtIndex:0];
[[self py] sortBy:[[sd key] integerValue] ascending:[sd ascending]];
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)column row:(NSInteger)row
{
BOOL isMarkable = n2b([[self py] valueForColumn:@"markable" row:row]);
if ([[column identifier] isEqual:@"marked"]) {
[cell setEnabled:isMarkable];
// Low-tech solution, for indentation, but it works...
NSCellImagePosition pos = isMarkable ? NSImageRight : NSImageLeft;
[cell setImagePosition:pos];
}
if ([cell isKindOfClass:[NSTextFieldCell class]]) {
// Determine if the text color will be blue due to directory being reference.
NSTextFieldCell *textCell = cell;
if (isMarkable) {
[textCell setTextColor:[NSColor blackColor]];
}
else {
[textCell setTextColor:[NSColor blueColor]];
if ([self deltaValuesMode]) {
NSInteger i = [[column identifier] integerValue];
if ([_deltaColumns containsIndex:i]) {
[textCell setTextColor:[NSColor orangeColor]];
}
}
}
}
}
- (BOOL)tableViewHadDeletePressed:(NSTableView *)tableView
{
[self removeSelected];
return YES;
}
- (BOOL)tableViewHadSpacePressed:(NSTableView *)tableView
{
[[self py] markSelected];
return YES;
}
/* Python --> Cocoa */
- (void)invalidateMarkings
{
[tableView setNeedsDisplay:YES];
}
@end

View File

@@ -7,10 +7,10 @@ http://www.hardcoded.net/licenses/hs_license
*/
#import <Cocoa/Cocoa.h>
#import "HSOutlineView.h"
#import "StatsLabel.h"
#import "ResultOutline.h"
#import "ResultTable.h"
#import "ProblemDialog.h"
#import "HSTableView.h"
#import "PyDupeGuru.h"
@interface ResultWindowBase : NSWindowController
@@ -19,7 +19,7 @@ http://www.hardcoded.net/licenses/hs_license
IBOutlet PyDupeGuruBase *py;
IBOutlet id app;
IBOutlet NSSegmentedControl *deltaSwitch;
IBOutlet HSOutlineView *matches;
IBOutlet HSTableView *matches;
IBOutlet NSSegmentedControl *pmSwitch;
IBOutlet NSTextField *stats;
IBOutlet NSMenu *columnsMenu;
@@ -27,7 +27,7 @@ http://www.hardcoded.net/licenses/hs_license
NSMutableArray *_resultColumns;
NSWindowController *preferencesPanel;
ResultOutline *outline;
ResultTable *table;
StatsLabel *statsLabel;
ProblemDialog *problemDialog;
}
@@ -38,6 +38,7 @@ http://www.hardcoded.net/licenses/hs_license
- (NSDictionary *)getColumnsWidth;
- (void)initResultColumns;
- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth;
- (void)sendMarkedToTrash:(BOOL)hardlinkDeleted;
/* Actions */
- (IBAction)clearIgnoreList:(id)sender;
@@ -45,6 +46,7 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)changePowerMarker:(id)sender;
- (IBAction)copyMarked:(id)sender;
- (IBAction)deleteMarked:(id)sender;
- (IBAction)hardlinkMarked:(id)sender;
- (IBAction)exportToXHTML:(id)sender;
- (IBAction)filter:(id)sender;
- (IBAction)ignoreSelected:(id)sender;

View File

@@ -18,8 +18,10 @@ http://www.hardcoded.net/licenses/hs_license
- (void)awakeFromNib
{
[self window];
/* Put a cute iTunes-like bottom bar */
[[self window] setContentBorderThickness:28 forEdge:NSMinYEdge];
preferencesPanel = [[NSWindowController alloc] initWithWindowNibName:@"Preferences"];
outline = [[ResultOutline alloc] initWithPyParent:py view:matches];
table = [[ResultTable alloc] initWithPyParent:py view:matches];
statsLabel = [[StatsLabel alloc] initWithPyParent:py labelView:stats];
problemDialog = [[ProblemDialog alloc] initWithPy:py];
[self initResultColumns];
@@ -37,7 +39,7 @@ http://www.hardcoded.net/licenses/hs_license
- (void)dealloc
{
[outline release];
[table release];
[preferencesPanel release];
[statsLabel release];
[problemDialog release];
@@ -124,6 +126,29 @@ http://www.hardcoded.net/licenses/hs_license
}
}
- (void)sendMarkedToTrash:(BOOL)hardlinkDeleted
{
NSInteger mark_count = [[py getMarkCount] intValue];
if (!mark_count) {
return;
}
NSString *msg = @"You are about to send %d files to Trash. Continue?";
if (hardlinkDeleted) {
msg = @"You are about to send %d files to Trash (and hardlink them afterwards). Continue?";
}
if ([Dialogs askYesNo:[NSString stringWithFormat:msg,mark_count]] == NSAlertSecondButtonReturn) { // NO
return;
}
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setRemoveEmptyFolders:n2b([ud objectForKey:@"removeEmptyFolders"])];
if (hardlinkDeleted) {
[py hardlinkMarked];
}
else {
[py deleteMarked];
}
}
/* Actions */
- (IBAction)clearIgnoreList:(id)sender
{
@@ -137,12 +162,12 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)changeDelta:(id)sender
{
[outline setDeltaValuesMode:[deltaSwitch selectedSegment] == 1];
[table setDeltaValuesMode:[deltaSwitch selectedSegment] == 1];
}
- (IBAction)changePowerMarker:(id)sender
{
[outline setPowerMarkerMode:[pmSwitch selectedSegment] == 1];
[table setPowerMarkerMode:[pmSwitch selectedSegment] == 1];
}
- (IBAction)copyMarked:(id)sender
@@ -166,14 +191,12 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)deleteMarked:(id)sender
{
NSInteger 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];
[self sendMarkedToTrash:NO];
}
- (IBAction)hardlinkMarked:(id)sender
{
[self sendMarkedToTrash:YES];
}
- (IBAction)exportToXHTML:(id)sender
@@ -185,13 +208,13 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)filter:(id)sender
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setEscapeFilterRegexp:b2n(!n2b([ud objectForKey:@"useRegexpFilter"]))];
[py setEscapeFilterRegexp:!n2b([ud objectForKey:@"useRegexpFilter"])];
[py applyFilter:[filterField stringValue]];
}
- (IBAction)ignoreSelected:(id)sender
{
NSInteger selectedDupeCount = [outline selectedDupeCount];
NSInteger selectedDupeCount = [table selectedDupeCount];
if (!selectedDupeCount)
return;
NSString *msg = [NSString stringWithFormat:@"All selected %d matches are going to be ignored in all subsequent scans. Continue?",selectedDupeCount];
@@ -262,7 +285,7 @@ http://www.hardcoded.net/licenses/hs_license
{
NSString *directory = [[op filenames] objectAtIndex:0];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[py setRemoveEmptyFolders:[ud objectForKey:@"removeEmptyFolders"]];
[py setRemoveEmptyFolders:n2b([ud objectForKey:@"removeEmptyFolders"])];
[py copyOrMove:b2n(NO) markedTo:directory recreatePath:[ud objectForKey:@"recreatePathType"]];
}
}
@@ -293,7 +316,7 @@ http://www.hardcoded.net/licenses/hs_license
- (IBAction)removeSelected:(id)sender
{
[outline removeSelected];
[table removeSelected];
}
- (IBAction)renameSelected:(id)sender
@@ -416,8 +439,8 @@ http://www.hardcoded.net/licenses/hs_license
}
}
else if ([lastAction isEqualTo:jobScan]) {
NSInteger groupCount = [outline intProperty:@"children_count" valueAtPath:nil];
if (groupCount == 0)
NSInteger rowCount = [[table py] numberOfRows];
if (rowCount == 0)
[Dialogs showMessage:@"No duplicates found."];
}

View File

@@ -12,7 +12,8 @@
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="1204"/>
<integer value="1147"/>
<integer value="598"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -84,17 +85,16 @@
<object class="NSSegmentedControl" key="NSToolbarItemView" id="35398541">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{7, 14}, {67, 24}}</string>
<string key="NSFrame">{{7, 14}, {67, 25}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSegmentedCell" key="NSCell" id="431579725">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<object class="NSFont" key="NSSupport" id="26">
<object class="NSFont" key="NSSupport" id="473104458">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
<int key="NSfFlags">16</int>
</object>
<reference key="NSControlView" ref="35398541"/>
<object class="NSMutableArray" key="NSSegmentImages">
@@ -112,13 +112,14 @@
</object>
</object>
<int key="NSSelectedSegment">1</int>
<int key="NSSegmentStyle">2</int>
</object>
</object>
<nil key="NSToolbarItemImage"/>
<nil key="NSToolbarItemTarget"/>
<nil key="NSToolbarItemAction"/>
<string key="NSToolbarItemMinSize">{67, 24}</string>
<string key="NSToolbarItemMaxSize">{67, 24}</string>
<string key="NSToolbarItemMaxSize">{67, 25}</string>
<bool key="NSToolbarItemEnabled">YES</bool>
<bool key="NSToolbarItemAutovalidates">YES</bool>
<int key="NSToolbarItemTag">0</int>
@@ -181,7 +182,6 @@
<int key="NSvFlags">258</int>
<string key="NSFrame">{{0, 14}, {81, 22}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSearchFieldCell" key="NSCell" id="484816507">
<int key="NSCellFlags">343014976</int>
@@ -325,18 +325,16 @@
<object class="NSPopUpButton" key="NSToolbarItemView" id="165812138">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{0, 14}, {58, 26}}</string>
<string key="NSFrame">{{1, 14}, {40, 25}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="436420677">
<int key="NSCellFlags">-2076049856</int>
<int key="NSCellFlags2">2048</int>
<int key="NSCellFlags2">134219776</int>
<reference key="NSSupport" ref="594927229"/>
<reference key="NSControlView" ref="165812138"/>
<int key="NSButtonFlags">109199615</int>
<int key="NSButtonFlags2">1</int>
<reference key="NSAlternateImage" ref="594927229"/>
<int key="NSButtonFlags">-2035269377</int>
<int key="NSButtonFlags2">35</int>
<string key="NSAlternateContents"/>
<object class="NSMutableString" key="NSKeyEquivalent">
<characters key="NS.bytes"/>
@@ -384,6 +382,16 @@
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="436420677"/>
</object>
<object class="NSMenuItem" id="103810273">
<reference key="NSMenu" ref="106411576"/>
<string key="NSTitle">Delete Marked and Replace with Hardlinks</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852972005"/>
<reference key="NSMixedImage" ref="218295580"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="436420677"/>
</object>
<object class="NSMenuItem" id="707934795">
<reference key="NSMenu" ref="106411576"/>
<string key="NSTitle">Move Marked to...</string>
@@ -504,18 +512,19 @@
</object>
</object>
</object>
<int key="NSSelectedIndex">2</int>
<bool key="NSPullDown">YES</bool>
<int key="NSPreferredEdge">3</int>
<bool key="NSUsesItemFromMenu">YES</bool>
<bool key="NSAltersState">YES</bool>
<int key="NSArrowPosition">1</int>
<int key="NSArrowPosition">2</int>
</object>
</object>
<reference key="NSToolbarItemImage" ref="465938577"/>
<nil key="NSToolbarItemTarget"/>
<nil key="NSToolbarItemAction"/>
<string key="NSToolbarItemMinSize">{58, 26}</string>
<string key="NSToolbarItemMaxSize">{58, 26}</string>
<string key="NSToolbarItemMinSize">{30, 25}</string>
<string key="NSToolbarItemMaxSize">{40, 26}</string>
<bool key="NSToolbarItemEnabled">YES</bool>
<bool key="NSToolbarItemAutovalidates">YES</bool>
<int key="NSToolbarItemTag">0</int>
@@ -532,14 +541,13 @@
<object class="NSSegmentedControl" key="NSToolbarItemView" id="311230297">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{4, 14}, {67, 24}}</string>
<string key="NSFrame">{{4, 14}, {67, 25}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSegmentedCell" key="NSCell" id="211272396">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<reference key="NSSupport" ref="26"/>
<reference key="NSSupport" ref="473104458"/>
<reference key="NSControlView" ref="311230297"/>
<object class="NSMutableArray" key="NSSegmentImages">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -556,13 +564,14 @@
</object>
</object>
<int key="NSSelectedSegment">1</int>
<int key="NSSegmentStyle">2</int>
</object>
</object>
<nil key="NSToolbarItemImage"/>
<nil key="NSToolbarItemTarget"/>
<nil key="NSToolbarItemAction"/>
<string key="NSToolbarItemMinSize">{67, 24}</string>
<string key="NSToolbarItemMaxSize">{67, 24}</string>
<string key="NSToolbarItemMaxSize">{67, 25}</string>
<bool key="NSToolbarItemEnabled">YES</bool>
<bool key="NSToolbarItemAutovalidates">YES</bool>
<int key="NSToolbarItemTag">0</int>
@@ -681,52 +690,80 @@
<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
<string key="NSWindowContentMinSize">{340, 340}</string>
<object class="NSView" key="NSWindowView" id="455829030">
<nil key="NSNextResponder"/>
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSScrollView" id="417210994">
<object class="NSTextField" id="895966510">
<reference key="NSNextResponder" ref="455829030"/>
<int key="NSvFlags">290</int>
<string key="NSFrame">{{17, 6}, {523, 17}}</string>
<reference key="NSSuperview" ref="455829030"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="839278531">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">138412032</int>
<string key="NSContents">Marked: 0 files, 0 B. Total: 0 files, 0 B.</string>
<reference key="NSSupport" ref="594927229"/>
<reference key="NSControlView" ref="895966510"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor" id="713772391">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<reference key="NSTextColor" ref="1058073270"/>
</object>
</object>
<object class="NSScrollView" id="516888538">
<reference key="NSNextResponder" ref="455829030"/>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="948758365">
<reference key="NSNextResponder" ref="417210994"/>
<object class="NSClipView" id="657398517">
<reference key="NSNextResponder" ref="516888538"/>
<int key="NSvFlags">2304</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSOutlineView" id="40047569">
<reference key="NSNextResponder" ref="948758365"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{515, 317}</string>
<reference key="NSSuperview" ref="948758365"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTableHeaderView" key="NSHeaderView" id="837301452">
<reference key="NSNextResponder" ref="1000298166"/>
<object class="NSTableView" id="982695974">
<reference key="NSNextResponder" ref="657398517"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{515, 17}</string>
<reference key="NSSuperview" ref="1000298166"/>
<reference key="NSTableView" ref="40047569"/>
<string key="NSFrameSize">{557, 355}</string>
<reference key="NSSuperview" ref="657398517"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTableHeaderView" key="NSHeaderView" id="437229738">
<reference key="NSNextResponder" ref="1021759594"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{557, 17}</string>
<reference key="NSSuperview" ref="1021759594"/>
<reference key="NSTableView" ref="982695974"/>
</object>
<object class="_NSCornerView" key="NSCornerView" id="860570967">
<reference key="NSNextResponder" ref="417210994"/>
<object class="_NSCornerView" key="NSCornerView" id="622871751">
<reference key="NSNextResponder" ref="516888538"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{-26, 0}, {16, 17}}</string>
<reference key="NSSuperview" ref="417210994"/>
<string key="NSFrame">{{224, 0}, {16, 17}}</string>
<reference key="NSSuperview" ref="516888538"/>
</object>
<object class="NSMutableArray" key="NSTableColumns">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTableColumn" id="430098394">
<object class="NSTableColumn" id="201009225">
<string key="NSIdentifier">marked</string>
<double key="NSWidth">47</double>
<double key="NSMinWidth">16</double>
<double key="NSMaxWidth">1000</double>
<double key="NSWidth">26</double>
<double key="NSMinWidth">26</double>
<double key="NSMaxWidth">26</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
<int key="NSCellFlags2">134219776</int>
<string key="NSContents"/>
<reference key="NSSupport" ref="26"/>
<object class="NSColor" key="NSBackgroundColor">
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<object class="NSColor" key="NSBackgroundColor" id="589534335">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">headerColor</string>
@@ -739,64 +776,59 @@
<reference key="NSColor" ref="951662694"/>
</object>
</object>
<object class="NSButtonCell" key="NSDataCell" id="705360835">
<object class="NSButtonCell" key="NSDataCell" id="267036250">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">131072</int>
<string key="NSContents"/>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">12</double>
<int key="NSfFlags">16</int>
</object>
<reference key="NSControlView" ref="40047569"/>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="982695974"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<object class="NSCustomResource" key="NSNormalImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSSwitch</string>
</object>
<object class="NSButtonImageSource" key="NSAlternateImage">
<string key="NSImageName">NSSwitch</string>
</object>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
<int key="NSPeriodicInterval">75</int>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<bool key="NSIsEditable">YES</bool>
<reference key="NSTableView" ref="40047569"/>
<reference key="NSTableView" ref="982695974"/>
</object>
<object class="NSTableColumn" id="932540235">
<object class="NSTableColumn" id="146307356">
<string key="NSIdentifier">0</string>
<double key="NSWidth">195</double>
<double key="NSMinWidth">16</double>
<double key="NSMaxWidth">1000</double>
<double key="NSMaxWidth">3.4028234663852886e+38</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
<string key="NSContents">Name</string>
<reference key="NSSupport" ref="26"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
</object>
<reference key="NSBackgroundColor" ref="589534335"/>
<reference key="NSTextColor" ref="570076428"/>
</object>
<object class="NSTextFieldCell" key="NSDataCell" id="573658629">
<object class="NSTextFieldCell" key="NSDataCell" id="810890923">
<int key="NSCellFlags">337772096</int>
<int key="NSCellFlags2">2048</int>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="40047569"/>
<string key="NSContents">Text Cell</string>
<reference key="NSSupport" ref="473104458"/>
<reference key="NSControlView" ref="982695974"/>
<object class="NSColor" key="NSBackgroundColor" id="91259834">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlBackgroundColor</string>
<object class="NSColor" key="NSColor" id="713772391">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
<reference key="NSColor" ref="713772391"/>
</object>
<reference key="NSTextColor" ref="1058073270"/>
</object>
<int key="NSResizingMask">2</int>
<bool key="NSIsResizeable">YES</bool>
<reference key="NSTableView" ref="40047569"/>
<reference key="NSTableView" ref="982695974"/>
<object class="NSSortDescriptor" key="NSSortDescriptorPrototype">
<string key="NSKey">0</string>
<bool key="NSAscending">YES</bool>
@@ -821,86 +853,70 @@
<reference key="NSDelegate"/>
<reference key="NSDataSource"/>
<int key="NSGridStyleMask">2</int>
<int key="NSColumnAutoresizingStyle">0</int>
<int key="NSColumnAutoresizingStyle">4</int>
<int key="NSDraggingSourceMaskForLocal">15</int>
<int key="NSDraggingSourceMaskForNonLocal">0</int>
<bool key="NSAllowsTypeSelect">YES</bool>
<int key="NSTableViewDraggingDestinationStyle">0</int>
</object>
</object>
<string key="NSFrame">{{1, 17}, {515, 317}}</string>
<reference key="NSSuperview" ref="417210994"/>
<reference key="NSDocView" ref="40047569"/>
<string key="NSFrame">{{1, 17}, {557, 355}}</string>
<reference key="NSSuperview" ref="516888538"/>
<reference key="NSNextKeyView" ref="982695974"/>
<reference key="NSDocView" ref="982695974"/>
<reference key="NSBGColor" ref="91259834"/>
<int key="NScvFlags">4</int>
</object>
<object class="NSScroller" id="167459243">
<reference key="NSNextResponder" ref="417210994"/>
<object class="NSScroller" id="998740212">
<reference key="NSNextResponder" ref="516888538"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{-30, 17}, {15, 302}}</string>
<reference key="NSSuperview" ref="417210994"/>
<reference key="NSTarget" ref="417210994"/>
<string key="NSFrame">{{224, 17}, {15, 102}}</string>
<reference key="NSSuperview" ref="516888538"/>
<reference key="NSTarget" ref="516888538"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.98739492893218994</double>
<double key="NSCurValue">37</double>
<double key="NSPercent">0.1947367936372757</double>
</object>
<object class="NSScroller" id="916628114">
<reference key="NSNextResponder" ref="417210994"/>
<object class="NSScroller" id="752400791">
<reference key="NSNextResponder" ref="516888538"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{1, 319}, {515, 15}}</string>
<reference key="NSSuperview" ref="417210994"/>
<string key="NSFrame">{{1, 119}, {223, 15}}</string>
<reference key="NSSuperview" ref="516888538"/>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="417210994"/>
<reference key="NSTarget" ref="516888538"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.85406301824212272</double>
<double key="NSPercent">0.57142859697341919</double>
</object>
<object class="NSClipView" id="1000298166">
<reference key="NSNextResponder" ref="417210994"/>
<object class="NSClipView" id="1021759594">
<reference key="NSNextResponder" ref="516888538"/>
<int key="NSvFlags">2304</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="837301452"/>
<reference ref="437229738"/>
</object>
<string key="NSFrame">{{1, 0}, {515, 17}}</string>
<reference key="NSSuperview" ref="417210994"/>
<reference key="NSDocView" ref="837301452"/>
<string key="NSFrame">{{1, 0}, {557, 17}}</string>
<reference key="NSSuperview" ref="516888538"/>
<reference key="NSNextKeyView" ref="437229738"/>
<reference key="NSDocView" ref="437229738"/>
<reference key="NSBGColor" ref="91259834"/>
<int key="NScvFlags">4</int>
</object>
<reference ref="860570967"/>
<reference ref="622871751"/>
</object>
<string key="NSFrame">{{20, 45}, {517, 335}}</string>
<string key="NSFrame">{{0, 28}, {559, 373}}</string>
<reference key="NSSuperview" ref="455829030"/>
<reference key="NSNextKeyView" ref="657398517"/>
<int key="NSsFlags">562</int>
<reference key="NSVScroller" ref="167459243"/>
<reference key="NSHScroller" ref="916628114"/>
<reference key="NSContentView" ref="948758365"/>
<reference key="NSHeaderClipView" ref="1000298166"/>
<reference key="NSCornerView" ref="860570967"/>
<reference key="NSVScroller" ref="998740212"/>
<reference key="NSHScroller" ref="752400791"/>
<reference key="NSContentView" ref="657398517"/>
<reference key="NSHeaderClipView" ref="1021759594"/>
<reference key="NSCornerView" ref="622871751"/>
<bytes key="NSScrollAmts">QSAAAEEgAABBgAAAQYAAAA</bytes>
</object>
<object class="NSTextField" id="895966510">
<reference key="NSNextResponder" ref="455829030"/>
<int key="NSvFlags">290</int>
<string key="NSFrame">{{17, 20}, {523, 17}}</string>
<reference key="NSSuperview" ref="455829030"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="839278531">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">138412032</int>
<string key="NSContents">Marked: 0 files, 0 B. Total: 0 files, 0 B.</string>
<reference key="NSSupport" ref="594927229"/>
<reference key="NSControlView" ref="895966510"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<reference key="NSColor" ref="713772391"/>
</object>
<reference key="NSTextColor" ref="1058073270"/>
</object>
</object>
</object>
<string key="NSFrameSize">{557, 400}</string>
<reference key="NSSuperview"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
<string key="NSMinSize">{340, 418}</string>
@@ -1217,6 +1233,15 @@
<reference key="NSOnImage" ref="852972005"/>
<reference key="NSMixedImage" ref="218295580"/>
</object>
<object class="NSMenuItem" id="514384201">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Delete Marked and Replace with Hardlinks</string>
<string key="NSKeyEquiv">T</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852972005"/>
<reference key="NSMixedImage" ref="218295580"/>
</object>
<object class="NSMenuItem" id="207129050">
<reference key="NSMenu" ref="600111647"/>
<string key="NSTitle">Move Marked to...</string>
@@ -1713,14 +1738,6 @@
</object>
<int key="connectionID">212</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">initialFirstResponder</string>
<reference key="source" ref="641929189"/>
<reference key="destination" ref="40047569"/>
</object>
<int key="connectionID">279</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">stats</string>
@@ -1833,14 +1850,6 @@
</object>
<int key="connectionID">661</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">menu</string>
<reference key="source" ref="40047569"/>
<reference key="destination" ref="591769558"/>
</object>
<int key="connectionID">663</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">openSelected:</string>
@@ -2241,14 +2250,6 @@
</object>
<int key="connectionID">1175</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">matches</string>
<reference key="source" ref="339936126"/>
<reference key="destination" ref="40047569"/>
</object>
<int key="connectionID">1176</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">invokeCustomCommand:</string>
@@ -2273,6 +2274,38 @@
</object>
<int key="connectionID">1208</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">matches</string>
<reference key="source" ref="339936126"/>
<reference key="destination" ref="982695974"/>
</object>
<int key="connectionID">1225</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">menu</string>
<reference key="source" ref="982695974"/>
<reference key="destination" ref="591769558"/>
</object>
<int key="connectionID">1226</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hardlinkMarked:</string>
<reference key="source" ref="339936126"/>
<reference key="destination" ref="514384201"/>
</object>
<int key="connectionID">1229</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hardlinkMarked:</string>
<reference key="source" ref="339936126"/>
<reference key="destination" ref="103810273"/>
</object>
<int key="connectionID">1231</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -2317,56 +2350,11 @@
<reference key="object" ref="455829030"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="417210994"/>
<reference ref="895966510"/>
<reference ref="516888538"/>
</object>
<reference key="parent" ref="641929189"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">219</int>
<reference key="object" ref="417210994"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="40047569"/>
<reference ref="167459243"/>
<reference ref="916628114"/>
<reference ref="837301452"/>
</object>
<reference key="parent" ref="455829030"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">220</int>
<reference key="object" ref="40047569"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="932540235"/>
<reference ref="430098394"/>
</object>
<reference key="parent" ref="417210994"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">222</int>
<reference key="object" ref="932540235"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="573658629"/>
</object>
<reference key="parent" ref="40047569"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">406</int>
<reference key="object" ref="430098394"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="705360835"/>
</object>
<reference key="parent" ref="40047569"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">407</int>
<reference key="object" ref="705360835"/>
<reference key="parent" ref="430098394"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">291</int>
<reference key="object" ref="895966510"/>
@@ -2600,6 +2588,7 @@
<reference ref="564101661"/>
<reference ref="747820446"/>
<reference ref="517397504"/>
<reference ref="514384201"/>
</object>
<reference key="parent" ref="528113253"/>
</object>
@@ -2870,26 +2859,6 @@
<reference key="object" ref="839278531"/>
<reference key="parent" ref="895966510"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1140</int>
<reference key="object" ref="573658629"/>
<reference key="parent" ref="932540235"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1144</int>
<reference key="object" ref="167459243"/>
<reference key="parent" ref="417210994"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1145</int>
<reference key="object" ref="916628114"/>
<reference key="parent" ref="417210994"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1146</int>
<reference key="object" ref="837301452"/>
<reference key="parent" ref="417210994"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1147</int>
<reference key="object" ref="307721027"/>
@@ -2989,6 +2958,7 @@
<reference ref="707934795"/>
<reference ref="13829058"/>
<reference ref="698110866"/>
<reference ref="103810273"/>
</object>
<reference key="parent" ref="436420677"/>
</object>
@@ -3171,6 +3141,81 @@
<reference key="object" ref="630362403"/>
<reference key="parent" ref="948321368"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1209</int>
<reference key="object" ref="516888538"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="998740212"/>
<reference ref="752400791"/>
<reference ref="982695974"/>
<reference ref="437229738"/>
</object>
<reference key="parent" ref="455829030"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1210</int>
<reference key="object" ref="998740212"/>
<reference key="parent" ref="516888538"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1211</int>
<reference key="object" ref="752400791"/>
<reference key="parent" ref="516888538"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1212</int>
<reference key="object" ref="982695974"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="201009225"/>
<reference ref="146307356"/>
</object>
<reference key="parent" ref="516888538"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1213</int>
<reference key="object" ref="437229738"/>
<reference key="parent" ref="516888538"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1218</int>
<reference key="object" ref="201009225"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="267036250"/>
</object>
<reference key="parent" ref="982695974"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1222</int>
<reference key="object" ref="146307356"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="810890923"/>
</object>
<reference key="parent" ref="982695974"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1223</int>
<reference key="object" ref="810890923"/>
<reference key="parent" ref="146307356"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1224</int>
<reference key="object" ref="267036250"/>
<reference key="parent" ref="201009225"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1227</int>
<reference key="object" ref="514384201"/>
<reference key="parent" ref="600111647"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1230</int>
<reference key="object" ref="103810273"/>
<reference key="parent" ref="106411576"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -3205,14 +3250,6 @@
<string>1137.IBPluginDependency</string>
<string>1138.IBPluginDependency</string>
<string>1139.IBPluginDependency</string>
<string>1140.IBPluginDependency</string>
<string>1140.IBShouldRemoveOnLegacySave</string>
<string>1144.IBPluginDependency</string>
<string>1144.IBShouldRemoveOnLegacySave</string>
<string>1145.IBPluginDependency</string>
<string>1145.IBShouldRemoveOnLegacySave</string>
<string>1146.IBPluginDependency</string>
<string>1146.IBShouldRemoveOnLegacySave</string>
<string>1147.IBEditorWindowLastContentRect</string>
<string>1147.IBPluginDependency</string>
<string>1156.IBPluginDependency</string>
@@ -3229,6 +3266,20 @@
<string>1204.IBPluginDependency</string>
<string>1205.IBPluginDependency</string>
<string>1206.IBPluginDependency</string>
<string>1209.IBPluginDependency</string>
<string>1210.IBPluginDependency</string>
<string>1211.IBPluginDependency</string>
<string>1212.CustomClassName</string>
<string>1212.IBPluginDependency</string>
<string>1213.IBPluginDependency</string>
<string>1218.IBPluginDependency</string>
<string>1222.IBPluginDependency</string>
<string>1223.IBPluginDependency</string>
<string>1224.IBPluginDependency</string>
<string>1227.IBPluginDependency</string>
<string>1227.ImportedFromIB2</string>
<string>1230.IBPluginDependency</string>
<string>1230.ImportedFromIB2</string>
<string>134.IBPluginDependency</string>
<string>134.ImportedFromIB2</string>
<string>136.IBPluginDependency</string>
@@ -3256,13 +3307,6 @@
<string>21.NSWindowTemplate.visibleAtLaunch</string>
<string>21.windowTemplate.hasMinSize</string>
<string>21.windowTemplate.minSize</string>
<string>219.IBPluginDependency</string>
<string>219.ImportedFromIB2</string>
<string>220.CustomClassName</string>
<string>220.IBPluginDependency</string>
<string>220.ImportedFromIB2</string>
<string>222.IBPluginDependency</string>
<string>222.ImportedFromIB2</string>
<string>23.IBPluginDependency</string>
<string>23.ImportedFromIB2</string>
<string>24.IBEditorWindowLastContentRect</string>
@@ -3277,10 +3321,6 @@
<string>398.ImportedFromIB2</string>
<string>399.IBPluginDependency</string>
<string>399.ImportedFromIB2</string>
<string>406.IBPluginDependency</string>
<string>406.ImportedFromIB2</string>
<string>407.IBPluginDependency</string>
<string>407.ImportedFromIB2</string>
<string>497.ImportedFromIB2</string>
<string>5.IBPluginDependency</string>
<string>5.ImportedFromIB2</string>
@@ -3452,15 +3492,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{409, 745}, {617, 0}}</string>
<string>{{294, 462}, {617, 227}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3477,6 +3509,18 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>HSTableView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -3494,24 +3538,19 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{{439, 345}, {557, 400}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{439, 345}, {557, 400}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{{324, 289}, {557, 400}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{324, 289}, {557, 400}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{340, 340}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>HSOutlineView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{531, 625}, {193, 143}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -3524,10 +3563,6 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -3546,7 +3581,7 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{328, 475}, {361, 293}}</string>
<string>{{328, 455}, {383, 313}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3586,7 +3621,7 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{94, 408}, {331, 243}}</string>
<string>{{310, 310}, {353, 263}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3686,7 +3721,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">1208</int>
<int key="maxID">1231</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -3863,16 +3898,23 @@
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">HSOutlineView</string>
<string key="superclassName">NSOutlineView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="384069338">
<string key="className">HSTableView</string>
<string key="superclassName">NSTableView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="1040579274">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSTableView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<reference key="sourceIdentifier" ref="384069338"/>
<reference key="sourceIdentifier" ref="1040579274"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
@@ -4075,6 +4117,7 @@
<string>deleteMarked:</string>
<string>exportToXHTML:</string>
<string>filter:</string>
<string>hardlinkMarked:</string>
<string>ignoreSelected:</string>
<string>invokeCustomCommand:</string>
<string>loadResults:</string>
@@ -4131,6 +4174,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
@@ -4144,6 +4188,7 @@
<string>deleteMarked:</string>
<string>exportToXHTML:</string>
<string>filter:</string>
<string>hardlinkMarked:</string>
<string>ignoreSelected:</string>
<string>invokeCustomCommand:</string>
<string>loadResults:</string>
@@ -4198,6 +4243,10 @@
<string key="name">filter:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">hardlinkMarked:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">ignoreSelected:</string>
<string key="candidateClassName">id</string>
@@ -4311,7 +4360,7 @@
<string>NSMenu</string>
<string>NSSegmentedControl</string>
<string>NSSearchField</string>
<string>HSOutlineView</string>
<string>HSTableView</string>
<string>NSSegmentedControl</string>
<string>PyDupeGuruBase</string>
<string>NSTextField</string>
@@ -4350,7 +4399,7 @@
</object>
<object class="IBToOneOutletInfo">
<string key="name">matches</string>
<string key="candidateClassName">HSOutlineView</string>
<string key="candidateClassName">HSTableView</string>
</object>
<object class="IBToOneOutletInfo">
<string key="name">pmSwitch</string>
@@ -4576,7 +4625,7 @@
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="444201337">
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string>
</object>
@@ -4763,11 +4812,6 @@
<string key="minorKey">Sparkle.framework/Headers/SUUpdater.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSOutlineView</string>
<string key="superclassName">NSTableView</string>
<reference key="sourceIdentifier" ref="444201337"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSPopUpButton</string>
<string key="superclassName">NSButton</string>
@@ -5023,6 +5067,7 @@
<string>NSApplicationIcon</string>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
<string>NSSwitch</string>
<string>details32</string>
<string>folder32</string>
<string>preferences32</string>
@@ -5033,6 +5078,7 @@
<string>{128, 128}</string>
<string>{9, 8}</string>
<string>{7, 2}</string>
<string>{15, 15}</string>
<string>{48, 48}</string>
<string>{32, 32}</string>
<string>{32, 32}</string>

View File

@@ -28,6 +28,7 @@ http://www.hardcoded.net/licenses/hs_license
[d setObject:b2n(NO) forKey:@"matchSimilarWords"];
[d setObject:b2n(YES) forKey:@"mixFileKind"];
[d setObject:b2n(NO) forKey:@"useRegexpFilter"];
[d setObject:b2n(NO) forKey:@"ignoreHardlinkMatches"];
[d setObject:b2n(NO) forKey:@"removeEmptyFolders"];
[d setObject:b2n(NO) forKey:@"debug"];
[d setObject:b2n(NO) forKey:@"scanTagTrack"];

View File

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

View File

@@ -22,7 +22,7 @@ http://www.hardcoded.net/licenses/hs_license
[[self window] setTitle:@"dupeGuru Music Edition"];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(2,6)];
[deltaColumns removeIndex:6];
[outline setDeltaColumns:deltaColumns];
[table setDeltaColumns:deltaColumns];
}
/* Actions */
@@ -38,12 +38,14 @@ http://www.hardcoded.net/licenses/hs_license
[columnsOrder addObject:@"2"];
[columnsOrder addObject:@"3"];
[columnsOrder addObject:@"4"];
[columnsOrder addObject:@"6"];
[columnsOrder addObject:@"15"];
NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary];
[columnsWidth setObject:i2n(214) forKey:@"0"];
[columnsWidth setObject:i2n(235) forKey:@"0"];
[columnsWidth setObject:i2n(63) forKey:@"2"];
[columnsWidth setObject:i2n(50) forKey:@"3"];
[columnsWidth setObject:i2n(50) forKey:@"4"];
[columnsWidth setObject:i2n(40) forKey:@"6"];
[columnsWidth setObject:i2n(57) forKey:@"15"];
[self restoreColumnsPosition:columnsOrder widths:columnsWidth];
}
@@ -66,7 +68,8 @@ http://www.hardcoded.net/licenses/hs_license
[_py enable:[ud objectForKey:@"scanTagYear"] scanForTag:@"year"];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:[ud objectForKey:@"mixFileKind"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
NSInteger r = n2i([py doScan]);
if (r == 3)

View File

@@ -33,7 +33,6 @@
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0BFF1175A1C000DCA3C6 /* HSTable.m */; };
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */; };
CE0A0C061175A24800DCA3C6 /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */; };
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B3D6611243F83009A7A30 /* ResultOutline.m */; };
CE1425890AFB718500BD5167 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
CE14259F0AFB719300BD5167 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE1425880AFB718500BD5167 /* Sparkle.framework */; };
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
@@ -54,12 +53,14 @@
CE515E1D0FC6C19300EC695D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515E160FC6C19300EC695D /* AppDelegate.m */; };
CE515E1E0FC6C19300EC695D /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515E190FC6C19300EC695D /* DirectoryPanel.m */; };
CE515E1F0FC6C19300EC695D /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE515E1C0FC6C19300EC695D /* ResultWindow.m */; };
CE578303124DFC660004769C /* HSTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE578302124DFC660004769C /* HSTableView.m */; };
CE6032C00FE6784C007E33FF /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6032BF0FE6784C007E33FF /* DetailsPanel.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 */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CE900AD2109B238600754048 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD1109B238600754048 /* Preferences.xib */; };
CE900AD7109B2A9B00754048 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE900AD6109B2A9B00754048 /* MainMenu.xib */; };
CEB14D29124DFC2800FA7481 /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CEB14D28124DFC2800FA7481 /* ResultTable.m */; };
CECC563B12144A9000ABF262 /* registration.xib in Resources */ = {isa = PBXBuildFile; fileRef = CECC563912144A9000ABF262 /* registration.xib */; };
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CEDF07A2112493B200EE5BC0 /* StatsLabel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
@@ -118,9 +119,6 @@
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE0A0C051175A24800DCA3C6 /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE0A0C131175A28100DCA3C6 /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE0B3D6411243F83009A7A30 /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE0B3D6511243F83009A7A30 /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE0B3D6611243F83009A7A30 /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
CE1425880AFB718500BD5167 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
CE381C9509914ACE003581CE /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
@@ -156,6 +154,8 @@
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDupeGuru.h; path = ../base/PyDupeGuru.h; sourceTree = SOURCE_ROOT; };
CE515E1B0FC6C19300EC695D /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultWindow.h; path = ../base/ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE515E1C0FC6C19300EC695D /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultWindow.m; path = ../base/ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE578301124DFC660004769C /* HSTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSTableView.h; path = ../../cocoalib/views/HSTableView.h; sourceTree = SOURCE_ROOT; };
CE578302124DFC660004769C /* HSTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSTableView.m; path = ../../cocoalib/views/HSTableView.m; sourceTree = SOURCE_ROOT; };
CE6032BE0FE6784C007E33FF /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = ../base/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE6032BF0FE6784C007E33FF /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DetailsPanel.m; path = ../base/DetailsPanel.m; sourceTree = SOURCE_ROOT; };
CE68EE6509ABC48000971085 /* DirectoryPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DirectoryPanel.h; sourceTree = SOURCE_ROOT; };
@@ -164,6 +164,9 @@
CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE900AD1109B238600754048 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
CE900AD6109B2A9B00754048 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = "<group>"; };
CEB14D26124DFC2800FA7481 /* PyResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTable.h; path = ../base/PyResultTable.h; sourceTree = SOURCE_ROOT; };
CEB14D27124DFC2800FA7481 /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CEB14D28124DFC2800FA7481 /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; sourceTree = SOURCE_ROOT; };
CECC563A12144A9000ABF262 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../../cocoalib/en.lproj/registration.xib; sourceTree = SOURCE_ROOT; };
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
@@ -306,6 +309,8 @@
CE003CBF11242D00004B0AA7 /* views */ = {
isa = PBXGroup;
children = (
CE578301124DFC660004769C /* HSTableView.h */,
CE578302124DFC660004769C /* HSTableView.m */,
CE003CC011242D00004B0AA7 /* HSOutlineView.h */,
CE003CC111242D00004B0AA7 /* HSOutlineView.m */,
CE003CC211242D00004B0AA7 /* NSIndexPathAdditions.h */,
@@ -383,6 +388,9 @@
CE515E140FC6C17900EC695D /* dgbase */ = {
isa = PBXGroup;
children = (
CEB14D26124DFC2800FA7481 /* PyResultTable.h */,
CEB14D27124DFC2800FA7481 /* ResultTable.h */,
CEB14D28124DFC2800FA7481 /* ResultTable.m */,
CE003CCD11242D2C004B0AA7 /* DirectoryOutline.h */,
CE003CCE11242D2C004B0AA7 /* DirectoryOutline.m */,
CE003CCF11242D2C004B0AA7 /* PyDirectoryOutline.h */,
@@ -397,14 +405,11 @@
CE0A0C021175A1DE00DCA3C6 /* ProblemDialog.m */,
CE515E1B0FC6C19300EC695D /* ResultWindow.h */,
CE515E1C0FC6C19300EC695D /* ResultWindow.m */,
CE0B3D6511243F83009A7A30 /* ResultOutline.h */,
CE0B3D6611243F83009A7A30 /* ResultOutline.m */,
CEDF07A1112493B200EE5BC0 /* StatsLabel.h */,
CEDF07A2112493B200EE5BC0 /* StatsLabel.m */,
CE515E1A0FC6C19300EC695D /* PyDupeGuru.h */,
CED0A591111C9FD10020AD7D /* PyDetailsPanel.h */,
CE0A0C031175A1DE00DCA3C6 /* PyProblemDialog.h */,
CE0B3D6411243F83009A7A30 /* PyResultTree.h */,
CEDF07A0112493B200EE5BC0 /* PyStatsLabel.h */,
);
name = dgbase;
@@ -521,10 +526,11 @@
CE003CCB11242D00004B0AA7 /* NSIndexPathAdditions.m in Sources */,
CE003CCC11242D00004B0AA7 /* NSTableViewAdditions.m in Sources */,
CE003CD011242D2C004B0AA7 /* DirectoryOutline.m in Sources */,
CE0B3D6711243F83009A7A30 /* ResultOutline.m in Sources */,
CEDF07A3112493B200EE5BC0 /* StatsLabel.m in Sources */,
CE0A0C001175A1C000DCA3C6 /* HSTable.m in Sources */,
CE0A0C041175A1DE00DCA3C6 /* ProblemDialog.m in Sources */,
CEB14D29124DFC2800FA7481 /* ResultTable.m in Sources */,
CE578303124DFC660004769C /* HSTableView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string>
<string key="NS.object.0">788</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -41,7 +41,7 @@
<object class="NSUserDefaultsController" id="579641073">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>CustomCommand</string>
<string>ignoreHardlinkMatches</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
@@ -698,7 +698,7 @@
<object class="NSTextField" id="519483808">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 192}, {85, 13}}</string>
<string key="NSFrame">{{14, 172}, {85, 13}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="142188233">
@@ -714,7 +714,7 @@
<object class="NSTextField" id="839713145">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 164}, {324, 17}}</string>
<string key="NSFrame">{{14, 144}, {324, 17}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="380716547">
@@ -730,7 +730,7 @@
<object class="NSPopUpButton" id="1046542754">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{104, 185}, {234, 26}}</string>
<string key="NSFrame">{{104, 165}, {234, 26}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="923770094">
@@ -800,7 +800,7 @@
<object class="NSTextField" id="330569030">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 142}, {326, 22}}</string>
<string key="NSFrame">{{17, 122}, {326, 22}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="573680954">
@@ -827,6 +827,27 @@
</object>
</object>
</object>
<object class="NSButton" id="1065764374">
<reference key="NSNextResponder" ref="76055040"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 195}, {265, 18}}</string>
<reference key="NSSuperview" ref="76055040"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="621426332">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Ignore duplicates hardlinking to the same file</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="1065764374"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="150447483"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {360, 234}}</string>
</object>
@@ -1461,6 +1482,22 @@
</object>
<int key="connectionID">124</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.ignoreHardlinkMatches</string>
<reference key="source" ref="1065764374"/>
<reference key="destination" ref="579641073"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="1065764374"/>
<reference key="NSDestination" ref="579641073"/>
<string key="NSLabel">value: values.ignoreHardlinkMatches</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.ignoreHardlinkMatches</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">128</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -1563,9 +1600,10 @@
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="836095588"/>
<reference ref="1046542754"/>
<reference ref="1065764374"/>
<reference ref="519483808"/>
<reference ref="839713145"/>
<reference ref="1046542754"/>
<reference ref="330569030"/>
</object>
<reference key="parent" ref="963172262"/>
@@ -2020,6 +2058,20 @@
<reference key="object" ref="573680954"/>
<reference key="parent" ref="330569030"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">125</int>
<reference key="object" ref="1065764374"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="621426332"/>
</object>
<reference key="parent" ref="76055040"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">126</int>
<reference key="object" ref="621426332"/>
<reference key="parent" ref="1065764374"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -2045,6 +2097,9 @@
<string>121.IBPluginDependency</string>
<string>122.IBPluginDependency</string>
<string>123.IBPluginDependency</string>
<string>125.IBPluginDependency</string>
<string>125.ImportedFromIB2</string>
<string>126.IBPluginDependency</string>
<string>13.IBPluginDependency</string>
<string>13.ImportedFromIB2</string>
<string>14.IBPluginDependency</string>
@@ -2165,6 +2220,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
@@ -2174,9 +2232,9 @@
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{318, 425}, {406, 326}}</string>
<string>{{555, 271}, {406, 326}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{318, 425}, {406, 326}}</string>
<string>{{555, 271}, {406, 326}}</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{213, 107}</string>
@@ -2275,7 +2333,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">124</int>
<int key="maxID">128</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -2825,6 +2883,13 @@
<string key="NS.key.0">showWindow:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">showWindow:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">showWindow:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string>
@@ -2833,6 +2898,7 @@
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<integer value="1050" key="NS.object.0"/>
@@ -2844,5 +2910,18 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../dupeguru.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>{9, 8}</string>
<string>{7, 2}</string>
</object>
</object>
</data>
</archive>

View File

@@ -25,6 +25,7 @@ http://www.hardcoded.net/licenses/hs_license
[d setObject:[NSNumber numberWithBool:NO] forKey:@"matchScaled"];
[d setObject:[NSNumber numberWithBool:YES] forKey:@"mixFileKind"];
[d setObject:[NSNumber numberWithBool:NO] forKey:@"useRegexpFilter"];
[d setObject:[NSNumber numberWithBool:NO] forKey:@"ignoreHardlinkMatches"];
[d setObject:[NSNumber numberWithBool:NO] forKey:@"removeEmptyFolders"];
[d setObject:[NSNumber numberWithBool:NO] forKey:@"debug"];
[d setObject:[NSArray array] forKey:@"recentDirectories"];

View File

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

View File

@@ -22,7 +22,7 @@ http://www.hardcoded.net/licenses/hs_license
[[self window] setTitle:@"dupeGuru Picture Edition"];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
[deltaColumns addIndex:5];
[outline setDeltaColumns:deltaColumns];
[table setDeltaColumns:deltaColumns];
}
/* Actions */
@@ -42,8 +42,8 @@ http://www.hardcoded.net/licenses/hs_license
[columnsOrder addObject:@"4"];
[columnsOrder addObject:@"6"];
NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary];
[columnsWidth setObject:i2n(121) forKey:@"0"];
[columnsWidth setObject:i2n(120) forKey:@"1"];
[columnsWidth setObject:i2n(162) forKey:@"0"];
[columnsWidth setObject:i2n(142) forKey:@"1"];
[columnsWidth setObject:i2n(63) forKey:@"2"];
[columnsWidth setObject:i2n(73) forKey:@"4"];
[columnsWidth setObject:i2n(58) forKey:@"6"];
@@ -60,7 +60,8 @@ http://www.hardcoded.net/licenses/hs_license
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
PyDupeGuru *_py = (PyDupeGuru *)py;
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setMixFileKind:[ud objectForKey:@"mixFileKind"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchScaled:[ud objectForKey:@"matchScaled"]];
int r = n2i([py doScan]);
if (r != 0)

View File

@@ -41,7 +41,6 @@
CE80DB8C0FC1951C0086DCA6 /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE80DB890FC1951C0086DCA6 /* ResultWindow.m */; };
CE848A1909DD85810004CB44 /* Consts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE848A1809DD85810004CB44 /* Consts.h */; };
CE895D7B12144A7800E74705 /* registration.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE895D7912144A7800E74705 /* registration.xib */; };
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE95865B112C516400F95FD2 /* ResultOutline.m */; };
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE95865D112C516400F95FD2 /* StatsLabel.m */; };
CE9EA7561122C96C008CD2BC /* HSGUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7441122C96C008CD2BC /* HSGUIController.m */; };
CE9EA7571122C96C008CD2BC /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA7461122C96C008CD2BC /* HSOutline.m */; };
@@ -55,6 +54,8 @@
CECA899C09DB132E00A3D774 /* DetailsPanel.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CECA899A09DB132E00A3D774 /* DetailsPanel.h */; };
CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CECA899B09DB132E00A3D774 /* DetailsPanel.m */; };
CEEB135209C837A2004D2330 /* dupeguru.icns in Resources */ = {isa = PBXBuildFile; fileRef = CEEB135109C837A2004D2330 /* dupeguru.icns */; };
CEF12A7E124DFD400087B51D /* HSTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF12A7D124DFD400087B51D /* HSTableView.m */; };
CEF12A84124DFD620087B51D /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF12A83124DFD620087B51D /* ResultTable.m */; };
CEFC294609C89E3D00D9F998 /* folder32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC294509C89E3D00D9F998 /* folder32.png */; };
CEFC295509C89FF200D9F998 /* details32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295309C89FF200D9F998 /* details32.png */; };
CEFC295609C89FF200D9F998 /* preferences32.png in Resources */ = {isa = PBXBuildFile; fileRef = CEFC295409C89FF200D9F998 /* preferences32.png */; };
@@ -139,10 +140,7 @@
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultWindow.m; path = ../base/ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE848A1809DD85810004CB44 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = "<group>"; };
CE895D7A12144A7800E74705 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = ../../cocoalib/en.lproj/registration.xib; sourceTree = SOURCE_ROOT; };
CE958658112C516400F95FD2 /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE958659112C516400F95FD2 /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CE95865A112C516400F95FD2 /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE95865B112C516400F95FD2 /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
CE95865C112C516400F95FD2 /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
CE95865D112C516400F95FD2 /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CE9EA7431122C96C008CD2BC /* HSGUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSGUIController.h; sourceTree = "<group>"; };
@@ -170,6 +168,11 @@
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>"; };
CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = "<group>"; };
CEF12A7C124DFD400087B51D /* HSTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSTableView.h; path = ../../cocoalib/views/HSTableView.h; sourceTree = SOURCE_ROOT; };
CEF12A7D124DFD400087B51D /* HSTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSTableView.m; path = ../../cocoalib/views/HSTableView.m; sourceTree = SOURCE_ROOT; };
CEF12A81124DFD620087B51D /* PyResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTable.h; path = ../base/PyResultTable.h; sourceTree = SOURCE_ROOT; };
CEF12A82124DFD620087B51D /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CEF12A83124DFD620087B51D /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; 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; };
CEFC295409C89FF200D9F998 /* preferences32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = preferences32.png; path = ../../images/preferences32.png; sourceTree = SOURCE_ROOT; };
@@ -339,6 +342,9 @@
CE80DB810FC194BD0086DCA6 /* dgbase */ = {
isa = PBXGroup;
children = (
CEF12A81124DFD620087B51D /* PyResultTable.h */,
CEF12A82124DFD620087B51D /* ResultTable.h */,
CEF12A83124DFD620087B51D /* ResultTable.m */,
CE80DB820FC1951C0086DCA6 /* AppDelegate.h */,
CE80DB830FC1951C0086DCA6 /* AppDelegate.m */,
CE80DB840FC1951C0086DCA6 /* Consts.h */,
@@ -352,9 +358,6 @@
CE0C2ABB1177014200BC749F /* ProblemDialog.m */,
CE80DB880FC1951C0086DCA6 /* ResultWindow.h */,
CE80DB890FC1951C0086DCA6 /* ResultWindow.m */,
CE958658112C516400F95FD2 /* PyResultTree.h */,
CE95865A112C516400F95FD2 /* ResultOutline.h */,
CE95865B112C516400F95FD2 /* ResultOutline.m */,
CE95865C112C516400F95FD2 /* StatsLabel.h */,
CE95865D112C516400F95FD2 /* StatsLabel.m */,
CE80DB870FC1951C0086DCA6 /* PyDupeGuru.h */,
@@ -396,6 +399,8 @@
CE9EA74F1122C96C008CD2BC /* views */ = {
isa = PBXGroup;
children = (
CEF12A7C124DFD400087B51D /* HSTableView.h */,
CEF12A7D124DFD400087B51D /* HSTableView.m */,
CE9EA7501122C96C008CD2BC /* HSOutlineView.h */,
CE9EA7511122C96C008CD2BC /* HSOutlineView.m */,
CE9EA7521122C96C008CD2BC /* NSIndexPathAdditions.h */,
@@ -532,10 +537,11 @@
CE9EA75B1122C96C008CD2BC /* NSIndexPathAdditions.m in Sources */,
CE9EA75C1122C96C008CD2BC /* NSTableViewAdditions.m in Sources */,
CE9EA7721122CA0B008CD2BC /* DirectoryOutline.m in Sources */,
CE95865E112C516400F95FD2 /* ResultOutline.m in Sources */,
CE95865F112C516400F95FD2 /* StatsLabel.m in Sources */,
CE0C2AB61177011000BC749F /* HSTable.m in Sources */,
CE0C2ABD1177014200BC749F /* ProblemDialog.m in Sources */,
CEF12A7E124DFD400087B51D /* HSTableView.m in Sources */,
CEF12A84124DFD620087B51D /* ResultTable.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string>
<string key="NS.object.0">788</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -41,7 +41,7 @@
<object class="NSUserDefaultsController" id="455472712">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>CustomCommand</string>
<string>ignoreHardlinkMatches</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
@@ -406,10 +406,31 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSButton" id="519470955">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 100}, {265, 18}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="595497720">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Ignore duplicates hardlinking to the same file</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="519470955"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="990345653"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSTextField" id="748076392">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 97}, {85, 13}}</string>
<string key="NSFrame">{{14, 77}, {85, 13}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="936873031">
@@ -425,7 +446,7 @@
<object class="NSTextField" id="526155835">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 69}, {306, 17}}</string>
<string key="NSFrame">{{14, 49}, {306, 17}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="765798142">
@@ -441,7 +462,7 @@
<object class="NSPopUpButton" id="724953200">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{104, 90}, {216, 26}}</string>
<string key="NSFrame">{{104, 70}, {216, 26}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="601288025">
@@ -517,7 +538,7 @@
<object class="NSTextField" id="590530357">
<reference key="NSNextResponder" ref="581039403"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 47}, {312, 22}}</string>
<string key="NSFrame">{{17, 27}, {312, 22}}</string>
<reference key="NSSuperview" ref="581039403"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="922246764">
@@ -790,6 +811,30 @@
</object>
<int key="connectionID">68</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">nextKeyView</string>
<reference key="source" ref="519470955"/>
<reference key="destination" ref="279087998"/>
</object>
<int key="connectionID">72</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.ignoreHardlinkMatches</string>
<reference key="source" ref="519470955"/>
<reference key="destination" ref="455472712"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="519470955"/>
<reference key="NSDestination" ref="455472712"/>
<string key="NSLabel">value: values.ignoreHardlinkMatches</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.ignoreHardlinkMatches</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">73</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -892,9 +937,10 @@
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="1018598123"/>
<reference ref="724953200"/>
<reference ref="519470955"/>
<reference ref="748076392"/>
<reference ref="526155835"/>
<reference ref="724953200"/>
<reference ref="590530357"/>
</object>
<reference key="parent" ref="1045400351"/>
@@ -1151,6 +1197,20 @@
<reference key="object" ref="922246764"/>
<reference key="parent" ref="590530357"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">69</int>
<reference key="object" ref="519470955"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="595497720"/>
</object>
<reference key="parent" ref="581039403"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">70</int>
<reference key="object" ref="595497720"/>
<reference key="parent" ref="519470955"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -1221,8 +1281,11 @@
<string>65.IBPluginDependency</string>
<string>66.IBPluginDependency</string>
<string>67.IBPluginDependency</string>
<string>69.IBPluginDependency</string>
<string>69.ImportedFromIB2</string>
<string>7.IBPluginDependency</string>
<string>7.ImportedFromIB2</string>
<string>70.IBPluginDependency</string>
<string>8.IBPluginDependency</string>
<string>8.ImportedFromIB2</string>
<string>9.IBPluginDependency</string>
@@ -1299,6 +1362,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
</object>
</object>
@@ -1318,7 +1384,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">68</int>
<int key="maxID">73</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -1330,6 +1396,13 @@
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSTableView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -1868,6 +1941,13 @@
<string key="NS.key.0">showWindow:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">showWindow:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">showWindow:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string>
@@ -1876,6 +1956,7 @@
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<integer value="1050" key="NS.object.0"/>
@@ -1887,5 +1968,18 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../dupeguru.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>{9, 8}</string>
<string>{7, 2}</string>
</object>
</object>
</data>
</archive>

View File

@@ -28,6 +28,7 @@ http://www.hardcoded.net/licenses/hs_license
[d setObject:b2n(NO) forKey:@"matchSimilarWords"];
[d setObject:b2n(YES) forKey:@"mixFileKind"];
[d setObject:b2n(NO) forKey:@"useRegexpFilter"];
[d setObject:b2n(NO) forKey:@"ignoreHardlinkMatches"];
[d setObject:b2n(NO) forKey:@"removeEmptyFolders"];
[d setObject:b2n(YES) forKey:@"ignoreSmallFiles"];
[d setObject:b2n(NO) forKey:@"debug"];

View File

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

View File

@@ -20,7 +20,7 @@ http://www.hardcoded.net/licenses/hs_license
[super awakeFromNib];
NSMutableIndexSet *deltaColumns = [NSMutableIndexSet indexSetWithIndex:2];
[deltaColumns addIndex:4];
[outline setDeltaColumns:deltaColumns];
[table setDeltaColumns:deltaColumns];
}
/* Actions */
@@ -33,7 +33,7 @@ http://www.hardcoded.net/licenses/hs_license
[columnsOrder addObject:@"5"];
NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary];
[columnsWidth setObject:i2n(195) forKey:@"0"];
[columnsWidth setObject:i2n(120) forKey:@"1"];
[columnsWidth setObject:i2n(183) forKey:@"1"];
[columnsWidth setObject:i2n(63) forKey:@"2"];
[columnsWidth setObject:i2n(60) forKey:@"5"];
[self restoreColumnsPosition:columnsOrder widths:columnsWidth];
@@ -51,7 +51,8 @@ http://www.hardcoded.net/licenses/hs_license
[_py setScanType:[ud objectForKey:@"scanType"]];
[_py setMinMatchPercentage:[ud objectForKey:@"minMatchPercentage"]];
[_py setWordWeighting:[ud objectForKey:@"wordWeighting"]];
[_py setMixFileKind:[ud objectForKey:@"mixFileKind"]];
[_py setMixFileKind:n2b([ud objectForKey:@"mixFileKind"])];
[_py setIgnoreHardlinkMatches:n2b([ud objectForKey:@"ignoreHardlinkMatches"])];
[_py setMatchSimilarWords:[ud objectForKey:@"matchSimilarWords"]];
int smallFileThreshold = [ud integerForKey:@"smallFileThreshold"]; // In KB
int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes

View File

@@ -20,6 +20,8 @@
CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE647E551173024A006D28BA /* ProblemDialog.m */; };
CE647E591173026F006D28BA /* ProblemDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE647E581173026F006D28BA /* ProblemDialog.xib */; };
CE6DD4E7124CA3070089A48D /* ResultTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6DD4E6124CA3070089A48D /* ResultTable.m */; };
CE6DD547124CAF1F0089A48D /* HSTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6DD546124CAF1F0089A48D /* HSTableView.m */; };
CE6E0DFE1054E9EF008D9390 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */; };
CE76FDC4111EE37C006618EA /* HSOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDBF111EE37C006618EA /* HSOutlineView.m */; };
CE76FDC5111EE37C006618EA /* NSIndexPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDC1111EE37C006618EA /* NSIndexPathAdditions.m */; };
@@ -29,7 +31,6 @@
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDDE111EE42F006618EA /* HSOutline.m */; };
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CE76FDF6111EE561006618EA /* NSEventAdditions.m */; };
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */ = {isa = PBXBuildFile; fileRef = CE8C53BB117324CE0011B41F /* HSTable.m */; };
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91F212113BC22D0010360B /* ResultOutline.m */; };
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91F214113BC22D0010360B /* StatsLabel.m */; };
CEAC6811109B0B7E00B43C85 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEAC6810109B0B7E00B43C85 /* Preferences.xib */; };
CEBC6C3912144A4B007B43AE /* registration.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEBC6C3712144A4B007B43AE /* registration.xib */; };
@@ -89,6 +90,11 @@
CE647E551173024A006D28BA /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
CE647E561173024A006D28BA /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E581173026F006D28BA /* ProblemDialog.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ProblemDialog.xib; path = ../base/xib/ProblemDialog.xib; sourceTree = SOURCE_ROOT; };
CE6DD4E4124CA3070089A48D /* PyResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTable.h; path = ../base/PyResultTable.h; sourceTree = SOURCE_ROOT; };
CE6DD4E5124CA3070089A48D /* ResultTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultTable.h; path = ../base/ResultTable.h; sourceTree = SOURCE_ROOT; };
CE6DD4E6124CA3070089A48D /* ResultTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultTable.m; path = ../base/ResultTable.m; sourceTree = SOURCE_ROOT; };
CE6DD545124CAF1F0089A48D /* HSTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSTableView.h; path = ../../cocoalib/views/HSTableView.h; sourceTree = SOURCE_ROOT; };
CE6DD546124CAF1F0089A48D /* HSTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSTableView.m; path = ../../cocoalib/views/HSTableView.m; sourceTree = SOURCE_ROOT; };
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dsa_pub.pem; path = ../base/dsa_pub.pem; sourceTree = "<group>"; };
CE6E7407111C997500C350E3 /* PyDetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyDetailsPanel.h; path = ../base/PyDetailsPanel.h; sourceTree = SOURCE_ROOT; };
CE76FDBE111EE37C006618EA /* HSOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSOutlineView.h; sourceTree = "<group>"; };
@@ -110,10 +116,7 @@
CE76FDF6111EE561006618EA /* NSEventAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSEventAdditions.m; path = ../../cocoalib/NSEventAdditions.m; sourceTree = SOURCE_ROOT; };
CE8C53B61173248F0011B41F /* PyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyTable.h; sourceTree = "<group>"; };
CE8C53BB117324CE0011B41F /* HSTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSTable.m; sourceTree = "<group>"; };
CE91F20F113BC22D0010360B /* PyResultTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyResultTree.h; path = ../base/PyResultTree.h; sourceTree = SOURCE_ROOT; };
CE91F210113BC22D0010360B /* PyStatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyStatsLabel.h; path = ../base/PyStatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F211113BC22D0010360B /* ResultOutline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResultOutline.h; path = ../base/ResultOutline.h; sourceTree = SOURCE_ROOT; };
CE91F212113BC22D0010360B /* ResultOutline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ResultOutline.m; path = ../base/ResultOutline.m; sourceTree = SOURCE_ROOT; };
CE91F213113BC22D0010360B /* StatsLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatsLabel.h; path = ../base/StatsLabel.h; sourceTree = SOURCE_ROOT; };
CE91F214113BC22D0010360B /* StatsLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatsLabel.m; path = ../base/StatsLabel.m; sourceTree = SOURCE_ROOT; };
CEAC6810109B0B7E00B43C85 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Preferences.xib; path = xib/Preferences.xib; sourceTree = "<group>"; };
@@ -260,6 +263,8 @@
CE76FDBD111EE37C006618EA /* views */ = {
isa = PBXGroup;
children = (
CE6DD545124CAF1F0089A48D /* HSTableView.h */,
CE6DD546124CAF1F0089A48D /* HSTableView.m */,
CE76FDBE111EE37C006618EA /* HSOutlineView.h */,
CE76FDBF111EE37C006618EA /* HSOutlineView.m */,
CE76FDC0111EE37C006618EA /* NSIndexPathAdditions.h */,
@@ -362,10 +367,10 @@
CEFC7FB00FC9518F00CD5728 /* dgbase */ = {
isa = PBXGroup;
children = (
CE91F20F113BC22D0010360B /* PyResultTree.h */,
CE6DD4E4124CA3070089A48D /* PyResultTable.h */,
CE6DD4E5124CA3070089A48D /* ResultTable.h */,
CE6DD4E6124CA3070089A48D /* ResultTable.m */,
CE91F210113BC22D0010360B /* PyStatsLabel.h */,
CE91F211113BC22D0010360B /* ResultOutline.h */,
CE91F212113BC22D0010360B /* ResultOutline.m */,
CE91F213113BC22D0010360B /* StatsLabel.h */,
CE91F214113BC22D0010360B /* StatsLabel.m */,
CE76FDD1111EE3A7006618EA /* DirectoryOutline.h */,
@@ -491,10 +496,11 @@
CE76FDDF111EE42F006618EA /* HSOutline.m in Sources */,
CE76FDF7111EE561006618EA /* NSEventAdditions.m in Sources */,
CEBE4D74111F0EE1009AAC6D /* HSWindowController.m in Sources */,
CE91F215113BC22D0010360B /* ResultOutline.m in Sources */,
CE91F216113BC22D0010360B /* StatsLabel.m in Sources */,
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */,
CE8C53BC117324CE0011B41F /* HSTable.m in Sources */,
CE6DD4E7124CA3070089A48D /* ResultTable.m in Sources */,
CE6DD547124CAF1F0089A48D /* HSTableView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -2,13 +2,13 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">740</string>
<string key="IBDocument.SystemVersion">10F569</string>
<string key="IBDocument.InterfaceBuilderVersion">788</string>
<string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">460.00</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">740</string>
<string key="NS.object.0">788</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -623,10 +623,31 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSButton" id="647216699">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{15, 171}, {265, 18}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="118836063">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Ignore duplicates hardlinking to the same file</string>
<reference key="NSSupport" ref="26"/>
<reference key="NSControlView" ref="647216699"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
</object>
<object class="NSTextField" id="962804407">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 168}, {315, 17}}</string>
<string key="NSFrame">{{14, 148}, {315, 17}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="111092399">
@@ -642,7 +663,7 @@
<object class="NSTextField" id="873032174">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">266</int>
<string key="NSFrame">{{17, 138}, {309, 22}}</string>
<string key="NSFrame">{{17, 118}, {309, 22}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="249250691">
@@ -659,7 +680,7 @@
<object class="NSTextField" id="511043844">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{14, 117}, {85, 13}}</string>
<string key="NSFrame">{{14, 97}, {85, 13}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="669919489">
@@ -675,7 +696,7 @@
<object class="NSPopUpButton" id="857082145">
<reference key="NSNextResponder" ref="448252432"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{101, 106}, {216, 26}}</string>
<string key="NSFrame">{{101, 86}, {216, 26}}</string>
<reference key="NSSuperview" ref="448252432"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="307074513">
@@ -1068,6 +1089,22 @@
</object>
<int key="connectionID">140</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: values.ignoreHardlinkMatches</string>
<reference key="source" ref="647216699"/>
<reference key="destination" ref="75941798"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="647216699"/>
<reference key="NSDestination" ref="75941798"/>
<string key="NSLabel">value: values.ignoreHardlinkMatches</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">values.ignoreHardlinkMatches</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">144</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -1170,6 +1207,7 @@
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="724127338"/>
<reference ref="647216699"/>
<reference ref="962804407"/>
<reference ref="873032174"/>
<reference ref="511043844"/>
@@ -1552,6 +1590,20 @@
<reference key="object" ref="97487610"/>
<reference key="parent" ref="593115874"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">141</int>
<reference key="object" ref="647216699"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="118836063"/>
</object>
<reference key="parent" ref="448252432"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">142</int>
<reference key="object" ref="118836063"/>
<reference key="parent" ref="647216699"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -1573,6 +1625,9 @@
<string>134.IBPluginDependency</string>
<string>138.IBPluginDependency</string>
<string>139.IBPluginDependency</string>
<string>141.IBPluginDependency</string>
<string>141.ImportedFromIB2</string>
<string>142.IBPluginDependency</string>
<string>51.IBPluginDependency</string>
<string>51.ImportedFromIB2</string>
<string>52.IBEditorWindowLastContentRect</string>
@@ -1675,6 +1730,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<string>{{88, 543}, {389, 302}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{88, 543}, {389, 302}}</string>
@@ -1773,7 +1831,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">140</int>
<int key="maxID">144</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -1785,6 +1843,13 @@
<string key="minorKey">../views/HSOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../views/HSTableView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -2323,6 +2388,13 @@
<string key="NS.key.0">showWindow:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">showWindow:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">showWindow:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string>
@@ -2331,6 +2403,7 @@
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<integer value="1050" key="NS.object.0"/>
@@ -2342,5 +2415,18 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../dupeguru.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>{9, 8}</string>
<string>{7, 2}</string>
</object>
</object>
</data>
</archive>

View File

@@ -6,8 +6,6 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
import os
import os.path as op
import logging
@@ -50,6 +48,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
self.options = {
'escape_filter_regexp': True,
'clean_empty_dirs': False,
'ignore_hardlink_matches': False,
}
self.selected_dupes = []
@@ -62,18 +61,22 @@ class DupeGuru(RegistrableApplication, Broadcaster):
else:
self.action_count += count
def _do_delete(self, j):
def _do_delete(self, j, replace_with_hardlinks):
def op(dupe):
j.add_progress()
return self._do_delete_dupe(dupe)
return self._do_delete_dupe(dupe, replace_with_hardlinks)
j.start_job(self.results.mark_count)
self.results.perform_on_marked(op, True)
def _do_delete_dupe(self, dupe):
def _do_delete_dupe(self, dupe, replace_with_hardlinks):
if not io.exists(dupe.path):
return
send2trash(str(dupe.path)) # Raises OSError when there's a problem
if replace_with_hardlinks:
group = self.results.get_group_of_duplicate(dupe)
ref = group.ref
os.link(str(ref.path), str(dupe.path))
self.clean_empty_dirs(dupe.path[:-1])
def _do_load(self, j):
@@ -117,14 +120,25 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def _reveal_path(path):
raise NotImplementedError()
@staticmethod
def _remove_hardlink_dupes(files):
seen_inodes = set()
result = []
for file in files:
inode = io.stat(file.path).st_ino
if inode not in seen_inodes:
seen_inodes.add(inode)
result.append(file)
return result
def _select_dupes(self, dupes):
if dupes == self.selected_dupes:
return
self.selected_dupes = dupes
self.notify('dupes_selected')
def _start_job(self, jobid, func):
# func(j)
def _start_job(self, jobid, func, *args):
# func(j, *args)
raise NotImplementedError()
def add_directory(self, d):
@@ -196,9 +210,9 @@ class DupeGuru(RegistrableApplication, Broadcaster):
jobid = JOB_COPY if copy else JOB_MOVE
self._start_job(jobid, do)
def delete_marked(self):
def delete_marked(self, replace_with_hardlinks=False):
self._demo_check()
self._start_job(JOB_DELETE, self._do_delete)
self._start_job(JOB_DELETE, self._do_delete, replace_with_hardlinks)
def export_to_xhtml(self, column_ids):
column_ids = [colid for colid in column_ids if colid.isdigit()]
@@ -341,6 +355,8 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def do(j):
j.set_progress(0, 'Collecting files to scan')
files = list(self.directories.get_files())
if self.options['ignore_hardlink_matches']:
files = self._remove_hardlink_dupes(files)
logging.info('Scanning %d files' % len(files))
self.results.groups = self.scanner.GetDupeGroups(files, j)

View File

@@ -55,10 +55,11 @@ class DupeGuru(app.DupeGuru):
def _reveal_path(path):
NSWorkspace.sharedWorkspace().selectFile_inFileViewerRootedAtPath_(str(path), '')
def _start_job(self, jobid, func):
def _start_job(self, jobid, func, *args):
try:
j = self.progress.create_job()
self.progress.run_threaded(func, args=(j, ))
args = tuple([j] + list(args))
self.progress.run_threaded(func, args=args)
except job.JobInProgressError:
NSNotificationCenter.defaultCenter().postNotificationName_object_('JobInProgress', self)
else:

View File

@@ -15,7 +15,7 @@ from .gui.details_panel import DetailsPanel
from .gui.directory_tree import DirectoryTree
from .gui.problem_dialog import ProblemDialog
from .gui.problem_table import ProblemTable
from .gui.result_tree import ResultTree
from .gui.result_table import ResultTable
from .gui.stats_label import StatsLabel
# Fix py2app's problems on relative imports
@@ -80,6 +80,9 @@ class PyDupeGuruBase(PyRegistrable):
def deleteMarked(self):
self.py.delete_marked()
def hardlinkMarked(self):
self.py.delete_marked(replace_with_hardlinks=True)
def applyFilter_(self, filter):
self.py.apply_filter(filter)
@@ -116,18 +119,31 @@ class PyDupeGuruBase(PyRegistrable):
return bool(self.py.results.problems)
#---Properties
@signature('v@:c')
def setMixFileKind_(self, mix_file_kind):
self.py.scanner.mix_file_kind = mix_file_kind
@signature('v@:c')
def setEscapeFilterRegexp_(self, escape_filter_regexp):
self.py.options['escape_filter_regexp'] = escape_filter_regexp
@signature('v@:c')
def setRemoveEmptyFolders_(self, remove_empty_folders):
self.py.options['clean_empty_dirs'] = remove_empty_folders
@signature('v@:c')
def setIgnoreHardlinkMatches_(self, ignore_hardlink_matches):
self.py.options['ignore_hardlink_matches'] = ignore_hardlink_matches
#---Worker
def getJobProgress(self):
try:
return self.py.progress.last_progress
except AttributeError:
# I have *no idea* why this can possible happen (last_progress is always set by
# create_job() *before* any threaded job notification, which shows the progress panel,
# is sent), but it happens anyway, so there we go.
return -1
def getJobDesc(self):
return self.py.progress.last_desc
@@ -157,8 +173,8 @@ class PyDirectoryOutline(PyOutline):
self.py.add_directory(path)
class PyResultOutline(PyOutline):
py_class = ResultTree
class PyResultTable(PyTable):
py_class = ResultTable
@signature('c@:')
def powerMarkerMode(self):
@@ -176,9 +192,9 @@ class PyResultOutline(PyOutline):
def setDeltaValuesMode_(self, value):
self.py.delta_values = value
@signature('@@:@i')
def valueForPath_column_(self, path, column):
return self.py.get_node_value(path, column)
@signature('@@:ii')
def valueForRow_column_(self, row_index, column):
return self.py.get_row_value(row_index, column)
@signature('c@:@')
def renameSelected_(self, newname):
@@ -194,8 +210,9 @@ class PyResultOutline(PyOutline):
def removeSelected(self):
self.py.app.remove_selected()
def rootChildrenCounts(self):
return self.py.root_children_counts()
@signature('i@:')
def selectedDupeCount(self):
return self.py.selected_dupe_count
# python --> cocoa
def invalidate_markings(self):

View File

@@ -9,14 +9,14 @@
from operator import attrgetter
from hsgui.tree import Tree, Node
from hsgui.table import GUITable, Row
from .base import GUIObject
class DupeNode(Node):
def __init__(self, app, group, dupe):
Node.__init__(self, '')
self._app = app
class DupeRow(Row):
def __init__(self, table, group, dupe):
Row.__init__(self, table)
self._app = table.app
self._group = group
self._dupe = dupe
self._data = None
@@ -34,6 +34,10 @@ class DupeNode(Node):
self._data_delta = self._app._get_display_info(self._dupe, self._group, True)
return self._data_delta
@property
def isref(self):
return self._dupe is self._group.ref
@property
def markable(self):
return self._app.results.is_markable(self._dupe)
@@ -47,10 +51,10 @@ class DupeNode(Node):
self._app.mark_dupe(self._dupe, value)
class ResultTree(GUIObject, Tree):
class ResultTable(GUIObject, GUITable):
def __init__(self, view, app):
GUIObject.__init__(self, view, app)
Tree.__init__(self)
GUITable.__init__(self)
self._power_marker = False
self._delta_values = False
self._sort_descriptors = (0, True)
@@ -58,61 +62,58 @@ class ResultTree(GUIObject, Tree):
#--- Override
def connect(self):
GUIObject.connect(self)
self._refresh()
self.view.refresh()
self._refresh_with_view()
def _select_nodes(self, nodes):
Tree._select_nodes(self, nodes)
self.app._select_dupes(list(map(attrgetter('_dupe'), nodes)))
def _restore_selection(self, previous_selection):
if self.app.selected_dupes:
to_find = set(self.app.selected_dupes)
indexes = [i for i, r in enumerate(self) if r._dupe in to_find]
self.selected_indexes = indexes
#--- Private
def _refresh(self):
self.clear()
def _update_selection(self):
rows = self.selected_rows
self.app._select_dupes(list(map(attrgetter('_dupe'), rows)))
def _fill(self):
if not self.power_marker:
for group in self.app.results.groups:
group_node = DupeNode(self.app, group, group.ref)
self.append(group_node)
self.append(DupeRow(self, group, group.ref))
for dupe in group.dupes:
group_node.append(DupeNode(self.app, group, dupe))
self.append(DupeRow(self, group, dupe))
else:
for dupe in self.app.results.dupes:
group = self.app.results.get_group_of_duplicate(dupe)
self.append(DupeNode(self.app, group, dupe))
if self.app.selected_dupes:
to_find = set(self.app.selected_dupes)
nodes = list(self.findall(lambda n: n is not self and n._dupe in to_find))
self.selected_nodes = nodes
self.append(DupeRow(self, group, dupe))
def _refresh_with_view(self):
self.refresh()
self.view.refresh()
self.view.show_selected_row()
#--- Public
def get_node_value(self, path, column):
def get_row_value(self, index, column):
try:
node = self.get_node(path)
row = self[index]
except IndexError:
return '---'
if self.delta_values:
return node.data_delta[column]
return row.data_delta[column]
else:
return node.data[column]
return row.data[column]
def rename_selected(self, newname):
node = self.selected_node
node._data = None
node._data_delta = None
row = self.selected_row
row._data = None
row._data_delta = None
return self.app.rename_selected(newname)
def root_children_counts(self):
# This is a speed optimization for cases where there's a lot of results so that there is
# not thousands of children_count queries when expandAll is called.
return [len(node) for node in self]
def sort(self, key, asc):
if self.power_marker:
self.app.results.sort_dupes(key, asc, self.delta_values)
else:
self.app.results.sort_groups(key, asc)
self._sort_descriptors = (key, asc)
self._refresh()
self.view.refresh()
self._refresh_with_view()
#--- Properties
@property
@@ -126,8 +127,7 @@ class ResultTree(GUIObject, Tree):
self._power_marker = value
key, asc = self._sort_descriptors
self.sort(key, asc)
self._refresh()
self.view.refresh()
# no need to refresh, it has happened in sort()
@property
def delta_values(self):
@@ -138,22 +138,25 @@ class ResultTree(GUIObject, Tree):
if value == self._delta_values:
return
self._delta_values = value
self._refresh()
self.refresh()
self.view.refresh()
@property
def selected_dupe_count(self):
return sum(1 for row in self.selected_rows if not row.isref)
#--- Event Handlers
def marking_changed(self):
self.view.invalidate_markings()
def results_changed(self):
self._refresh()
self.view.refresh()
self._refresh_with_view()
def results_changed_but_keep_selection(self):
# What we want to to here is that instead of restoring selected *dupes* after refresh, we
# restore selected *paths*.
paths = self.selected_paths
self._refresh()
self.selected_paths = paths
indexes = self.selected_indexes
self.refresh()
self.select(indexes)
self.view.refresh()

View File

@@ -23,14 +23,15 @@ from .. import app, fs, engine
from ..app import DupeGuru as DupeGuruBase
from ..gui.details_panel import DetailsPanel
from ..gui.directory_tree import DirectoryTree
from ..gui.result_tree import ResultTree
from ..gui.result_table import ResultTable
from ..scanner import ScanType
class DupeGuru(DupeGuruBase):
def __init__(self):
DupeGuruBase.__init__(self, data, '/tmp', appid=4)
def _start_job(self, jobid, func):
func(nulljob)
def _start_job(self, jobid, func, *args):
func(nulljob, *args)
class CallLogger(object):
@@ -122,6 +123,19 @@ class TCDupeGuru(TestCase):
app.directories._dirs.append('this is just so Scan() doesnt return 3')
app.start_scanning() # no exception
def test_ignore_hardlink_matches(self):
# If the ignore_hardlink_matches option is set, don't match files hardlinking to the same
# inode.
tmppath = Path(self.tmpdir())
io.open(tmppath + 'myfile', 'w').write('foo')
os.link(str(tmppath + 'myfile'), str(tmppath + 'hardlink'))
app = DupeGuru()
app.directories.add_path(tmppath)
app.scanner.scan_type = ScanType.Contents
app.options['ignore_hardlink_matches'] = True
app.start_scanning()
eq_(len(app.results.groups), 0)
class TCDupeGuru_clean_empty_dirs(TestCase):
cls_tested_module = app
@@ -166,11 +180,11 @@ class TCDupeGuruWithResults(TestCase):
self.dpanel = DetailsPanel(self.dpanel_gui, self.app)
self.dtree_gui = CallLogger()
self.dtree = DirectoryTree(self.dtree_gui, self.app)
self.rtree_gui = CallLogger()
self.rtree = ResultTree(self.rtree_gui, self.app)
self.rtable_gui = CallLogger()
self.rtable = ResultTable(self.rtable_gui, self.app)
self.dpanel.connect()
self.dtree.connect()
self.rtree.connect()
self.rtable.connect()
tmppath = self.tmppath()
io.mkdir(tmppath + 'foo')
io.mkdir(tmppath + 'bar')
@@ -217,42 +231,35 @@ class TCDupeGuruWithResults(TestCase):
def test_GetObjects(self):
objects = self.objects
groups = self.groups
n = self.rtree.get_node([0])
assert n._group is groups[0]
assert n._dupe is objects[0]
n = self.rtree.get_node([0, 0])
assert n._group is groups[0]
assert n._dupe is objects[1]
n = self.rtree.get_node([1, 0])
assert n._group is groups[1]
assert n._dupe is objects[4]
r = self.rtable[0]
assert r._group is groups[0]
assert r._dupe is objects[0]
r = self.rtable[1]
assert r._group is groups[0]
assert r._dupe is objects[1]
r = self.rtable[4]
assert r._group is groups[1]
assert r._dupe is objects[4]
def test_GetObjects_after_sort(self):
objects = self.objects
groups = self.groups[:] # we need an un-sorted reference
self.rtree.sort(0, False) #0 = Filename
n = self.rtree.get_node([0, 0])
assert n._group is groups[1]
assert n._dupe is objects[4]
def test_selected_result_node_paths(self):
# app.selected_dupes is correctly converted into node paths
paths = [[0, 0], [0, 1], [1]]
self.rtree.selected_paths = paths
eq_(self.rtree.selected_paths, paths)
self.rtable.sort(0, False) #0 = Filename
r = self.rtable[1]
assert r._group is groups[1]
assert r._dupe is objects[4]
def test_selected_result_node_paths_after_deletion(self):
# cases where the selected dupes aren't there are correctly handled
paths = [[0, 0], [0, 1], [1]]
self.rtree.selected_paths = paths
self.rtable.select([1, 2, 3])
self.app.remove_selected()
# The first 2 dupes have been removed. The 3rd one is a ref. it stays there, in first pos.
eq_(self.rtree.selected_paths, [[0, 0]]) # no exception
eq_(self.rtable.selected_indexes, [1]) # no exception
def test_selectResultNodePaths(self):
app = self.app
objects = self.objects
self.rtree.selected_paths = [[0, 0], [0, 1]]
self.rtable.select([1, 2])
eq_(len(app.selected_dupes), 2)
assert app.selected_dupes[0] is objects[1]
assert app.selected_dupes[1] is objects[2]
@@ -260,7 +267,7 @@ class TCDupeGuruWithResults(TestCase):
def test_selectResultNodePaths_with_ref(self):
app = self.app
objects = self.objects
self.rtree.selected_paths = [[0, 0], [0, 1], [1]]
self.rtable.select([1, 2, 3])
eq_(len(app.selected_dupes), 3)
assert app.selected_dupes[0] is objects[1]
assert app.selected_dupes[1] is objects[2]
@@ -270,9 +277,9 @@ class TCDupeGuruWithResults(TestCase):
app = self.app
objects = self.objects
groups = self.groups[:] #To keep the old order in memory
self.rtree.sort(0, False) #0 = Filename
self.rtable.sort(0, False) #0 = Filename
#Now, the group order is supposed to be reversed
self.rtree.selected_paths = [[0, 0], [1], [1, 0]]
self.rtable.select([1, 2, 3])
eq_(len(app.selected_dupes), 3)
assert app.selected_dupes[0] is objects[4]
assert app.selected_dupes[1] is groups[0].ref
@@ -282,39 +289,26 @@ class TCDupeGuruWithResults(TestCase):
# app.selected_dupes is correctly converted into paths
app = self.app
objects = self.objects
self.rtree.power_marker = True
self.rtree.selected_paths = [[0], [1], [2]]
self.rtree.power_marker = False
eq_(self.rtree.selected_paths, [[0, 0], [0, 1], [1, 0]])
self.rtable.power_marker = True
self.rtable.select([0, 1, 2])
self.rtable.power_marker = False
eq_(self.rtable.selected_indexes, [1, 2, 4])
def test_selected_powermarker_node_paths_after_deletion(self):
# cases where the selected dupes aren't there are correctly handled
app = self.app
objects = self.objects
self.rtree.power_marker = True
self.rtree.selected_paths = [[0], [1], [2]]
self.rtable.power_marker = True
self.rtable.select([0, 1, 2])
app.remove_selected()
eq_(self.rtree.selected_paths, []) # no exception
def test_selectPowerMarkerRows(self):
app = self.app
objects = self.objects
self.rtree.selected_paths = [[0, 0], [0, 1], [1, 0]]
eq_(len(app.selected_dupes), 3)
assert app.selected_dupes[0] is objects[1]
assert app.selected_dupes[1] is objects[2]
assert app.selected_dupes[2] is objects[4]
def test_selectPowerMarkerRows_empty(self):
self.rtree.selected_paths = []
eq_(len(self.app.selected_dupes), 0)
eq_(self.rtable.selected_indexes, []) # no exception
def test_selectPowerMarkerRows_after_sort(self):
app = self.app
objects = self.objects
self.rtree.power_marker = True
self.rtree.sort(0, False) #0 = Filename
self.rtree.selected_paths = [[0], [1], [2]]
self.rtable.power_marker = True
self.rtable.sort(0, False) #0 = Filename
self.rtable.select([0, 1, 2])
eq_(len(app.selected_dupes), 3)
assert app.selected_dupes[0] is objects[4]
assert app.selected_dupes[1] is objects[2]
@@ -325,7 +319,7 @@ class TCDupeGuruWithResults(TestCase):
objects = self.objects
app.toggle_selected_mark_state()
eq_(app.results.mark_count, 0)
self.rtree.selected_paths = [[0, 0], [1, 0]]
self.rtable.select([1, 4])
app.toggle_selected_mark_state()
eq_(app.results.mark_count, 2)
assert not app.results.is_marked(objects[0])
@@ -335,10 +329,10 @@ class TCDupeGuruWithResults(TestCase):
assert app.results.is_marked(objects[4])
def test_refreshDetailsWithSelected(self):
self.rtree.selected_paths = [[0, 0], [1, 0]]
self.rtable.select([1, 4])
eq_(self.dpanel.row(0), ('Filename', 'bar bleh', 'foo bar'))
self.check_gui_calls(self.dpanel_gui, ['refresh'])
self.rtree.selected_paths = []
self.rtable.select([])
eq_(self.dpanel.row(0), ('Filename', '---', '---'))
self.check_gui_calls(self.dpanel_gui, ['refresh'])
@@ -346,7 +340,7 @@ class TCDupeGuruWithResults(TestCase):
app = self.app
objects = self.objects
groups = self.groups
self.rtree.selected_paths = [[0, 0], [1, 0]]
self.rtable.select([1, 4])
app.make_selected_reference()
assert groups[0].ref is objects[1]
assert groups[1].ref is objects[4]
@@ -355,7 +349,7 @@ class TCDupeGuruWithResults(TestCase):
app = self.app
objects = self.objects
groups = self.groups
self.rtree.selected_paths = [[0, 0], [0, 1], [1, 0]]
self.rtable.select([1, 2, 4])
#Only [0, 0] and [1, 0] must go ref, not [0, 1] because it is a part of the same group
app.make_selected_reference()
assert groups[0].ref is objects[1]
@@ -363,7 +357,7 @@ class TCDupeGuruWithResults(TestCase):
def test_removeSelected(self):
app = self.app
self.rtree.selected_paths = [[0, 0], [1, 0]]
self.rtable.select([1, 4])
app.remove_selected()
eq_(len(app.results.dupes), 1) # the first path is now selected
app.remove_selected()
@@ -386,10 +380,10 @@ class TCDupeGuruWithResults(TestCase):
def test_ignore(self):
app = self.app
self.rtree.selected_path = [1, 0] #The dupe of the second, 2 sized group
self.rtable.select([4]) #The dupe of the second, 2 sized group
app.add_selected_to_ignore_list()
eq_(len(app.scanner.ignore_list), 1)
self.rtree.selected_path = [0, 0] #first dupe of the 3 dupes group
self.rtable.select([1]) #first dupe of the 3 dupes group
app.add_selected_to_ignore_list()
#BOTH the ref and the other dupe should have been added
eq_(len(app.scanner.ignore_list), 3)
@@ -416,7 +410,7 @@ class TCDupeGuruWithResults(TestCase):
app = self.app
app.scanner.ignore_list.Ignore = FakeIgnore
self.rtree.selected_path = [1, 0]
self.rtable.select([4])
app.add_selected_to_ignore_list()
@@ -440,14 +434,14 @@ class TCDupeGuru_renameSelected(TestCase):
self.groups = groups
self.p = p
self.files = files
self.rtree_gui = CallLogger()
self.rtree = ResultTree(self.rtree_gui, self.app)
self.rtree.connect()
self.rtable_gui = CallLogger()
self.rtable = ResultTable(self.rtable_gui, self.app)
self.rtable.connect()
def test_simple(self):
app = self.app
g = self.groups[0]
self.rtree.selected_path = [0, 0]
self.rtable.select([1])
assert app.rename_selected('renamed')
names = io.listdir(self.p)
assert 'renamed' in names
@@ -457,7 +451,7 @@ class TCDupeGuru_renameSelected(TestCase):
def test_none_selected(self):
app = self.app
g = self.groups[0]
self.rtree.selected_paths = []
self.rtable.select([])
self.mock(logging, 'warning', log_calls(lambda msg: None))
assert not app.rename_selected('renamed')
msg = logging.warning.calls[0]['msg']
@@ -470,7 +464,7 @@ class TCDupeGuru_renameSelected(TestCase):
def test_name_already_exists(self):
app = self.app
g = self.groups[0]
self.rtree.selected_path = [0, 0]
self.rtable.select([1])
self.mock(logging, 'warning', log_calls(lambda msg: None))
assert not app.rename_selected('foo bar 1')
msg = logging.warning.calls[0]['msg']

View File

@@ -139,10 +139,10 @@ class DupeGuruPE(app_cocoa.DupeGuru):
self.directories = Directories()
self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db')
def _do_delete(self, j):
def _do_delete(self, j, replace_with_hardlinks):
def op(dupe):
j.add_progress()
return self._do_delete_dupe(dupe)
return self._do_delete_dupe(dupe, replace_with_hardlinks)
marked = [dupe for dupe in self.results.dupes if self.results.is_marked(dupe)]
self.path2iphoto = {}
@@ -164,7 +164,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
self.results.perform_on_marked(op, True)
del self.path2iphoto
def _do_delete_dupe(self, dupe):
def _do_delete_dupe(self, dupe, replace_with_hardlinks):
if isinstance(dupe, IPhoto):
if str(dupe.path) in self.path2iphoto:
photo = self.path2iphoto[str(dupe.path)]
@@ -177,7 +177,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
msg = "Could not find photo %s in iPhoto Library" % str(dupe.path)
raise EnvironmentError(msg)
else:
app_cocoa.DupeGuru._do_delete_dupe(self, dupe)
app_cocoa.DupeGuru._do_delete_dupe(self, dupe, replace_with_hardlinks)
def _get_file(self, str_path):
p = Path(str_path)

View File

@@ -1,3 +1,12 @@
- date: 2010-09-27
version: 5.10.0
description: |
* Improved UI with a little revamp.
* Added the possibility to place hardlinks to references after having deleted duplicates. [Mac OS X, Linux] (#91)
* Added an option to ignore duplicates hardlinking to the same file. [Mac OS X, Linux] (#92)
* Added multiple selection in the "Add Directory" dialog. [Mac OS X] (#105)
* Fixed a bug preventing drag & drop from working in the Directories panel. [Windows, Linux]
* Fixed a crash on some badly formed Id3v2 tags. (#107)
- date: 2010-08-24
version: 5.9.1
description: |

View File

@@ -17,6 +17,8 @@
**Can mix file kind:** If you check this box, duplicate groups are allowed to have files with different extensions. If you don't check it, well, they aren't!
**Ignore duplicates hardlinking to the same file:** If this option is enabled, dupeGuru will verify duplicates to see if they refer to the same [inode](http://en.wikipedia.org/wiki/Inode). If they do, they will not be considered duplicates. (Only for OS X and Linux)
**Use regular expressions when filtering:** If you check this box, the filtering feature will treat your filter query as a **regular expression**. Explaining them is beyond the scope of this document. A good place to start learning it is <http://www.regular-expressions.info>.
**Remove empty folders after delete or move:** When this option is enabled, folders are deleted after a file is deleted or moved and the folder is empty.

View File

@@ -56,6 +56,7 @@ Action Menu
* **Clear Ignore List:** Remove all ignored matches you added. You have to start a new scan for the newly cleared ignore list to be effective.
* **Export Results to XHTML:** Take the current results, and create an XHTML file out of it. The columns that are visible when you click on this button will be the columns present in the XHTML file. The file will automatically be opened in your default browser.
* **Send Marked to Trash:** Send all marked duplicates to trash, obviously.
* **Delete Marked and Replace with Hardlinks:** Sends all marked duplicates to trash, but after having done that, the deleted files are replaced by a [hard link](http://en.wikipedia.org/wiki/Hard_link) to the reference file. (Only for OS X and Linux)
* **Move Marked to...:** Prompt you for a destination, and then move all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Copy Marked to...:** Prompt you for a destination, and then copy all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Remove Marked from Results:** Remove all marked duplicates from results. The actual files will not be touched and will stay where they are.

View File

@@ -1,3 +1,11 @@
- date: 2010-09-27
version: 1.11.0
description: |
* Improved UI with a little revamp.
* Added the possibility to place hardlinks to references after having deleted duplicates. [Mac OS X, Linux] (#91)
* Added an option to ignore duplicates hardlinking to the same file. [Mac OS X, Linux] (#92)
* Added multiple selection in the "Add Directory" dialog. [Mac OS X] (#105)
* Fixed a bug preventing drag & drop from working in the Directories panel. [Windows, Linux]
- date: 2010-08-21
version: 1.10.0
description: |

View File

@@ -4,6 +4,8 @@
**Can mix file kind:** If you check this box, duplicate groups are allowed to have files with different extensions. If you don't check it, well, they aren't!
**Ignore duplicates hardlinking to the same file:** If this option is enabled, dupeGuru will verify duplicates to see if they refer to the same [inode](http://en.wikipedia.org/wiki/Inode). If they do, they will not be considered duplicates. (Only for OS X and Linux)
**Use regular expressions when filtering:** If you check this box, the filtering feature will treat your filter query as a **regular expression**. Explaining them is beyond the scope of this document. A good place to start learning it is <http://www.regular-expressions.info>.
**Remove empty folders after delete or move:** When this option is enabled, folders are deleted after a file is deleted or moved and the folder is empty.

View File

@@ -56,6 +56,7 @@ Action Menu
* **Clear Ignore List:** Remove all ignored matches you added. You have to start a new scan for the newly cleared ignore list to be effective.
* **Export Results to XHTML:** Take the current results, and create an XHTML file out of it. The columns that are visible when you click on this button will be the columns present in the XHTML file. The file will automatically be opened in your default browser.
* **Send Marked to Trash:** Send all marked duplicates to trash, obviously.
* **Delete Marked and Replace with Hardlinks:** Sends all marked duplicates to trash, but after having done that, the deleted files are replaced by a [hard link](http://en.wikipedia.org/wiki/Hard_link) to the reference file. (Only for OS X and Linux)
* **Move Marked to...:** Prompt you for a destination, and then move all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Copy Marked to...:** Prompt you for a destination, and then copy all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Remove Marked from Results:** Remove all marked duplicates from results. The actual files will not be touched and will stay where they are.

View File

@@ -1,3 +1,11 @@
- date: 2010-09-26
version: 2.12.0
description: |
* Improved UI with a little revamp.
* Added the possibility to place hardlinks to references after having deleted duplicates. [Mac OS X, Linux] (#91)
* Added an option to ignore duplicates hardlinking to the same file. [Mac OS X, Linux] (#92)
* Added multiple selection in the "Add Directory" dialog. [Mac OS X] (#105)
* Fixed a bug preventing drag & drop from working in the Directories panel. [Windows, Linux]
- date: 2010-08-26
version: 2.11.1
description: |

View File

@@ -8,6 +8,8 @@
**Can mix file kind:** If you check this box, duplicate groups are allowed to have files with different extensions. If you don't check it, well, they aren't!
**Ignore duplicates hardlinking to the same file:** If this option is enabled, dupeGuru will verify duplicates to see if they refer to the same [inode](http://en.wikipedia.org/wiki/Inode). If they do, they will not be considered duplicates. (Only for OS X and Linux)
**Use regular expressions when filtering:** If you check this box, the filtering feature will treat your filter query as a **regular expression**. Explaining them is beyond the scope of this document. A good place to start learning it is <http://www.regular-expressions.info>.
**Remove empty folders after delete or move:** When this option is enabled, folders are deleted after a file is deleted or moved and the folder is empty.

View File

@@ -56,6 +56,7 @@ Action Menu
* **Clear Ignore List:** Remove all ignored matches you added. You have to start a new scan for the newly cleared ignore list to be effective.
* **Export Results to XHTML:** Take the current results, and create an XHTML file out of it. The columns that are visible when you click on this button will be the columns present in the XHTML file. The file will automatically be opened in your default browser.
* **Send Marked to Trash:** Send all marked duplicates to trash, obviously.
* **Delete Marked and Replace with Hardlinks:** Sends all marked duplicates to trash, but after having done that, the deleted files are replaced by a [hard link](http://en.wikipedia.org/wiki/Hard_link) to the reference file. (Only for OS X and Linux)
* **Move Marked to...:** Prompt you for a destination, and then move all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Copy Marked to...:** Prompt you for a destination, and then copy all marked files to that destination. Source file's path might be re-created in destination, depending on the "Copy and Move" preference.
* **Remove Marked from Results:** Remove all marked duplicates from results. The actual files will not be touched and will stay where they are.

View File

@@ -106,6 +106,7 @@ class DupeGuru(DupeGuruBase, QObject):
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
self.options['ignore_hardlink_matches'] = self.prefs.ignore_hardlink_matches
#--- Virtual
def _create_details_dialog(self, parent):
@@ -130,11 +131,12 @@ class DupeGuru(DupeGuruBase, QObject):
def _reveal_path(path):
DupeGuru._open_path(path[:-1])
def _start_job(self, jobid, func):
def _start_job(self, jobid, func, *args):
title = JOBID2TITLE[jobid]
try:
j = self._progress.create_job()
self._progress.run(jobid, title, func, args=(j, ))
args = tuple([j] + list(args))
self._progress.run(jobid, title, func, args=args)
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)

View File

@@ -96,13 +96,13 @@ class DirectoriesModel(TreeModel):
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.
# the data in mimeData is urlencoded **in utf-8**!!! What we do is to decode, the mime data
# with 'ascii', which works since it's urlencoded. Then, we pass that to urllib.
if not mimeData.hasFormat('text/uri-list'):
return False
data = str(mimeData.data('text/uri-list'))
data = bytes(mimeData.data('text/uri-list')).decode('ascii')
unquoted = urllib.parse.unquote(data)
urls = str(unquoted, 'utf-8').split('\r\n')
urls = unquoted.split('\r\n')
paths = [str(QUrl(url).toLocalFile()) for url in urls if url]
for path in paths:
self.model.add_directory(path)

View File

@@ -44,11 +44,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.actionInvokeCustomCommand.triggered.connect(self.app.invokeCustomCommand)
self.actionLoadResults.triggered.connect(self.loadResultsTriggered)
self.actionSaveResults.triggered.connect(self.saveResultsTriggered)
self.actionHardlinkMarked.triggered.connect(self.hardlinkTriggered)
def _setupUi(self):
self.setupUi(self)
# Stuff that can't be setup in the Designer
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
h.setHighlightSections(False)
h.setMovable(True)
h.setStretchLastSection(False)
@@ -73,6 +74,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
actionMenu = QMenu('Actions', self.toolBar)
actionMenu.setIcon(QIcon(QPixmap(":/actions")))
actionMenu.addAction(self.actionDeleteMarked)
actionMenu.addAction(self.actionHardlinkMarked)
actionMenu.addAction(self.actionMoveMarked)
actionMenu.addAction(self.actionCopyMarked)
actionMenu.addAction(self.actionRemoveMarked)
@@ -99,9 +101,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if self.app.prefs.mainWindowRect is not None and not self.app.prefs.mainWindowIsMaximized:
self.setGeometry(self.app.prefs.mainWindowRect)
# Linux setup
# Platform-specific setup
if sys.platform == 'linux2':
self.actionCheckForUpdate.setVisible(False) # This only works on Windows
if sys.platform not in {'darwin', 'linux2'}:
self.actionHardlinkMarked.setVisible(False)
#--- Private
def _confirm(self, title, msg, default_button=QMessageBox.Yes):
@@ -110,7 +114,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return answer == QMessageBox.Yes
def _load_columns(self):
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
h.setResizeMode(QHeaderView.Interactive)
prefs = self.app.prefs
attrs = list(zip(prefs.columns_width, prefs.columns_visible))
@@ -120,7 +124,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
h.setResizeMode(0, QHeaderView.Stretch)
def _update_column_actions_status(self):
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
for action in self._column_actions:
colid = action.column_index
action.setChecked(not h.isSectionHidden(colid))
@@ -185,7 +189,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.app.show_directories()
def exportTriggered(self):
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
column_ids = []
for i in range(len(self.app.data.COLUMNS)):
if not h.isSectionHidden(i):
@@ -194,6 +198,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
url = QUrl.fromLocalFile(exported_path)
QDesktopServices.openUrl(url)
def hardlinkTriggered(self):
count = self.app.results.mark_count
if not count:
return
title = "Delete and hardlink duplicates"
msg = "You are about to send {0} files to the trash and hardlink them afterwards. Continue?".format(count)
if self._confirm(title, msg):
self.app.delete_marked(replace_with_hardlinks=True)
def loadResultsTriggered(self):
title = "Select a results file to load"
files = "dupeGuru Results (*.dupeguru)"
@@ -278,7 +291,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
#--- Events
def appWillSavePrefs(self):
prefs = self.app.prefs
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
widths = []
visible = []
for i in range(len(self.app.data.COLUMNS)):
@@ -295,7 +308,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.app.prefs.reset_columns()
self._load_columns()
else:
h = self.resultsView.header()
h = self.resultsView.horizontalHeader()
h.setSectionHidden(colid, not h.isSectionHidden(colid))
self._update_column_actions_status()

View File

@@ -26,27 +26,21 @@
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<attribute name="headerStretchLastSection">
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<attribute name="verticalHeaderDefaultSectionSize">
<number>18</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>18</number>
</attribute>
</widget>
</item>
</layout>
@@ -57,7 +51,7 @@
<x>0</x>
<y>0</y>
<width>630</width>
<height>20</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuColumns">
@@ -70,6 +64,7 @@
<string>Actions</string>
</property>
<addaction name="actionDeleteMarked"/>
<addaction name="actionHardlinkMarked"/>
<addaction name="actionMoveMarked"/>
<addaction name="actionCopyMarked"/>
<addaction name="actionRemoveMarked"/>
@@ -271,6 +266,14 @@
<string>Ctrl+D</string>
</property>
</action>
<action name="actionHardlinkMarked">
<property name="text">
<string>Delete Marked and Replace with Hardlinks</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+D</string>
</property>
</action>
<action name="actionMoveMarked">
<property name="text">
<string>Move Marked to...</string>
@@ -462,7 +465,7 @@
<customwidgets>
<customwidget>
<class>ResultsView</class>
<extends>QTreeView</extends>
<extends>QTableView</extends>
<header>.results_model</header>
</customwidget>
</customwidgets>

View File

@@ -24,6 +24,7 @@ class Preferences(PreferencesBase):
get = self.get_value
self.filter_hardness = get('FilterHardness', self.filter_hardness)
self.mix_file_kind = get('MixFileKind', self.mix_file_kind)
self.ignore_hardlink_matches = get('IgnoreHardlinkMatches', self.ignore_hardlink_matches)
self.use_regexp = get('UseRegexp', self.use_regexp)
self.remove_empty_folders = get('RemoveEmptyFolders', self.remove_empty_folders)
self.destination_type = get('DestinationType', self.destination_type)
@@ -52,6 +53,7 @@ class Preferences(PreferencesBase):
self.filter_hardness = 95
self.mix_file_kind = True
self.use_regexp = False
self.ignore_hardlink_matches = False
self.remove_empty_folders = False
self.destination_type = 1
self.custom_command = ''
@@ -77,6 +79,7 @@ class Preferences(PreferencesBase):
set_ = self.set_value
set_('FilterHardness', self.filter_hardness)
set_('MixFileKind', self.mix_file_kind)
set_('IgnoreHardlinkMatches', self.ignore_hardlink_matches)
set_('UseRegexp', self.use_regexp)
set_('RemoveEmptyFolders', self.remove_empty_folders)
set_('DestinationType', self.destination_type)

View File

@@ -7,85 +7,47 @@
# http://www.hardcoded.net/licenses/hs_license
from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import (QBrush, QStyledItemDelegate, QFont, QTreeView, QColor, QItemSelectionModel,
QItemSelection)
from PyQt4.QtGui import QBrush, QFont, QTableView, QColor, QItemSelectionModel, QItemSelection
from qtlib.tree_model import TreeModel, RefNode
from qtlib.table import Table
from core.gui.result_tree import ResultTree as ResultTreeModel
from core.gui.result_table import ResultTable as ResultTableModel
class ResultsDelegate(QStyledItemDelegate):
def initStyleOption(self, option, index):
QStyledItemDelegate.initStyleOption(self, option, index)
node = index.internalPointer()
ref = node.ref
if ref._group.ref is ref._dupe:
newfont = QFont(option.font)
newfont.setBold(True)
option.font = newfont
class ResultsModel(TreeModel):
class ResultsModel(Table):
def __init__(self, app, view):
TreeModel.__init__(self)
self.view = view
model = ResultTableModel(self, app)
self._app = app
self._data = app.data
self._delta_columns = app.DELTA_COLUMNS
self.resultsDelegate = ResultsDelegate()
self.model = ResultTreeModel(self, app)
self.view.setItemDelegate(self.resultsDelegate)
self.view.setModel(self)
Table.__init__(self, model, view)
self.model.connect()
self.connect(self.view.selectionModel(), SIGNAL('selectionChanged(QItemSelection,QItemSelection)'), self.selectionChanged)
def _createNode(self, ref, row):
return RefNode(self, None, ref, row)
def _getChildren(self):
return list(self.model)
def _updateSelection(self):
selectedIndexes = []
for path in self.model.selected_paths:
modelIndex = self.findIndex(path)
if modelIndex.isValid():
selectedIndexes.append(modelIndex)
if selectedIndexes:
selection = QItemSelection()
for modelIndex in selectedIndexes:
selection.select(modelIndex, modelIndex)
flags = QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows
self.view.selectionModel().select(selection, flags)
flags = QItemSelectionModel.Rows
self.view.selectionModel().setCurrentIndex(selectedIndexes[0], flags)
self.view.scrollTo(selectedIndexes[0])
else:
self.view.selectionModel().clear()
def columnCount(self, parent):
return len(self._data.COLUMNS)
def data(self, index, role):
if not index.isValid():
return None
node = index.internalPointer()
ref = node.ref
row = self.model[index.row()]
if role == Qt.DisplayRole:
data = ref.data_delta if self.model.delta_values else ref.data
data = row.data_delta if self.model.delta_values else row.data
return data[index.column()]
elif role == Qt.CheckStateRole:
if index.column() == 0 and ref.markable:
return Qt.Checked if ref.marked else Qt.Unchecked
if index.column() == 0 and row.markable:
return Qt.Checked if row.marked else Qt.Unchecked
elif role == Qt.ForegroundRole:
if ref._dupe is ref._group.ref or ref._dupe.is_ref:
if row.isref:
return QBrush(Qt.blue)
elif self.model.delta_values and index.column() in self._delta_columns:
return QBrush(QColor(255, 142, 40)) # orange
elif role == Qt.FontRole:
isBold = row.isref
font = QFont(self.view.font())
font.setBold(isBold)
return font
elif role == Qt.EditRole:
if index.column() == 0:
return ref.data[index.column()]
return row.data[index.column()]
return None
def flags(self, index):
@@ -93,7 +55,10 @@ class ResultsModel(TreeModel):
return Qt.ItemIsEnabled
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if index.column() == 0:
flags |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable
flags |= Qt.ItemIsEditable
row = self.model[index.row()]
if row.markable:
flags |= Qt.ItemIsUserCheckable
return flags
def headerData(self, section, orientation, role):
@@ -104,13 +69,12 @@ class ResultsModel(TreeModel):
def setData(self, index, value, role):
if not index.isValid():
return False
node = index.internalPointer()
ref = node.ref
row = self.model[index.row()]
if role == Qt.CheckStateRole:
if index.column() == 0:
self._app.mark_dupe(ref._dupe, value.toBool())
self._app.mark_dupe(row._dupe, value.toBool())
return True
if role == Qt.EditRole:
elif role == Qt.EditRole:
if index.column() == 0:
value = str(value.toString())
return self.model.rename_selected(value)
@@ -136,18 +100,7 @@ class ResultsModel(TreeModel):
def delta_values(self, value):
self.model.delta_values = value
#--- Events
def selectionChanged(self, selected, deselected):
indexes = self.view.selectionModel().selectedRows()
nodes = [index.internalPointer() for index in indexes]
self.model.selected_nodes = [node.ref for node in nodes]
#--- model --> view
def refresh(self):
self.reset()
self.view.expandAll()
self._updateSelection()
def invalidate_markings(self):
# redraw view
# HACK. this is the only way I found to update the widget without reseting everything
@@ -155,13 +108,13 @@ class ResultsModel(TreeModel):
self.view.scroll(0, -1)
class ResultsView(QTreeView):
class ResultsView(QTableView):
#--- Override
def keyPressEvent(self, event):
if event.text() == ' ':
self.emit(SIGNAL('spacePressed()'))
return
QTreeView.keyPressEvent(self, event)
QTableView.keyPressEvent(self, event)
def mouseDoubleClickEvent(self, event):
self.emit(SIGNAL('doubleClicked()'))

View File

@@ -17,7 +17,7 @@ class DupeGuru(DupeGuruBase):
EDITION = 'me'
LOGO_NAME = 'logo_me'
NAME = 'dupeGuru Music Edition'
VERSION = '5.9.1'
VERSION = '5.10.0'
DELTA_COLUMNS = frozenset([2, 3, 4, 5, 7])
def __init__(self):

View File

@@ -6,6 +6,7 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
import sys
from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import QDialog, QDialogButtonBox
@@ -35,6 +36,9 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
def _setupUi(self):
self.setupUi(self)
if sys.platform not in {'darwin', 'linux2'}:
self.verticalLayout.removeWidget(self.ignoreHardlinkMatches)
self.ignoreHardlinkMatches.setHidden(True)
def load(self, prefs=None):
if prefs is None:
@@ -53,6 +57,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
setchecked(self.matchSimilarBox, prefs.match_similar)
setchecked(self.wordWeightingBox, prefs.word_weighting)
setchecked(self.mixFileKindBox, prefs.mix_file_kind)
setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches)
setchecked(self.useRegexpBox, prefs.use_regexp)
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type)
@@ -72,6 +77,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
prefs.match_similar = ischecked(self.matchSimilarBox)
prefs.word_weighting = ischecked(self.wordWeightingBox)
prefs.mix_file_kind = ischecked(self.mixFileKindBox)
prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches)
prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()

View File

@@ -310,6 +310,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ignoreHardlinkMatches">
<property name="text">
<string>Ignore duplicates hardlinking to the same file</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>

View File

@@ -60,7 +60,7 @@ class DupeGuru(DupeGuruBase):
EDITION = 'pe'
LOGO_NAME = 'logo_pe'
NAME = 'dupeGuru Picture Edition'
VERSION = '1.10.0'
VERSION = '1.11.0'
DELTA_COLUMNS = frozenset([2, 5])
def __init__(self):

View File

@@ -6,6 +6,7 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
import sys
from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import QDialog, QDialogButtonBox
@@ -23,6 +24,9 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
def _setupUi(self):
self.setupUi(self)
if sys.platform not in {'darwin', 'linux2'}:
self.verticalLayout.removeWidget(self.ignoreHardlinkMatches)
self.ignoreHardlinkMatches.setHidden(True)
def load(self, prefs=None):
if prefs is None:

View File

@@ -150,6 +150,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ignoreHardlinkMatches">
<property name="text">
<string>Ignore duplicates hardlinking to the same file</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>

View File

@@ -27,7 +27,7 @@ class DupeGuru(DupeGuruBase):
EDITION = 'se'
LOGO_NAME = 'logo_se'
NAME = 'dupeGuru'
VERSION = '2.11.1'
VERSION = '2.12.0'
DELTA_COLUMNS = frozenset([2, 4])
def __init__(self):

View File

@@ -6,6 +6,7 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/hs_license
import platform
from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import QDialog, QDialogButtonBox
@@ -33,6 +34,13 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
def _setupUi(self):
self.setupUi(self)
if platform.system() not in {'Darwin', 'Linux'}:
self.verticalLayout_4.removeWidget(self.ignoreHardlinkMatches)
self.ignoreHardlinkMatches.setHidden(True)
if platform.system() == 'Linux':
# Under linux, whether it's a Qt layout bug or something else, the size threshold text edit
# doesn't have enough space, so we make the pref pane higher to compensate.
self.resize(self.width(), 400)
def load(self, prefs=None):
if prefs is None:
@@ -45,6 +53,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
setchecked(self.matchSimilarBox, prefs.match_similar)
setchecked(self.wordWeightingBox, prefs.word_weighting)
setchecked(self.mixFileKindBox, prefs.mix_file_kind)
setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches)
setchecked(self.useRegexpBox, prefs.use_regexp)
setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders)
setchecked(self.ignoreSmallFilesBox, prefs.ignore_small_files)
@@ -60,6 +69,7 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog):
prefs.match_similar = ischecked(self.matchSimilarBox)
prefs.word_weighting = ischecked(self.wordWeightingBox)
prefs.mix_file_kind = ischecked(self.mixFileKindBox)
prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches)
prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.ignore_small_files = ischecked(self.ignoreSmallFilesBox)

View File

@@ -256,6 +256,13 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="ignoreHardlinkMatches">
<property name="text">
<string>Ignore duplicates hardlinking to the same file</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>