diff --git a/cocoa/base/PyDupeGuru.h b/cocoa/base/PyDupeGuru.h index ebe1a325..ddfb2ed8 100644 --- a/cocoa/base/PyDupeGuru.h +++ b/cocoa/base/PyDupeGuru.h @@ -48,8 +48,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 diff --git a/cocoa/base/ResultWindow.m b/cocoa/base/ResultWindow.m index 076fa225..7e131743 100644 --- a/cocoa/base/ResultWindow.m +++ b/cocoa/base/ResultWindow.m @@ -174,7 +174,7 @@ http://www.hardcoded.net/licenses/hs_license 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 setRemoveEmptyFolders:n2b([ud objectForKey:@"removeEmptyFolders"])]; [py deleteMarked]; } @@ -187,7 +187,7 @@ 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]]; } @@ -264,7 +264,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"]]; } } diff --git a/cocoa/me/AppDelegate.m b/cocoa/me/AppDelegate.m index 81209634..d0a6ec14 100644 --- a/cocoa/me/AppDelegate.m +++ b/cocoa/me/AppDelegate.m @@ -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"]; diff --git a/cocoa/me/ResultWindow.m b/cocoa/me/ResultWindow.m index 21cf5c39..cbed7c89 100644 --- a/cocoa/me/ResultWindow.m +++ b/cocoa/me/ResultWindow.m @@ -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 */ @@ -66,7 +66,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) diff --git a/cocoa/me/dupeguru.xcodeproj/project.pbxproj b/cocoa/me/dupeguru.xcodeproj/project.pbxproj index 2bab3650..e78a9ab4 100644 --- a/cocoa/me/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/me/dupeguru.xcodeproj/project.pbxproj @@ -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 = ""; }; - 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 = ""; }; 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 = ""; }; CE900AD1109B238600754048 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = ""; }; CE900AD6109B2A9B00754048 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = ""; }; + 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; }; diff --git a/cocoa/me/xib/Preferences.xib b/cocoa/me/xib/Preferences.xib index 94797c42..e18d22b4 100644 --- a/cocoa/me/xib/Preferences.xib +++ b/cocoa/me/xib/Preferences.xib @@ -2,13 +2,13 @@ 1050 - 10D573 - 740 + 10F569 + 788 1038.29 - 460.00 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 740 + 788 YES @@ -41,7 +41,7 @@ YES - CustomCommand + ignoreHardlinkMatches YES @@ -698,7 +698,7 @@ 292 - {{14, 192}, {85, 13}} + {{14, 172}, {85, 13}} YES @@ -714,7 +714,7 @@ 292 - {{14, 164}, {324, 17}} + {{14, 144}, {324, 17}} YES @@ -730,7 +730,7 @@ 292 - {{104, 185}, {234, 26}} + {{104, 165}, {234, 26}} YES @@ -800,7 +800,7 @@ 266 - {{17, 142}, {326, 22}} + {{17, 122}, {326, 22}} YES @@ -827,6 +827,27 @@ + + + 256 + {{15, 195}, {265, 18}} + + YES + + 67239424 + 0 + Ignore duplicates hardlinking to the same file + + + 1211912703 + 2 + + + + 200 + 25 + + {{10, 33}, {360, 234}} @@ -1461,6 +1482,22 @@ 124 + + + value: values.ignoreHardlinkMatches + + + + + + value: values.ignoreHardlinkMatches + value + values.ignoreHardlinkMatches + 2 + + + 128 + @@ -1563,9 +1600,10 @@ YES - + + @@ -2020,6 +2058,20 @@ + + 125 + + + YES + + + + + + 126 + + + @@ -2045,6 +2097,9 @@ 121.IBPluginDependency 122.IBPluginDependency 123.IBPluginDependency + 125.IBPluginDependency + 125.ImportedFromIB2 + 126.IBPluginDependency 13.IBPluginDependency 13.ImportedFromIB2 14.IBPluginDependency @@ -2165,6 +2220,9 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2174,9 +2232,9 @@ com.apple.InterfaceBuilder.CocoaPlugin - {{318, 425}, {406, 326}} + {{555, 271}, {406, 326}} com.apple.InterfaceBuilder.CocoaPlugin - {{318, 425}, {406, 326}} + {{555, 271}, {406, 326}} {213, 107} @@ -2275,7 +2333,7 @@ - 124 + 128 @@ -2825,6 +2883,13 @@ showWindow: id + + showWindow: + + showWindow: + id + + IBFrameworkSource AppKit.framework/Headers/NSWindowController.h @@ -2833,6 +2898,7 @@ 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -2844,5 +2910,18 @@ YES ../dupeguru.xcodeproj 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + diff --git a/cocoa/pe/AppDelegate.m b/cocoa/pe/AppDelegate.m index abc51358..e3956c73 100644 --- a/cocoa/pe/AppDelegate.m +++ b/cocoa/pe/AppDelegate.m @@ -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"]; diff --git a/cocoa/pe/ResultWindow.m b/cocoa/pe/ResultWindow.m index 888cddd2..be5c584a 100644 --- a/cocoa/pe/ResultWindow.m +++ b/cocoa/pe/ResultWindow.m @@ -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 */ @@ -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) diff --git a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj index 48246d6c..7e3efe33 100644 --- a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; @@ -170,6 +168,11 @@ CECA899A09DB132E00A3D774 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = DetailsPanel.h; sourceTree = ""; }; CECA899B09DB132E00A3D774 /* DetailsPanel.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = DetailsPanel.m; sourceTree = ""; }; CEEB135109C837A2004D2330 /* dupeguru.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = dupeguru.icns; sourceTree = ""; }; + 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; }; diff --git a/cocoa/pe/xib/Preferences.xib b/cocoa/pe/xib/Preferences.xib index 2444e86a..fa8b332f 100644 --- a/cocoa/pe/xib/Preferences.xib +++ b/cocoa/pe/xib/Preferences.xib @@ -2,13 +2,13 @@ 1050 - 10D573 - 740 + 10F569 + 788 1038.29 - 460.00 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 740 + 788 YES @@ -41,7 +41,7 @@ YES - CustomCommand + ignoreHardlinkMatches YES @@ -406,10 +406,31 @@ 25 + + + 256 + {{15, 100}, {265, 18}} + + YES + + 67239424 + 0 + Ignore duplicates hardlinking to the same file + + + 1211912703 + 2 + + + + 200 + 25 + + 292 - {{14, 97}, {85, 13}} + {{14, 77}, {85, 13}} YES @@ -425,7 +446,7 @@ 292 - {{14, 69}, {306, 17}} + {{14, 49}, {306, 17}} YES @@ -441,7 +462,7 @@ 292 - {{104, 90}, {216, 26}} + {{104, 70}, {216, 26}} YES @@ -517,7 +538,7 @@ 266 - {{17, 47}, {312, 22}} + {{17, 27}, {312, 22}} YES @@ -790,6 +811,30 @@ 68 + + + nextKeyView + + + + 72 + + + + value: values.ignoreHardlinkMatches + + + + + + value: values.ignoreHardlinkMatches + value + values.ignoreHardlinkMatches + 2 + + + 73 + @@ -892,9 +937,10 @@ YES - + + @@ -1151,6 +1197,20 @@ + + 69 + + + YES + + + + + + 70 + + + @@ -1221,8 +1281,11 @@ 65.IBPluginDependency 66.IBPluginDependency 67.IBPluginDependency + 69.IBPluginDependency + 69.ImportedFromIB2 7.IBPluginDependency 7.ImportedFromIB2 + 70.IBPluginDependency 8.IBPluginDependency 8.ImportedFromIB2 9.IBPluginDependency @@ -1299,6 +1362,9 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin @@ -1318,7 +1384,7 @@ - 68 + 73 @@ -1330,6 +1396,13 @@ ../views/HSOutlineView.h + + NSObject + + IBProjectSource + ../views/HSTableView.h + + NSObject @@ -1868,6 +1941,13 @@ showWindow: id + + showWindow: + + showWindow: + id + + IBFrameworkSource AppKit.framework/Headers/NSWindowController.h @@ -1876,6 +1956,7 @@ 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -1887,5 +1968,18 @@ YES ../dupeguru.xcodeproj 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + diff --git a/cocoa/se/AppDelegate.m b/cocoa/se/AppDelegate.m index f22fabcf..42ead927 100644 --- a/cocoa/se/AppDelegate.m +++ b/cocoa/se/AppDelegate.m @@ -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"]; diff --git a/cocoa/se/ResultWindow.m b/cocoa/se/ResultWindow.m index d35ca977..be00b657 100644 --- a/cocoa/se/ResultWindow.m +++ b/cocoa/se/ResultWindow.m @@ -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 diff --git a/cocoa/se/xib/Preferences.xib b/cocoa/se/xib/Preferences.xib index 6b826e31..62e8fd44 100644 --- a/cocoa/se/xib/Preferences.xib +++ b/cocoa/se/xib/Preferences.xib @@ -2,13 +2,13 @@ 1050 - 10D573 - 740 + 10F569 + 788 1038.29 - 460.00 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 740 + 788 YES @@ -623,10 +623,31 @@ 25 + + + 256 + {{15, 171}, {265, 18}} + + YES + + 67239424 + 0 + Ignore duplicates hardlinking to the same file + + + 1211912703 + 2 + + + + 200 + 25 + + 292 - {{14, 168}, {315, 17}} + {{14, 148}, {315, 17}} YES @@ -642,7 +663,7 @@ 266 - {{17, 138}, {309, 22}} + {{17, 118}, {309, 22}} YES @@ -659,7 +680,7 @@ 292 - {{14, 117}, {85, 13}} + {{14, 97}, {85, 13}} YES @@ -675,7 +696,7 @@ 292 - {{101, 106}, {216, 26}} + {{101, 86}, {216, 26}} YES @@ -1068,6 +1089,22 @@ 140 + + + value: values.ignoreHardlinkMatches + + + + + + value: values.ignoreHardlinkMatches + value + values.ignoreHardlinkMatches + 2 + + + 144 + @@ -1170,6 +1207,7 @@ YES + @@ -1552,6 +1590,20 @@ + + 141 + + + YES + + + + + + 142 + + + @@ -1573,6 +1625,9 @@ 134.IBPluginDependency 138.IBPluginDependency 139.IBPluginDependency + 141.IBPluginDependency + 141.ImportedFromIB2 + 142.IBPluginDependency 51.IBPluginDependency 51.ImportedFromIB2 52.IBEditorWindowLastContentRect @@ -1675,6 +1730,9 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{88, 543}, {389, 302}} com.apple.InterfaceBuilder.CocoaPlugin {{88, 543}, {389, 302}} @@ -1773,7 +1831,7 @@ - 140 + 144 @@ -1785,6 +1843,13 @@ ../views/HSOutlineView.h + + NSObject + + IBProjectSource + ../views/HSTableView.h + + NSObject @@ -2323,6 +2388,13 @@ showWindow: id + + showWindow: + + showWindow: + id + + IBFrameworkSource AppKit.framework/Headers/NSWindowController.h @@ -2331,6 +2403,7 @@ 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -2342,5 +2415,18 @@ YES ../dupeguru.xcodeproj 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + diff --git a/core/app.py b/core/app.py index 206840a0..eba5977c 100644 --- a/core/app.py +++ b/core/app.py @@ -50,6 +50,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): self.options = { 'escape_filter_regexp': True, 'clean_empty_dirs': False, + 'ignore_hardlink_matches': False, } self.selected_dupes = [] @@ -117,6 +118,17 @@ 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 @@ -341,6 +353,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) diff --git a/core/app_cocoa_inter.py b/core/app_cocoa_inter.py index 1d11e13b..87e77e6e 100644 --- a/core/app_cocoa_inter.py +++ b/core/app_cocoa_inter.py @@ -116,15 +116,22 @@ 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: diff --git a/core/tests/app_test.py b/core/tests/app_test.py index 9a40749c..abfc463a 100644 --- a/core/tests/app_test.py +++ b/core/tests/app_test.py @@ -24,6 +24,7 @@ from ..app import DupeGuru as DupeGuruBase from ..gui.details_panel import DetailsPanel from ..gui.directory_tree import DirectoryTree from ..gui.result_table import ResultTable +from ..scanner import ScanType class DupeGuru(DupeGuruBase): def __init__(self): @@ -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 diff --git a/qt/base/app.py b/qt/base/app.py index e5ca785f..7b4639a2 100644 --- a/qt/base/app.py +++ b/qt/base/app.py @@ -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): diff --git a/qt/base/preferences.py b/qt/base/preferences.py index f1768a6a..79f2c96a 100644 --- a/qt/base/preferences.py +++ b/qt/base/preferences.py @@ -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) diff --git a/qt/me/preferences_dialog.py b/qt/me/preferences_dialog.py index d7d6b014..676b0d47 100644 --- a/qt/me/preferences_dialog.py +++ b/qt/me/preferences_dialog.py @@ -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() diff --git a/qt/me/preferences_dialog.ui b/qt/me/preferences_dialog.ui index 6ed46cd1..1e00a211 100644 --- a/qt/me/preferences_dialog.ui +++ b/qt/me/preferences_dialog.ui @@ -310,6 +310,13 @@ + + + + Ignore duplicates hardlinking to the same file + + + diff --git a/qt/pe/preferences_dialog.py b/qt/pe/preferences_dialog.py index ff9a3920..1c7862d5 100644 --- a/qt/pe/preferences_dialog.py +++ b/qt/pe/preferences_dialog.py @@ -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: diff --git a/qt/pe/preferences_dialog.ui b/qt/pe/preferences_dialog.ui index b8bb11cb..c0aa0b8b 100644 --- a/qt/pe/preferences_dialog.ui +++ b/qt/pe/preferences_dialog.ui @@ -150,6 +150,13 @@ + + + + Ignore duplicates hardlinking to the same file + + + diff --git a/qt/se/preferences_dialog.py b/qt/se/preferences_dialog.py index 116dca37..5a9510a0 100644 --- a/qt/se/preferences_dialog.py +++ b/qt/se/preferences_dialog.py @@ -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 @@ -33,6 +34,9 @@ class PreferencesDialog(QDialog, Ui_PreferencesDialog): def _setupUi(self): self.setupUi(self) + if sys.platform not in {'darwin', 'linux2'}: + self.verticalLayout_4.removeWidget(self.ignoreHardlinkMatches) + self.ignoreHardlinkMatches.setHidden(True) def load(self, prefs=None): if prefs is None: @@ -45,6 +49,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 +65,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) diff --git a/qt/se/preferences_dialog.ui b/qt/se/preferences_dialog.ui index 98eb1f2a..217a5cc9 100644 --- a/qt/se/preferences_dialog.ui +++ b/qt/se/preferences_dialog.ui @@ -253,9 +253,16 @@ - + + + + + Ignore duplicates hardlinking to the same file + + +