diff --git a/cocoa/base/AppDelegate.m b/cocoa/base/AppDelegate.m index 63c6a6c9..6cdda0b8 100644 --- a/cocoa/base/AppDelegate.m +++ b/cocoa/base/AppDelegate.m @@ -158,14 +158,6 @@ http://www.hardcoded.net/licenses/bsd_license - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [[ProgressController mainProgressController] setWorker:py]; - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - //Restore Columns - NSArray *columnsOrder = [ud arrayForKey:@"columnsOrder"]; - NSDictionary *columnsWidth = [ud dictionaryForKey:@"columnsWidth"]; - if ([columnsOrder count]) - [[self resultWindow] restoreColumnsPosition:columnsOrder widths:columnsWidth]; - else - [[self resultWindow] resetColumnsToDefault:nil]; [py initialRegistrationSetup]; [py loadSession]; } @@ -191,8 +183,6 @@ http://www.hardcoded.net/licenses/bsd_license - (void)applicationWillTerminate:(NSNotification *)aNotification { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - [ud setObject: [[self resultWindow] getColumnsOrder] forKey:@"columnsOrder"]; - [ud setObject: [[self resultWindow] getColumnsWidth] forKey:@"columnsWidth"]; NSInteger sc = [ud integerForKey:@"sessionCountSinceLastIgnorePurge"]; if (sc >= 10) { sc = -1; diff --git a/cocoa/base/PyResultTable.h b/cocoa/base/PyResultTable.h index b7ea6c31..84d5ebca 100644 --- a/cocoa/base/PyResultTable.h +++ b/cocoa/base/PyResultTable.h @@ -15,7 +15,7 @@ http://www.hardcoded.net/licenses/bsd_license - (BOOL)deltaValuesMode; - (void)setDeltaValuesMode:(BOOL)aDeltaValuesMode; -- (NSString *)valueForRow:(NSInteger)rowIndex column:(NSInteger)aColumn; +- (NSString *)valueForRow:(NSInteger)rowIndex column:(NSString *)aColumn; - (BOOL)renameSelected:(NSString *)aNewName; - (void)sortBy:(NSInteger)aIdentifier ascending:(BOOL)aAscending; - (void)markSelected; diff --git a/cocoa/base/ResultTable.h b/cocoa/base/ResultTable.h index e2f68256..eca0c840 100644 --- a/cocoa/base/ResultTable.h +++ b/cocoa/base/ResultTable.h @@ -9,14 +9,17 @@ http://www.hardcoded.net/licenses/bsd_license #import #import #import "HSTable.h" +#import "HSColumns.h" #import "PyResultTable.h" @interface ResultTable : HSTable { NSIndexSet *_deltaColumns; + HSColumns *columns; } - (id)initWithPyParent:(id)aPyParent view:(NSTableView *)aTableView; - (PyResultTable *)py; +- (HSColumns *)columns; - (BOOL)powerMarkerMode; - (void)setPowerMarkerMode:(BOOL)aPowerMarkerMode; - (BOOL)deltaValuesMode; diff --git a/cocoa/base/ResultTable.m b/cocoa/base/ResultTable.m index c00b71e3..953fcec2 100644 --- a/cocoa/base/ResultTable.m +++ b/cocoa/base/ResultTable.m @@ -21,6 +21,7 @@ http://www.hardcoded.net/licenses/bsd_license - (id)initWithPyParent:(id)aPyParent view:(NSTableView *)aTableView { self = [super initWithPyClassName:@"PyResultTable" pyParent:aPyParent view:aTableView]; + columns = [[HSColumns alloc] initWithPy:[[self py] columns] tableView:aTableView]; [self connect]; return self; } @@ -28,6 +29,7 @@ http://www.hardcoded.net/licenses/bsd_license - (void)dealloc { [self disconnect]; + [columns release]; [_deltaColumns release]; [super dealloc]; } @@ -58,6 +60,11 @@ http://www.hardcoded.net/licenses/bsd_license } /* Public */ +- (HSColumns *)columns +{ + return columns; +} + - (BOOL)powerMarkerMode { return [[self py] powerMarkerMode]; @@ -108,8 +115,7 @@ http://www.hardcoded.net/licenses/bsd_license if ([identifier isEqual:@"marked"]) { return [[self py] valueForColumn:@"marked" row:row]; } - NSInteger columnId = [identifier integerValue]; - return [[self py] valueForRow:row column:columnId]; + return [[self py] valueForRow:row column:identifier]; } - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)column row:(NSInteger)row @@ -118,8 +124,8 @@ http://www.hardcoded.net/licenses/bsd_license 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]; + else if ([identifier isEqual:@"name"]) { + NSString *oldName = [[self py] valueForRow:row column:identifier]; NSString *newName = object; if (![newName isEqual:oldName]) { BOOL renamed = [[self py] renameSelected:newName]; diff --git a/cocoa/base/ResultWindow.h b/cocoa/base/ResultWindow.h index 0eded9ec..8d4bf570 100644 --- a/cocoa/base/ResultWindow.h +++ b/cocoa/base/ResultWindow.h @@ -27,7 +27,6 @@ http://www.hardcoded.net/licenses/bsd_license AppDelegateBase *app; PyDupeGuruBase *py; NSMenu *columnsMenu; - NSMutableArray *_resultColumns; ResultTable *table; StatsLabel *statsLabel; ProblemDialog *problemDialog; @@ -41,10 +40,7 @@ http://www.hardcoded.net/licenses/bsd_license /* Helpers */ - (void)fillColumnsMenu; -- (NSTableColumn *)getColumnForIdentifier:(NSInteger)aIdentifier title:(NSString *)aTitle width:(NSInteger)aWidth refCol:(NSTableColumn *)aColumn; - (NSArray *)getColumnsOrder; -- (NSDictionary *)getColumnsWidth; -- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth; - (void)sendMarkedToTrash:(BOOL)hardlinkDeleted; - (void)updateOptionSegments; diff --git a/cocoa/base/ResultWindow.m b/cocoa/base/ResultWindow.m index d520e5c6..2417fafc 100644 --- a/cocoa/base/ResultWindow.m +++ b/cocoa/base/ResultWindow.m @@ -50,9 +50,6 @@ http://www.hardcoded.net/licenses/bsd_license /* Virtual */ - (void)initResultColumns { - NSUserDefaults *udc = [NSUserDefaultsController sharedUserDefaultsController]; - NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; - [refCol bind:@"fontSize" toObject:udc withKeyPath:@"values.TableFontSize" options:nil]; } - (void)setScanOptions @@ -62,14 +59,15 @@ http://www.hardcoded.net/licenses/bsd_license /* Helpers */ - (void)fillColumnsMenu { - // The columns menu is supposed to be empty and initResultColumns must have been called - for (NSTableColumn *col in _resultColumns) - { - NSMenuItem *mi = [columnsMenu addItemWithTitle:[[col headerCell] stringValue] action:@selector(toggleColumn:) keyEquivalent:@""]; - [mi setTag:[[col identifier] integerValue]]; + NSArray *menuItems = [[[table columns] py] menuItems]; + for (NSInteger i=0; i < [menuItems count]; i++) { + NSArray *pair = [menuItems objectAtIndex:i]; + NSString *display = [pair objectAtIndex:0]; + BOOL marked = n2b([pair objectAtIndex:1]); + NSMenuItem *mi = [columnsMenu addItemWithTitle:display action:@selector(toggleColumn:) keyEquivalent:@""]; [mi setTarget:self]; - if ([[matches tableColumns] containsObject:col]) - [mi setState:NSOnState]; + [mi setState:marked ? NSOnState : NSOffState]; + [mi setTag:i]; } [columnsMenu addItem:[NSMenuItem separatorItem]]; NSMenuItem *mi = [columnsMenu addItemWithTitle:TR(@"Reset to Default") @@ -77,21 +75,6 @@ http://www.hardcoded.net/licenses/bsd_license [mi setTarget:self]; } -- (NSTableColumn *)getColumnForIdentifier:(NSInteger)aIdentifier title:(NSString *)aTitle width:(NSInteger)aWidth refCol:(NSTableColumn *)aColumn -{ - NSNumber *n = [NSNumber numberWithInteger:aIdentifier]; - NSTableColumn *col = [[NSTableColumn alloc] initWithIdentifier:[n stringValue]]; - [col setWidth:aWidth]; - [col setEditable:NO]; - [[col dataCell] setFont:[[aColumn dataCell] font]]; - [[col headerCell] setStringValue:aTitle]; - [col setResizingMask:NSTableColumnUserResizingMask]; - [col setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:[n stringValue] ascending:YES]]; - NSUserDefaults *udc = [NSUserDefaultsController sharedUserDefaultsController]; - [col bind:@"fontSize" toObject:udc withKeyPath:@"values.TableFontSize" options:nil]; - return col; -} - //Returns an array of identifiers, in order. - (NSArray *)getColumnsOrder { @@ -103,40 +86,6 @@ http://www.hardcoded.net/licenses/bsd_license return result; } -- (NSDictionary *)getColumnsWidth -{ - NSMutableDictionary *result = [NSMutableDictionary dictionary]; - for (NSTableColumn *col in [matches tableColumns]) { - NSString *colId = [col identifier]; - NSNumber *width = [NSNumber numberWithDouble:[col width]]; - [result setObject:width forKey:colId]; - } - return result; -} - -- (void)restoreColumnsPosition:(NSArray *)aColumnsOrder widths:(NSDictionary *)aColumnsWidth -{ - for (NSMenuItem *mi in [columnsMenu itemArray]) { - if ([mi state] == NSOnState) { - [self toggleColumn:mi]; - } - } - //Add columns and set widths - for (NSString *colId in aColumnsOrder) { - NSInteger colIndex = [colId integerValue]; - if ((colIndex == 0) && (![colId isEqual:@"0"])) { - continue; - } - NSTableColumn *col = [_resultColumns objectAtIndex:colIndex]; - NSNumber *width = [aColumnsWidth objectForKey:[col identifier]]; - NSMenuItem *mi = [columnsMenu itemWithTag:colIndex]; - if (width) { - [col setWidth:[width floatValue]]; - } - [self toggleColumn:mi]; - } -} - - (void)sendMarkedToTrash:(BOOL)hardlinkDeleted { NSInteger mark_count = [[py getMarkCount] intValue]; @@ -223,6 +172,7 @@ http://www.hardcoded.net/licenses/bsd_license - (IBAction)exportToXHTML:(id)sender { + // XXX No need to get column order from GUI anymore. NSString *exported = [py exportToXHTMLwithColumns:[self getColumnsOrder]]; [[NSWorkspace sharedWorkspace] openFile:exported]; } @@ -346,7 +296,7 @@ http://www.hardcoded.net/licenses/bsd_license - (IBAction)resetColumnsToDefault:(id)sender { - // Virtual + [[[table columns] py] resetToDefaults]; } - (IBAction)revealSelected:(id)sender @@ -384,19 +334,8 @@ http://www.hardcoded.net/licenses/bsd_license - (IBAction)toggleColumn:(id)sender { NSMenuItem *mi = sender; - NSString *colId = [NSString stringWithFormat:@"%d",[mi tag]]; - NSTableColumn *col = [matches tableColumnWithIdentifier:colId]; - if (col == nil) { - //Add Column - col = [_resultColumns objectAtIndex:[mi tag]]; - [matches addTableColumn:col]; - [mi setState:NSOnState]; - } - else { - //Remove column - [matches removeTableColumn:col]; - [mi setState:NSOffState]; - } + BOOL checked = [[[table columns] py] toggleMenuItem:[mi tag]]; + [mi setState:checked ? NSOnState : NSOffState]; } - (IBAction)toggleDetailsPanel:(id)sender diff --git a/cocoa/base/en.lproj/ResultWindow.xib b/cocoa/base/en.lproj/ResultWindow.xib index f4e25ab6..ed972c01 100644 --- a/cocoa/base/en.lproj/ResultWindow.xib +++ b/cocoa/base/en.lproj/ResultWindow.xib @@ -2,13 +2,13 @@ 1060 - 11B26 - 1617 - 1138 - 566.00 + 11C74 + 1938 + 1138.23 + 567.00 com.apple.InterfaceBuilder.CocoaPlugin - 1617 + 1938 NSPopUpButton @@ -18,13 +18,12 @@ NSToolbarFlexibleSpaceItem NSCustomObject NSTableView - NSTextField NSSearchField + NSTextField NSSearchFieldCell NSWindowTemplate NSTextFieldCell NSButtonCell - NSTableColumn NSSegmentedControl NSToolbarSpaceItem NSPopUpButtonCell @@ -40,7 +39,10 @@ com.apple.InterfaceBuilder.CocoaPlugin - + + PluginDependencyRecalculationVersion + + ResultWindow @@ -162,7 +164,7 @@ 67239424 0 - + LucidaGrande 11 16 @@ -240,7 +242,7 @@ 6 System controlTextColor - + 3 MAA @@ -703,94 +705,7 @@ - - - marked - 26 - 26 - 26 - - 75628096 - 134219776 - - - LucidaGrande - 11 - 3100 - - - 6 - System - headerColor - - - - 6 - System - headerTextColor - - - - - 67239424 - 131072 - - - - 1211912703 - 2 - - NSImage - NSSwitch - - - NSSwitch - - - - 200 - 25 - - YES - - - - 0 - 195 - 16 - 3.4028234663852886e+38 - - 75628096 - 2048 - Name - - - - - - 337772096 - 2048 - Text Cell - - - - 6 - System - controlBackgroundColor - - - - - 2 - YES - - - 0 - YES - compare: - - - + 3 2 @@ -821,7 +736,12 @@ - + + 6 + System + controlBackgroundColor + + 4 @@ -894,14 +814,6 @@ - - - delegate - - - - 45 - window @@ -1094,6 +1006,14 @@ 81 + + + toggleQuicklookPanel: + + + + 87 + showDirectoryWindow: @@ -1102,6 +1022,14 @@ 82 + + + delegate + + + + 45 + menu @@ -1110,14 +1038,6 @@ 83 - - - toggleQuicklookPanel: - - - - 87 - rowHeight: values.TableFontSize @@ -1216,10 +1136,7 @@ 8 - - - - + @@ -1232,32 +1149,6 @@ - - 11 - - - - - - - - 12 - - - - - - - - 13 - - - - - 14 - - - 67 @@ -1530,10 +1421,6 @@ {{324, 305}, {557, 400}} com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1905,7 +1792,7 @@ com.apple.InterfaceBuilder.CocoaPlugin.macosx - + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 @@ -1918,7 +1805,6 @@ {9, 8} {7, 2} {21, 16} - {15, 15} {32, 32} diff --git a/cocoa/inter/result_table.py b/cocoa/inter/result_table.py index b2a2a55f..6cc4c75c 100644 --- a/cocoa/inter/result_table.py +++ b/cocoa/inter/result_table.py @@ -21,7 +21,7 @@ class PyResultTable(PyTable): def setDeltaValuesMode_(self, value): self.py.delta_values = value - @signature('@@:ii') + @signature('@@:i@') def valueForRow_column_(self, row_index, column): return self.py.get_row_value(row_index, column) diff --git a/cocoa/me/ResultWindow.m b/cocoa/me/ResultWindow.m index b7a4b0bf..6e5b1f9c 100644 --- a/cocoa/me/ResultWindow.m +++ b/cocoa/me/ResultWindow.m @@ -34,33 +34,39 @@ http://www.hardcoded.net/licenses/bsd_license - (void)initResultColumns { - [super initResultColumns]; - NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; - _resultColumns = [[NSMutableArray alloc] init]; - [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name - [_resultColumns addObject:[self getColumnForIdentifier:1 title:TRCOL(@"Folder") width:120 refCol:refCol]]; - NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TRCOL(@"Size (MB)") width:63 refCol:refCol]; - [[sizeCol dataCell] setAlignment:NSRightTextAlignment]; - [_resultColumns addObject:sizeCol]; - NSTableColumn *timeCol = [self getColumnForIdentifier:3 title:TRCOL(@"Time") width:50 refCol:refCol]; - [[timeCol dataCell] setAlignment:NSRightTextAlignment]; - [_resultColumns addObject:timeCol]; - NSTableColumn *brCol = [self getColumnForIdentifier:4 title:TRCOL(@"Bitrate") width:50 refCol:refCol]; - [[brCol dataCell] setAlignment:NSRightTextAlignment]; - [_resultColumns addObject:brCol]; - [_resultColumns addObject:[self getColumnForIdentifier:5 title:TRCOL(@"Sample Rate") width:60 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:6 title:TRCOL(@"Kind") width:40 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:7 title:TRCOL(@"Modification") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:8 title:TRCOL(@"Title") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:9 title:TRCOL(@"Artist") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:10 title:TRCOL(@"Album") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:11 title:TRCOL(@"Genre") width:80 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:12 title:TRCOL(@"Year") width:40 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:13 title:TRCOL(@"Track Number") width:40 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:14 title:TRCOL(@"Comment") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:15 title:TRCOL(@"Match %") width:57 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:16 title:TRCOL(@"Words Used") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:17 title:TRCOL(@"Dupe Count") width:80 refCol:refCol]]; + HSColumnDef defs[] = { + {@"marked", 26, 26, 26, NO, [NSButtonCell class]}, + {@"name", 235, 16, 0, YES, nil}, + {@"folder_path", 120, 16, 0, YES, nil}, + {@"size", 63, 16, 0, YES, nil}, + {@"duration", 50, 16, 0, YES, nil}, + {@"bitrate", 50, 16, 0, YES, nil}, + {@"samplerate", 60, 16, 0, YES, nil}, + {@"extension", 40, 16, 0, YES, nil}, + {@"mtime", 120, 16, 0, YES, nil}, + {@"title", 120, 16, 0, YES, nil}, + {@"artist", 120, 16, 0, YES, nil}, + {@"album", 120, 16, 0, YES, nil}, + {@"genre", 80, 16, 0, YES, nil}, + {@"year", 40, 16, 0, YES, nil}, + {@"track", 40, 16, 0, YES, nil}, + {@"comment", 120, 16, 0, YES, nil}, + {@"percentage", 57, 16, 0, YES, nil}, + {@"words", 120, 16, 0, YES, nil}, + {@"dupe_count", 80, 16, 0, YES, nil}, + nil + }; + [[self columns] initializeColumns:defs]; + NSTableColumn *c = [matches tableColumnWithIdentifier:@"marked"]; + [[c dataCell] setButtonType:NSSwitchButton]; + [[c dataCell] setControlSize:NSSmallControlSize]; + c = [[self tableView] tableColumnWithIdentifier:@"size"]; + [[c dataCell] setAlignment:NSRightTextAlignment]; + c = [[self tableView] tableColumnWithIdentifier:@"duration"]; + [[c dataCell] setAlignment:NSRightTextAlignment]; + c = [[self tableView] tableColumnWithIdentifier:@"bitrate"]; + [[c dataCell] setAlignment:NSRightTextAlignment]; + [[table columns] restoreColumns]; } /* Actions */ @@ -69,25 +75,6 @@ http://www.hardcoded.net/licenses/bsd_license [(PyDupeGuru *)py scanDeadTracks]; } -- (IBAction)resetColumnsToDefault:(id)sender -{ - NSMutableArray *columnsOrder = [NSMutableArray array]; - [columnsOrder addObject:@"0"]; - [columnsOrder addObject:@"2"]; - [columnsOrder addObject:@"3"]; - [columnsOrder addObject:@"4"]; - [columnsOrder addObject:@"6"]; - [columnsOrder addObject:@"15"]; - NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary]; - [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]; -} - /* Notifications */ - (void)jobCompleted:(NSNotification *)aNotification { diff --git a/cocoa/pe/ResultWindow.m b/cocoa/pe/ResultWindow.m index 26ad1cd6..5dedc3e6 100644 --- a/cocoa/pe/ResultWindow.m +++ b/cocoa/pe/ResultWindow.m @@ -16,19 +16,25 @@ http://www.hardcoded.net/licenses/bsd_license /* Override */ - (void)initResultColumns { - [super initResultColumns]; - NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; - _resultColumns = [[NSMutableArray alloc] init]; - [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name - [_resultColumns addObject:[self getColumnForIdentifier:1 title:TRCOL(@"Folder") width:120 refCol:refCol]]; - NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TRCOL(@"Size (KB)") width:63 refCol:refCol]; - [[sizeCol dataCell] setAlignment:NSRightTextAlignment]; - [_resultColumns addObject:sizeCol]; - [_resultColumns addObject:[self getColumnForIdentifier:3 title:TRCOL(@"Kind") width:40 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:4 title:TRCOL(@"Dimensions") width:80 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:5 title:TRCOL(@"Modification") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:6 title:TRCOL(@"Match %") width:58 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:7 title:TRCOL(@"Dupe Count") width:80 refCol:refCol]]; + HSColumnDef defs[] = { + {@"marked", 26, 26, 26, NO, [NSButtonCell class]}, + {@"name", 162, 16, 0, YES, nil}, + {@"folder_path", 142, 16, 0, YES, nil}, + {@"size", 63, 16, 0, YES, nil}, + {@"extension", 40, 16, 0, YES, nil}, + {@"dimensions", 73, 16, 0, YES, nil}, + {@"mtime", 120, 16, 0, YES, nil}, + {@"percentage", 58, 16, 0, YES, nil}, + {@"dupe_count", 80, 16, 0, YES, nil}, + nil + }; + [[self columns] initializeColumns:defs]; + NSTableColumn *c = [matches tableColumnWithIdentifier:@"marked"]; + [[c dataCell] setButtonType:NSSwitchButton]; + [[c dataCell] setControlSize:NSSmallControlSize]; + c = [[self tableView] tableColumnWithIdentifier:@"size"]; + [[c dataCell] setAlignment:NSRightTextAlignment]; + [[table columns] restoreColumns]; } - (void)setScanOptions @@ -50,21 +56,4 @@ http://www.hardcoded.net/licenses/bsd_license return; [(PyDupeGuru *)py clearPictureCache]; } - -- (IBAction)resetColumnsToDefault:(id)sender -{ - NSMutableArray *columnsOrder = [NSMutableArray array]; - [columnsOrder addObject:@"0"]; - [columnsOrder addObject:@"1"]; - [columnsOrder addObject:@"2"]; - [columnsOrder addObject:@"4"]; - [columnsOrder addObject:@"6"]; - NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary]; - [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"]; - [self restoreColumnsPosition:columnsOrder widths:columnsWidth]; -} @end \ No newline at end of file diff --git a/cocoa/se/ResultWindow.m b/cocoa/se/ResultWindow.m index 3b87ac92..43cc3e40 100644 --- a/cocoa/se/ResultWindow.m +++ b/cocoa/se/ResultWindow.m @@ -15,19 +15,25 @@ http://www.hardcoded.net/licenses/bsd_license /* Override */ - (void)initResultColumns { - [super initResultColumns]; - NSTableColumn *refCol = [matches tableColumnWithIdentifier:@"0"]; - _resultColumns = [[NSMutableArray alloc] init]; - [_resultColumns addObject:[matches tableColumnWithIdentifier:@"0"]]; // File Name - [_resultColumns addObject:[self getColumnForIdentifier:1 title:TRCOL(@"Folder") width:120 refCol:refCol]]; - NSTableColumn *sizeCol = [self getColumnForIdentifier:2 title:TRCOL(@"Size (KB)") width:63 refCol:refCol]; - [[sizeCol dataCell] setAlignment:NSRightTextAlignment]; - [_resultColumns addObject:sizeCol]; - [_resultColumns addObject:[self getColumnForIdentifier:3 title:TRCOL(@"Kind") width:40 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:4 title:TRCOL(@"Modification") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:5 title:TRCOL(@"Match %") width:60 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:6 title:TRCOL(@"Words Used") width:120 refCol:refCol]]; - [_resultColumns addObject:[self getColumnForIdentifier:7 title:TRCOL(@"Dupe Count") width:80 refCol:refCol]]; + HSColumnDef defs[] = { + {@"marked", 26, 26, 26, NO, [NSButtonCell class]}, + {@"name", 195, 16, 0, YES, nil}, + {@"folder_path", 183, 16, 0, YES, nil}, + {@"size", 63, 16, 0, YES, nil}, + {@"extension", 40, 16, 0, YES, nil}, + {@"mtime", 120, 16, 0, YES, nil}, + {@"percentage", 60, 16, 0, YES, nil}, + {@"words", 120, 16, 0, YES, nil}, + {@"dupe_count", 80, 16, 0, YES, nil}, + nil + }; + [[table columns] initializeColumns:defs]; + NSTableColumn *c = [matches tableColumnWithIdentifier:@"marked"]; + [[c dataCell] setButtonType:NSSwitchButton]; + [[c dataCell] setControlSize:NSSmallControlSize]; + c = [matches tableColumnWithIdentifier:@"size"]; + [[c dataCell] setAlignment:NSRightTextAlignment]; + [[table columns] restoreColumns]; } - (void)setScanOptions @@ -44,20 +50,4 @@ http://www.hardcoded.net/licenses/bsd_license int sizeThreshold = [ud boolForKey:@"ignoreSmallFiles"] ? smallFileThreshold * 1024 : 0; // The py side wants bytes [_py setSizeThreshold:sizeThreshold]; } - -/* Actions */ -- (IBAction)resetColumnsToDefault:(id)sender -{ - NSMutableArray *columnsOrder = [NSMutableArray array]; - [columnsOrder addObject:@"0"]; - [columnsOrder addObject:@"1"]; - [columnsOrder addObject:@"2"]; - [columnsOrder addObject:@"5"]; - NSMutableDictionary *columnsWidth = [NSMutableDictionary dictionary]; - [columnsWidth setObject:i2n(195) forKey:@"0"]; - [columnsWidth setObject:i2n(183) forKey:@"1"]; - [columnsWidth setObject:i2n(63) forKey:@"2"]; - [columnsWidth setObject:i2n(60) forKey:@"5"]; - [self restoreColumnsPosition:columnsOrder widths:columnsWidth]; -} @end diff --git a/cocoa/se/dupeguru.xcodeproj/project.pbxproj b/cocoa/se/dupeguru.xcodeproj/project.pbxproj index 327ba1eb..55e1e9dc 100644 --- a/cocoa/se/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/se/dupeguru.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; }; CE5335FC142BBFAF008E5374 /* HSQuicklook.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5335FB142BBFAF008E5374 /* HSQuicklook.m */; }; CE533603142BC034008E5374 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE533602142BC034008E5374 /* Quartz.framework */; }; + CE54A87E148046F9008EEA77 /* HSColumns.m in Sources */ = {isa = PBXBuildFile; fileRef = CE54A87D148046F9008EEA77 /* HSColumns.m */; }; CE647E571173024A006D28BA /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE647E551173024A006D28BA /* ProblemDialog.m */; }; CE665B3013225ADD003F5CFB /* ExtraFairwareReminder.m in Sources */ = {isa = PBXBuildFile; fileRef = CE665B2E13225ADD003F5CFB /* ExtraFairwareReminder.m */; }; CE665B3313225AF8003F5CFB /* ExtraFairwareReminder.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE665B3113225AF8003F5CFB /* ExtraFairwareReminder.xib */; }; @@ -126,6 +127,9 @@ CE5335FA142BBFAF008E5374 /* HSQuicklook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSQuicklook.h; path = ../../cocoalib/HSQuicklook.h; sourceTree = ""; }; CE5335FB142BBFAF008E5374 /* HSQuicklook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSQuicklook.m; path = ../../cocoalib/HSQuicklook.m; sourceTree = ""; }; CE533602142BC034008E5374 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; + CE54A87A14804687008EEA77 /* PyColumns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyColumns.h; sourceTree = ""; }; + CE54A87C148046F9008EEA77 /* HSColumns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSColumns.h; sourceTree = ""; }; + CE54A87D148046F9008EEA77 /* HSColumns.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSColumns.m; sourceTree = ""; }; CE647E541173024A006D28BA /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; }; CE647E551173024A006D28BA /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; }; CE647E561173024A006D28BA /* PyProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PyProblemDialog.h; path = ../base/PyProblemDialog.h; sourceTree = SOURCE_ROOT; }; @@ -386,6 +390,8 @@ CE76FDC7111EE38E006618EA /* controllers */ = { isa = PBXGroup; children = ( + CE54A87C148046F9008EEA77 /* HSColumns.h */, + CE54A87D148046F9008EEA77 /* HSColumns.m */, CEBE4D72111F0EE1009AAC6D /* HSWindowController.h */, CEBE4D73111F0EE1009AAC6D /* HSWindowController.m */, CE76FDDD111EE42F006618EA /* HSOutline.h */, @@ -406,6 +412,7 @@ CE76FDCC111EE38E006618EA /* proxies */ = { isa = PBXGroup; children = ( + CE54A87A14804687008EEA77 /* PyColumns.h */, CE76FDCD111EE38E006618EA /* PyGUI.h */, CE76FDCE111EE38E006618EA /* PyOutline.h */, CE8C53B61173248F0011B41F /* PyTable.h */, @@ -636,6 +643,7 @@ CE41672D141FE1E5004F3F0B /* HSSelectableList.m in Sources */, CE89240A14239CC30024CE4E /* PrioritizeList.m in Sources */, CE5335FC142BBFAF008E5374 /* HSQuicklook.m in Sources */, + CE54A87E148046F9008EEA77 /* HSColumns.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/core/app.py b/core/app.py index b3315330..b2387933 100644 --- a/core/app.py +++ b/core/app.py @@ -41,8 +41,6 @@ class JobType: Copy = 'job_copy' Delete = 'job_delete' -Column = namedtuple('Column', 'attr display') - def format_timestamp(t, delta): if delta: return format_time_decimal(t) @@ -68,10 +66,10 @@ def format_dupe_count(c): return str(c) if c else '---' def cmp_value(dupe, column): - if column.attr == 'name': + if column.name == 'name': value = rem_file_ext(dupe.name) else: - value = getattr(dupe, column.attr, '') + value = getattr(dupe, column.name, '') return value.lower() if isinstance(value, str) else value class DupeGuru(RegistrableApplication, Broadcaster): @@ -411,6 +409,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): self.directories.save_to_file(op.join(self.appdata, 'last_directories.xml')) p = op.join(self.appdata, 'ignore_list.xml') self.scanner.ignore_list.save_to_xml(p) + self.notify('save_session') def save_as(self, filename): self.results.save_to_xml(filename) diff --git a/core/gui/result_table.py b/core/gui/result_table.py index 2e0bb667..026de188 100644 --- a/core/gui/result_table.py +++ b/core/gui/result_table.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Created By: Virgil Dupras # Created On: 2010-02-11 # Copyright 2011 Hardcoded Software (http://www.hardcoded.net) @@ -10,6 +9,7 @@ from operator import attrgetter from hscommon.gui.table import GUITable, Row +from hscommon.gui.column import Columns from .base import GUIObject @@ -55,6 +55,8 @@ class ResultTable(GUIObject, GUITable): def __init__(self, view, app): GUIObject.__init__(self, view, app) GUITable.__init__(self) + self.COLUMNS = app.COLUMNS + self.columns = Columns(self, prefaccess=app, savename='ResultTable') self._power_marker = False self._delta_values = False self._sort_descriptors = (0, True) @@ -63,6 +65,7 @@ class ResultTable(GUIObject, GUITable): def connect(self): GUIObject.connect(self) self._refresh_with_view() + self.columns.restore_columns() def _restore_selection(self, previous_selection): if self.app.selected_dupes: @@ -162,3 +165,6 @@ class ResultTable(GUIObject, GUITable): self.select(indexes) self.view.refresh() + def save_session(self): + self.columns.save_columns() + diff --git a/core_me/app.py b/core_me/app.py index d4d4b43f..94fd6532 100644 --- a/core_me/app.py +++ b/core_me/app.py @@ -7,8 +7,9 @@ from hscommon.trans import trget from hscommon.util import format_size, format_time +from hscommon.gui.column import Column -from core.app import (DupeGuru as DupeGuruBase, Column, format_timestamp, +from core.app import (DupeGuru as DupeGuruBase, format_timestamp, format_perc, format_words, format_dupe_count, cmp_value) from . import prioritize from . import __appname__ @@ -19,24 +20,25 @@ coltr = trget('columns') class DupeGuru(DupeGuruBase): NAME = __appname__ COLUMNS = [ + Column('marked', ''), Column('name', coltr("Filename")), - Column('folder_path', coltr("Folder")), - Column('size', coltr("Size (MB)")), - Column('duration', coltr("Time")), - Column('bitrate', coltr("Bitrate")), - Column('samplerate', coltr("Sample Rate")), - Column('extension', coltr("Kind")), - Column('mtime', coltr("Modification")), - Column('title', coltr("Title")), - Column('artist', coltr("Artist")), - Column('album', coltr("Album")), - Column('genre', coltr("Genre")), - Column('year', coltr("Year")), - Column('track', coltr("Track Number")), - Column('comment', coltr("Comment")), - Column('percentage', coltr("Match %")), - Column('words', coltr("Words Used")), - Column('dupe_count', coltr("Dupe Count")), + Column('folder_path', coltr("Folder"), visible=False, optional=True), + Column('size', coltr("Size (MB)"), optional=True), + Column('duration', coltr("Time"), optional=True), + Column('bitrate', coltr("Bitrate"), optional=True), + Column('samplerate', coltr("Sample Rate"), visible=False, optional=True), + Column('extension', coltr("Kind"), optional=True), + Column('mtime', coltr("Modification"), visible=False, optional=True), + Column('title', coltr("Title"), visible=False, optional=True), + Column('artist', coltr("Artist"), visible=False, optional=True), + Column('album', coltr("Album"), visible=False, optional=True), + Column('genre', coltr("Genre"), visible=False, optional=True), + Column('year', coltr("Year"), visible=False, optional=True), + Column('track', coltr("Track Number"), visible=False, optional=True), + Column('comment', coltr("Comment"), visible=False, optional=True), + Column('percentage', coltr("Match %"), optional=True), + Column('words', coltr("Words Used"), visible=False, optional=True), + Column('dupe_count', coltr("Dupe Count"), visible=False, optional=True), ] DELTA_COLUMNS = {2, 3, 4, 5, 7} METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist', @@ -69,26 +71,26 @@ class DupeGuru(DupeGuruBase): else: percentage = group.percentage dupe_count = len(group.dupes) - return [ - dupe.name, - str(dupe.folder_path), - format_size(size, 2, 2, False), - format_time(duration, with_hours=False), - str(bitrate), - str(samplerate), - dupe.extension, - format_timestamp(mtime,delta and m), - dupe.title, - dupe.artist, - dupe.album, - dupe.genre, - dupe.year, - str(dupe.track), - dupe.comment, - format_perc(percentage), - format_words(dupe.words) if hasattr(dupe, 'words') else '', - format_dupe_count(dupe_count) - ] + return { + 'name': dupe.name, + 'folder_path': str(dupe.folder_path), + 'size': format_size(size, 2, 2, False), + 'duration': format_time(duration, with_hours=False), + 'bitrate': str(bitrate), + 'samplerate': str(samplerate), + 'extension': dupe.extension, + 'mtime': format_timestamp(mtime,delta and m), + 'title': dupe.title, + 'artist': dupe.artist, + 'album': dupe.album, + 'genre': dupe.genre, + 'year': dupe.year, + 'track': str(dupe.track), + 'comment': dupe.comment, + 'percentage': format_perc(percentage), + 'words': format_words(dupe.words) if hasattr(dupe, 'words') else '', + 'dupe_count': format_dupe_count(dupe_count), + } def _get_dupe_sort_key(self, dupe, get_group, key, delta): if key == self.MATCHPERC_COL: diff --git a/core_pe/app.py b/core_pe/app.py index 92cc7487..1e6fd844 100644 --- a/core_pe/app.py +++ b/core_pe/app.py @@ -9,8 +9,9 @@ import os.path as op from hscommon.trans import trget from hscommon.util import format_size +from hscommon.gui.column import Column -from core.app import (DupeGuru as DupeGuruBase, Column, format_timestamp, format_perc, +from core.app import (DupeGuru as DupeGuruBase, format_timestamp, format_perc, format_dupe_count, cmp_value) from .scanner import ScannerPE from . import prioritize @@ -27,14 +28,15 @@ def get_delta_dimensions(value, ref_value): class DupeGuru(DupeGuruBase): NAME = __appname__ COLUMNS = [ + Column('marked', ''), Column('name', coltr("Filename")), - Column('folder_path', coltr("Folder")), - Column('size', coltr("Size (KB)")), - Column('extension', coltr("Kind")), - Column('dimensions', coltr("Dimensions")), - Column('mtime', coltr("Modification")), - Column('percentage', coltr("Match %")), - Column('dupe_count', coltr("Dupe Count")), + Column('folder_path', coltr("Folder"), optional=True), + Column('size', coltr("Size (KB)"), optional=True), + Column('extension', coltr("Kind"), visible=False, optional=True), + Column('dimensions', coltr("Dimensions"), optional=True), + Column('mtime', coltr("Modification"), visible=False, optional=True), + Column('percentage', coltr("Match %"), optional=True), + Column('dupe_count', coltr("Dupe Count"), visible=False, optional=True), ] DELTA_COLUMNS = {2, 4, 5} METADATA_TO_READ = ['size', 'mtime', 'dimensions'] @@ -64,16 +66,16 @@ class DupeGuru(DupeGuruBase): percentage = group.percentage dupe_count = len(group.dupes) dupe_folder_path = getattr(dupe, 'display_folder_path', dupe.folder_path) - return [ - dupe.name, - str(dupe_folder_path), - format_size(size, 0, 1, False), - dupe.extension, - format_dimensions(dimensions), - format_timestamp(mtime, delta and m), - format_perc(percentage), - format_dupe_count(dupe_count) - ] + return { + 'name': dupe.name, + 'folder_path': str(dupe_folder_path), + 'size': format_size(size, 0, 1, False), + 'extension': dupe.extension, + 'dimensions': format_dimensions(dimensions), + 'mtime': format_timestamp(mtime, delta and m), + 'percentage': format_perc(percentage), + 'dupe_count': format_dupe_count(dupe_count), + } def _get_dupe_sort_key(self, dupe, get_group, key, delta): if key == self.MATCHPERC_COL: diff --git a/core_se/app.py b/core_se/app.py index f24b6cf7..ee57aca7 100644 --- a/core_se/app.py +++ b/core_se/app.py @@ -7,8 +7,9 @@ from hscommon.trans import trget from hscommon.util import format_size +from hscommon.gui.column import Column -from core.app import (DupeGuru as DupeGuruBase, Column, format_timestamp, format_perc, +from core.app import (DupeGuru as DupeGuruBase, format_timestamp, format_perc, format_words, format_dupe_count, cmp_value) from core import prioritize from . import __appname__ @@ -18,14 +19,15 @@ coltr = trget('columns') class DupeGuru(DupeGuruBase): NAME = __appname__ COLUMNS = [ + Column('marked', ''), Column('name', coltr("Filename")), - Column('folder_path', coltr("Folder")), - Column('size', coltr("Size (KB)")), - Column('extension', coltr("Kind")), - Column('mtime', coltr("Modification")), - Column('percentage', coltr("Match %")), - Column('words', coltr("Words Used")), - Column('dupe_count', coltr("Dupe Count")), + Column('folder_path', coltr("Folder"), optional=True), + Column('size', coltr("Size (KB)"), optional=True), + Column('extension', coltr("Kind"), visible=False, optional=True), + Column('mtime', coltr("Modification"), visible=False, optional=True), + Column('percentage', coltr("Match %"), optional=True), + Column('words', coltr("Words Used"), visible=False, optional=True), + Column('dupe_count', coltr("Dupe Count"), visible=False, optional=True), ] DELTA_COLUMNS = {2, 4} METADATA_TO_READ = ['size', 'mtime'] @@ -49,16 +51,16 @@ class DupeGuru(DupeGuruBase): else: percentage = group.percentage dupe_count = len(group.dupes) - return [ - dupe.name, - str(dupe.folder_path), - format_size(size, 0, 1, False), - dupe.extension, - format_timestamp(mtime, delta and m), - format_perc(percentage), - format_words(dupe.words) if hasattr(dupe, 'words') else '', - format_dupe_count(dupe_count) - ] + return { + 'name': dupe.name, + 'folder_path': str(dupe.folder_path), + 'size': format_size(size, 0, 1, False), + 'extension': dupe.extension, + 'mtime': format_timestamp(mtime, delta and m), + 'percentage': format_perc(percentage), + 'words': format_words(dupe.words) if hasattr(dupe, 'words') else '', + 'dupe_count': format_dupe_count(dupe_count), + } def _get_dupe_sort_key(self, dupe, get_group, key, delta): if key == self.MATCHPERC_COL: