diff --git a/FileListNode.h b/FileListNode.h new file mode 100644 index 000000000..ad0756526 --- /dev/null +++ b/FileListNode.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * $Id$ + * + * Copyright (c) 2008 Transmission authors and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +#import + + +@interface FileListNode : NSObject +{ + NSString * fName, * fPath; + BOOL fIsFolder; + NSMutableIndexSet * fIndexes; + + uint64_t fSize; + NSImage * fIcon; + + NSMutableArray * fChildren; +} + +- (id) initWithFolderName: (NSString *) name path: (NSString *) path; +- (id) initWithFileName: (NSString *) name path: (NSString *) path size: (uint64_t) size index: (int) index; + +- (void) insertChild: (FileListNode *) child; +- (void) insertIndex: (NSUInteger) index; + +- (BOOL) isFolder; +- (NSString *) name; +- (NSString *) fullPath; +- (NSIndexSet *) indexes; + +- (uint64_t) size; +- (NSImage *) icon; + +- (NSArray *) children; + +@end diff --git a/FileListNode.m b/FileListNode.m new file mode 100644 index 000000000..56a8314ce --- /dev/null +++ b/FileListNode.m @@ -0,0 +1,148 @@ +/****************************************************************************** + * $Id$ + * + * Copyright (c) 2008 Transmission authors and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +#import "FileListNode.h" + +@interface FileListNode (Private) + +- (id) initWithFolder: (BOOL) isFolder name: (NSString *) name path: (NSString *) path; + +@end + +@implementation FileListNode + +- (id) initWithFolderName: (NSString *) name path: (NSString *) path +{ + if ((self = [self initWithFolder: YES name: name path: path])) + { + fChildren = [[NSMutableArray alloc] init]; + } + + return self; +} + +- (id) initWithFileName: (NSString *) name path: (NSString *) path size: (uint64_t) size index: (int) index +{ + if ((self = [self initWithFolder: NO name: name path: path])) + { + fSize = size; + [fIndexes addIndex: index]; + } + + return self; +} + +- (void) insertChild: (FileListNode *) child +{ + [fChildren addObject: child]; +} + +- (void) insertIndex: (NSUInteger) index +{ + [fIndexes addIndex: index]; +} + +- (id) copyWithZone: (NSZone *) zone +{ + return [self retain]; +} + +- (void) dealloc +{ + [fName release]; + [fPath release]; + [fIndexes release]; + + [fIcon release]; + + [fChildren release]; + + [super dealloc]; +} + +- (BOOL) isFolder +{ + return fIsFolder; +} + +- (NSString *) name +{ + return fName; +} + +- (NSString *) fullPath +{ + return fPath; +} + +- (NSIndexSet *) indexes +{ + return fIndexes; +} + +- (uint64_t) size +{ + NSAssert(!fIsFolder, @"method can only be invoked on files currently"); + + return fSize; +} + +- (NSImage *) icon +{ + NSAssert(!fIsFolder, @"method can only be invoked on files currently"); + + if (!fIcon) + { + fIcon = [[[NSWorkspace sharedWorkspace] iconForFileType: [fName pathExtension]] retain]; + [fIcon setFlipped: YES]; + } + return fIcon; +} + +- (NSArray *) children +{ + NSAssert(fIsFolder, @"method can only be invoked on folders"); + + return fChildren; +} + +@end + +@implementation FileListNode (Private) + +- (id) initWithFolder: (BOOL) isFolder name: (NSString *) name path: (NSString *) path +{ + if ((self = [super init])) + { + fIsFolder = isFolder; + fName = [name retain]; + fPath = [[path stringByAppendingPathComponent: name] retain]; + + fIndexes = [[NSMutableIndexSet alloc] init]; + } + + return self; +} + +@end diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index fa132eaee..e629dc74b 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -142,6 +142,7 @@ A26E75880CB6AA7500226674 /* InfoOptions.png in Resources */ = {isa = PBXBuildFile; fileRef = A26E75870CB6AA7500226674 /* InfoOptions.png */; }; A26E75960CB6AB4800226674 /* InfoGeneral.png in Resources */ = {isa = PBXBuildFile; fileRef = A26E75950CB6AB4800226674 /* InfoGeneral.png */; }; A2710E770A86796000CE4F7D /* PrefsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A2710E750A86796000CE4F7D /* PrefsWindow.m */; }; + A2725B6E0DE5C4F5003445E7 /* FileListNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A2725B6D0DE5C4F5003445E7 /* FileListNode.m */; }; A277DA0B0C693D9C00DA2CD4 /* ActionOn.png in Resources */ = {isa = PBXBuildFile; fileRef = A277DA090C693D9C00DA2CD4 /* ActionOn.png */; }; A29576030D11D63C0093B167 /* Creator.xib in Resources */ = {isa = PBXBuildFile; fileRef = A29576010D11D63C0093B167 /* Creator.xib */; }; A29576130D11D8DD0093B167 /* InfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A29576110D11D8DD0093B167 /* InfoWindow.xib */; }; @@ -581,6 +582,8 @@ A26E75950CB6AB4800226674 /* InfoGeneral.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = InfoGeneral.png; path = macosx/Images/InfoGeneral.png; sourceTree = ""; }; A2710E740A86796000CE4F7D /* PrefsWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PrefsWindow.h; path = macosx/PrefsWindow.h; sourceTree = ""; }; A2710E750A86796000CE4F7D /* PrefsWindow.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PrefsWindow.m; path = macosx/PrefsWindow.m; sourceTree = ""; }; + A2725B6C0DE5C4F5003445E7 /* FileListNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileListNode.h; sourceTree = ""; }; + A2725B6D0DE5C4F5003445E7 /* FileListNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileListNode.m; sourceTree = ""; }; A27476FF0CC38EE6003CC76D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = macosx/es.lproj/InfoPlist.strings; sourceTree = ""; }; A27477010CC38EE6003CC76D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = macosx/es.lproj/Localizable.strings; sourceTree = ""; }; A277DA090C693D9C00DA2CD4 /* ActionOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ActionOn.png; path = macosx/Images/ActionOn.png; sourceTree = ""; }; @@ -905,6 +908,8 @@ 4D364D9F091FBB2C00377D12 /* TorrentTableView.m */, 4DCCBB3D09C3D71100D3CABF /* TorrentCell.h */, 4DCCBB3C09C3D71100D3CABF /* TorrentCell.m */, + A2725B6C0DE5C4F5003445E7 /* FileListNode.h */, + A2725B6D0DE5C4F5003445E7 /* FileListNode.m */, A25AFDE70D1038AD0092A1BA /* MenuLabel.h */, A25AFDE80D1038AD0092A1BA /* MenuLabel.m */, A26AF2820D2DC27C00FF7140 /* AddWindowController.h */, @@ -1997,6 +2002,7 @@ A2FB701C0D95CAEA0001F331 /* GroupsController.m in Sources */, A2D307A40D9EC6870051FD27 /* BlocklistDownloader.m in Sources */, A2DF57740DE46A6A000795D5 /* QuickLookController.m in Sources */, + A2725B6E0DE5C4F5003445E7 /* FileListNode.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macosx/FileNameCell.m b/macosx/FileNameCell.m index 6ad5eccb0..eb7aee561 100644 --- a/macosx/FileNameCell.m +++ b/macosx/FileNameCell.m @@ -25,6 +25,7 @@ #import "FileNameCell.h" #import "FileOutlineView.h" #import "Torrent.h" +#import "FileListNode.h" #import "NSApplicationAdditions.h" #import "NSStringAdditions.h" @@ -91,8 +92,9 @@ - (NSImage *) image { - NSImage * image = [[self objectValue] objectForKey: @"Icon"]; - if (!image) + FileListNode * node = (FileListNode *)[self objectValue]; + NSImage * image; + if ([node isFolder]) { if (!fFolderImage) { @@ -101,6 +103,9 @@ } image = fFolderImage; } + else + image = [node icon]; + return image; } @@ -110,7 +115,7 @@ result.origin.x += PADDING_HORIZONAL; - const float IMAGE_SIZE = [[[self objectValue] objectForKey: @"IsFolder"] boolValue] ? IMAGE_FOLDER_SIZE : IMAGE_ICON_SIZE; + const float IMAGE_SIZE = [(FileListNode *)[self objectValue] isFolder] ? IMAGE_FOLDER_SIZE : IMAGE_ICON_SIZE; result.origin.y += (result.size.height - IMAGE_SIZE) * 0.5; result.size = NSMakeSize(IMAGE_SIZE, IMAGE_SIZE); @@ -138,7 +143,7 @@ && [[self highlightColorWithFrame: cellFrame inView: controlView] isEqual: [NSColor alternateSelectedControlColor]]) specialColor = [NSColor whiteColor]; else if ([[(FileOutlineView *)[self controlView] torrent] checkForFiles: - [[self objectValue] objectForKey: @"Indexes"]] == NSOffState) + [(FileListNode *)[self objectValue] indexes]] == NSOffState) specialColor = [NSColor disabledControlTextColor]; else; @@ -147,7 +152,7 @@ [titleString drawInRect: titleRect]; //status - if (![[[self objectValue] objectForKey: @"IsFolder"] boolValue]) + if (![(FileListNode *)[self objectValue] isFolder]) { NSAttributedString * statusString = [self attributedStatusWithColor: specialColor ? specialColor : [NSColor darkGrayColor]]; NSRect statusRect = [self rectForStatusWithString: statusString inBounds: cellFrame]; @@ -165,7 +170,7 @@ NSRect result = bounds; - if (![[[self objectValue] objectForKey: @"IsFolder"] boolValue]) + if (![(FileListNode *)[self objectValue] isFolder]) { result.origin.x += PADDING_HORIZONAL + IMAGE_ICON_SIZE + PADDING_BETWEEN_IMAGE_AND_TITLE; result.origin.y += PADDING_ABOVE_TITLE_FILE; @@ -183,7 +188,7 @@ - (NSRect) rectForStatusWithString: (NSAttributedString *) string inBounds: (NSRect) bounds { - if ([[[self objectValue] objectForKey: @"IsFolder"] boolValue]) + if ([(FileListNode *)[self objectValue] isFolder]) return NSZeroRect; NSSize statusSize = [string size]; @@ -204,7 +209,7 @@ if (color) [fTitleAttributes setObject: color forKey: NSForegroundColorAttributeName]; - NSString * title = [[self objectValue] objectForKey: @"Name"]; + NSString * title = [(FileListNode *)[self objectValue] name]; return [[[NSAttributedString alloc] initWithString: title attributes: fTitleAttributes] autorelease]; } @@ -214,11 +219,11 @@ [fStatusAttributes setObject: color forKey: NSForegroundColorAttributeName]; Torrent * torrent = [(FileOutlineView *)[self controlView] torrent]; - float percent = [torrent fileProgress: [[[self objectValue] objectForKey: @"Indexes"] firstIndex]] * 100.0; + FileListNode * node = (FileListNode *)[self objectValue]; + float percent = [torrent fileProgress: [[node indexes] firstIndex]] * 100.0; NSString * status = [NSString localizedStringWithFormat: NSLocalizedString(@"%.2f%% of %@", - "Inspector -> Files tab -> file status string"), percent, - [NSString stringForFileSize: [[[self objectValue] objectForKey: @"Size"] unsignedLongLongValue]]]; + "Inspector -> Files tab -> file status string"), percent, [NSString stringForFileSize: [node size]]]; return [[[NSAttributedString alloc] initWithString: status attributes: fStatusAttributes] autorelease]; } diff --git a/macosx/FileOutlineController.m b/macosx/FileOutlineController.m index 348327079..4821866d0 100644 --- a/macosx/FileOutlineController.m +++ b/macosx/FileOutlineController.m @@ -26,6 +26,7 @@ #import "Torrent.h" #import "FileOutlineView.h" #import "FilePriorityCell.h" +#import "FileListNode.h" #import "QuickLookController.h" #import "NSApplicationAdditions.h" @@ -101,23 +102,26 @@ typedef enum if (!item) return fTorrent ? [[fTorrent fileList] count] : 0; else - return [[item objectForKey: @"IsFolder"] boolValue] ? [[item objectForKey: @"Children"] count] : 0; + { + FileListNode * node = (FileListNode *)item; + return [node isFolder] ? [[node children] count] : 0; + } } - (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item { - return [[item objectForKey: @"IsFolder"] boolValue]; + return [(FileListNode *)item isFolder]; } - (id) outlineView: (NSOutlineView *) outlineView child: (int) index ofItem: (id) item { - return [(item ? [item objectForKey: @"Children"] : [fTorrent fileList]) objectAtIndex: index]; + return [(item ? [(FileListNode *)item children] : [fTorrent fileList]) objectAtIndex: index]; } - (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item { if ([[tableColumn identifier] isEqualToString: @"Check"]) - return [NSNumber numberWithInt: [fTorrent checkForFiles: [item objectForKey: @"Indexes"]]]; + return [NSNumber numberWithInt: [fTorrent checkForFiles: [(FileListNode *)item indexes]]]; else return item; } @@ -127,7 +131,7 @@ typedef enum { NSString * identifier = [tableColumn identifier]; if ([identifier isEqualToString: @"Check"]) - [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [item objectForKey: @"Indexes"]]]; + [cell setEnabled: [fTorrent canChangeDownloadCheckForFiles: [(FileListNode *)item indexes]]]; else if ([identifier isEqualToString: @"Priority"]) { [cell setRepresentedObject: item]; @@ -148,7 +152,7 @@ typedef enum if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) indexSet = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTorrent fileCount])]; else - indexSet = [item objectForKey: @"Indexes"]; + indexSet = [(FileListNode *)item indexes]; [fTorrent setFileCheckState: [object intValue] != NSOffState ? NSOnState : NSOffState forIndexes: indexSet]; [fOutline reloadData]; @@ -159,7 +163,7 @@ typedef enum - (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item { - return [item objectForKey: @"Name"]; + return [(FileListNode *)item name]; } - (NSString *) outlineView: (NSOutlineView *) outlineView toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect @@ -167,7 +171,7 @@ typedef enum { NSString * ident = [tableColumn identifier]; if ([ident isEqualToString: @"Name"]) - return [[fTorrent downloadFolder] stringByAppendingPathComponent: [item objectForKey: @"Path"]]; + return [[fTorrent downloadFolder] stringByAppendingPathComponent: [(FileListNode *)item fullPath]]; else if ([ident isEqualToString: @"Check"]) { switch ([cell state]) @@ -182,7 +186,7 @@ typedef enum } else if ([ident isEqualToString: @"Priority"]) { - NSSet * priorities = [fTorrent filePrioritiesForIndexes: [item objectForKey: @"Indexes"]]; + NSSet * priorities = [fTorrent filePrioritiesForIndexes: [(FileListNode *)item indexes]]; switch ([priorities count]) { case 0: @@ -209,7 +213,7 @@ typedef enum - (float) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item { - if ([[item objectForKey: @"IsFolder"] boolValue]) + if ([(FileListNode *)item isFolder]) return ROW_SMALL_HEIGHT; else return [outlineView rowHeight]; @@ -223,7 +227,7 @@ typedef enum NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet]; int i; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) - [itemIndexes addIndexes: [[fOutline itemAtRow: i] objectForKey: @"Indexes"]]; + [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]]; [fTorrent setFileCheckState: state forIndexes: itemIndexes]; [fOutline reloadData]; @@ -235,7 +239,7 @@ typedef enum NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet]; int i; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) - [itemIndexes addIndexes: [[fOutline itemAtRow: i] objectForKey: @"Indexes"]]; + [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]]; [fTorrent setFileCheckState: NSOnState forIndexes: itemIndexes]; @@ -265,7 +269,7 @@ typedef enum NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet]; int i; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) - [itemIndexes addIndexes: [[fOutline itemAtRow: i] objectForKey: @"Indexes"]]; + [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]]; [fTorrent setFilePriority: priority forIndexes: itemIndexes]; [fOutline reloadData]; @@ -278,7 +282,7 @@ typedef enum int i; for (i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) [[NSWorkspace sharedWorkspace] selectFile: [folder stringByAppendingPathComponent: - [[fOutline itemAtRow: i] objectForKey: @"Path"]] inFileViewerRootedAtPath: nil]; + [[fOutline itemAtRow: i] fullPath]] inFileViewerRootedAtPath: nil]; } #warning make real view controller (Leopard-only) so that Command-R will work @@ -296,7 +300,7 @@ typedef enum int i; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) if ([[NSFileManager defaultManager] fileExistsAtPath: - [downloadFolder stringByAppendingPathComponent: [[[fTorrent fileList] objectAtIndex: i] objectForKey: @"Path"]]]) + [downloadFolder stringByAppendingPathComponent: [[[fTorrent fileList] objectAtIndex: i] fullPath]]]) return YES; return NO; } @@ -310,7 +314,7 @@ typedef enum NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet]; int i, state = ([menuItem tag] == FILE_CHECK_TAG) ? NSOnState : NSOffState; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) - [itemIndexes addIndexes: [[fOutline itemAtRow: i] objectForKey: @"Indexes"]]; + [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]]; return [fTorrent checkForFiles: itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles: itemIndexes]; } @@ -324,7 +328,7 @@ typedef enum NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet]; int i; for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i]) - [itemIndexes addIndexes: [[fOutline itemAtRow: i] objectForKey: @"Indexes"]]; + [itemIndexes addIndexes: [[fOutline itemAtRow: i] indexes]]; return [fTorrent canChangeDownloadCheckForFiles: itemIndexes]; } @@ -357,7 +361,7 @@ typedef enum NSIndexSet * fileIndexSet; for (i = [indexSet firstIndex]; i != NSNotFound && (!current || !other); i = [indexSet indexGreaterThanIndex: i]) { - fileIndexSet = [[fOutline itemAtRow: i] objectForKey: @"Indexes"]; + fileIndexSet = [[fOutline itemAtRow: i] indexes]; if (![fTorrent canChangeDownloadCheckForFiles: fileIndexSet]) continue; else if ([fTorrent hasFilePriority: priority forIndexes: fileIndexSet]) diff --git a/macosx/FileOutlineView.m b/macosx/FileOutlineView.m index d767032a4..13db0801a 100644 --- a/macosx/FileOutlineView.m +++ b/macosx/FileOutlineView.m @@ -26,6 +26,7 @@ #import "FileNameCell.h" #import "FilePriorityCell.h" #import "Torrent.h" +#import "FileListNode.h" #import "QuickLookController.h" #import "CTGradient.h" @@ -179,7 +180,7 @@ if (![self isRowSelected: row]) { NSDictionary * item = [self itemAtRow: row]; - NSIndexSet * indexes = [item objectForKey: @"Indexes"]; + NSIndexSet * indexes = [(FileListNode *)item indexes]; if ([fTorrent checkForFiles: indexes] != NSOffState) { diff --git a/macosx/FilePriorityCell.m b/macosx/FilePriorityCell.m index b523e718d..53504f980 100644 --- a/macosx/FilePriorityCell.m +++ b/macosx/FilePriorityCell.m @@ -24,6 +24,7 @@ #import "FilePriorityCell.h" #import "FileOutlineView.h" +#import "FileListNode.h" #import "Torrent.h" @implementation FilePriorityCell @@ -73,7 +74,7 @@ FileOutlineView * controlView = (FileOutlineView *)[self controlView]; Torrent * torrent = [controlView torrent]; - [torrent setFilePriority: priority forIndexes: [[self representedObject] objectForKey: @"Indexes"]]; + [torrent setFilePriority: priority forIndexes: [(FileListNode *)[self representedObject] indexes]]; [controlView reloadData]; } @@ -101,8 +102,8 @@ - (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView { Torrent * torrent = [(FileOutlineView *)controlView torrent]; - NSDictionary * dict = [self representedObject]; - NSSet * priorities = [torrent filePrioritiesForIndexes: [dict objectForKey: @"Indexes"]]; + FileListNode * node = [self representedObject]; + NSSet * priorities = [torrent filePrioritiesForIndexes: [node indexes]]; int count = [priorities count]; if (fHoverRow && count > 0) diff --git a/macosx/InfoWindowController.m b/macosx/InfoWindowController.m index 7c77fc873..09e1dccb5 100644 --- a/macosx/InfoWindowController.m +++ b/macosx/InfoWindowController.m @@ -25,6 +25,7 @@ #import "InfoWindowController.h" #import "InfoTabButtonCell.h" #import "FileOutlineView.h" +#import "FileListNode.h" #import "QuickLookController.h" #import "NSApplicationAdditions.h" #import "NSStringAdditions.h" @@ -907,9 +908,9 @@ typedef enum int i; for (i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) { - NSDictionary * item = [fileOutlineView itemAtRow: i]; - if ([[item objectForKey: @"IsFolder"] boolValue] || [torrent fileProgress: [[item objectForKey: @"Indexes"] firstIndex]] == 1.0) - [urlArray addObject: [NSURL fileURLWithPath: [folder stringByAppendingPathComponent: [item objectForKey: @"Path"]]]]; + FileListNode * item = [fileOutlineView itemAtRow: i]; + if ([item isFolder] || [torrent fileProgress: [[item indexes] firstIndex]] == 1.0) + [urlArray addObject: [NSURL fileURLWithPath: [folder stringByAppendingPathComponent: [item fullPath]]]]; } return urlArray; @@ -924,8 +925,8 @@ typedef enum int i; for (i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) { - NSDictionary * item = [fileOutlineView itemAtRow: i]; - if ([[item objectForKey: @"IsFolder"] boolValue] || [torrent fileProgress: [[item objectForKey: @"Indexes"] firstIndex]] == 1.0) + FileListNode * item = [fileOutlineView itemAtRow: i]; + if ([item isFolder] || [torrent fileProgress: [[item indexes] firstIndex]] == 1.0) return YES; } @@ -943,8 +944,8 @@ typedef enum int row; for (row = visibleRows.location; row < NSMaxRange(visibleRows); row++) { - id rowItem = [fileOutlineView itemAtRow: row]; - if ([[folder stringByAppendingPathComponent: [rowItem objectForKey: @"Path"]] isEqualToString: fullPath]) + FileListNode * rowItem = [fileOutlineView itemAtRow: row]; + if ([[folder stringByAppendingPathComponent: [rowItem fullPath]] isEqualToString: fullPath]) { NSRect frame = [fileOutlineView iconRectForRow: row]; frame.origin = [fileOutlineView convertPoint: frame.origin toView: nil]; diff --git a/macosx/QuickLookController.h b/macosx/QuickLookController.h index a1ed8fbed..443ec01a4 100644 --- a/macosx/QuickLookController.h +++ b/macosx/QuickLookController.h @@ -1,7 +1,7 @@ /****************************************************************************** * $Id$ * - * Copyright (c) 2007-2008 Transmission authors and contributors + * Copyright (c) 2008 Transmission authors and contributors * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/macosx/QuickLookController.m b/macosx/QuickLookController.m index 96e738e06..5bbee8c1e 100644 --- a/macosx/QuickLookController.m +++ b/macosx/QuickLookController.m @@ -1,7 +1,7 @@ /****************************************************************************** * $Id$ * - * Copyright (c) 2007-2008 Transmission authors and contributors + * Copyright (c) 2008 Transmission authors and contributors * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -49,9 +49,8 @@ QuickLookController * fQuickLookInstance = nil; return fQuickLookInstance; } -// This is the QuickLook delegate method -// It should return the frame for the item represented by the URL -// If an empty frame is returned then the panel will fade in/out instead +//QuickLook delegate method +//returns the frame for the item represented by the URL, or an empty frame to fade in/out instead - (NSRect) previewPanel: (NSPanel *) panel frameForURL: (NSURL *) url { if ([fInfoController shouldQuickLookFileView]) @@ -65,8 +64,7 @@ QuickLookController * fQuickLookInstance = nil; if (!fQuickLookAvailable) return NO; - NSArray * urlArray = nil; - + NSArray * urlArray; if ([fInfoController shouldQuickLookFileView]) urlArray = [fInfoController quickLookURLs]; else @@ -74,7 +72,7 @@ QuickLookController * fQuickLookInstance = nil; if (urlArray && [urlArray count] > 0) { - [[QLPreviewPanel sharedPreviewPanel] setURLs: urlArray currentIndex: 0 preservingDisplayState: YES]; + [[QLPreviewPanel sharedPreviewPanel] setURLs: urlArray]; return YES; } else @@ -83,6 +81,9 @@ QuickLookController * fQuickLookInstance = nil; - (BOOL) canQuickLook { + if (!fQuickLookAvailable) + return NO; + if ([fInfoController shouldQuickLookFileView]) return [fInfoController canQuickLook]; else diff --git a/macosx/Torrent.m b/macosx/Torrent.m index de8bda658..63137bbe4 100644 --- a/macosx/Torrent.m +++ b/macosx/Torrent.m @@ -24,6 +24,7 @@ #import "Torrent.h" #import "GroupsController.h" +#import "FileListNode.h" #import "NSApplicationAdditions.h" #import "NSStringAdditions.h" @@ -43,8 +44,7 @@ - (void) updateDownloadFolder; - (void) createFileList; -- (void) insertPath: (NSMutableArray *) components forSiblings: (NSMutableArray *) siblings previousPath: (NSString *) previousPath - fileSize: (uint64_t) size index: (int) index; +- (void) insertPath: (NSMutableArray *) components forParent: (FileListNode *) parent fileSize: (uint64_t) size index: (int) index; - (void) completenessChange: (NSNumber *) status; @@ -1648,78 +1648,90 @@ void completenessChangeCallback(tr_torrent * torrent, cp_status_t status, void * - (void) createFileList { - int count = [self fileCount], i; - NSMutableArray * fileList = [[NSMutableArray alloc] initWithCapacity: count]; - - for (i = 0; i < count; i++) + if ([self folder]) { - tr_file * file = &fInfo->files[i]; + int count = [self fileCount], i; + NSMutableArray * fileList = [[NSMutableArray alloc] initWithCapacity: count]; - NSMutableArray * pathComponents = [[[NSString stringWithUTF8String: file->name] pathComponents] mutableCopy]; - NSString * path; - if ([self folder]) + for (i = 0; i < count; i++) { - path = [pathComponents objectAtIndex: 0]; - [pathComponents removeObjectAtIndex: 0]; + tr_file * file = &fInfo->files[i]; + + NSMutableArray * pathComponents = [[[NSString stringWithUTF8String: file->name] pathComponents] mutableCopy]; + NSString * path = [pathComponents objectAtIndex: 0]; + NSString * name = [pathComponents objectAtIndex: 1]; + [pathComponents removeObjectsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, 2)]]; + + if ([pathComponents count] > 0) + { + //determine if node already exists + NSEnumerator * enumerator = [fileList objectEnumerator]; + FileListNode * node; + while ((node = [enumerator nextObject])) + if ([[node name] isEqualToString: name]) + break; + + if (!node) + { + node = [[FileListNode alloc] initWithFolderName: name path: path]; + [fileList addObject: node]; + [node release]; + } + + [self insertPath: pathComponents forParent: node fileSize: file->length index: i]; + } + else + { + FileListNode * node = [[FileListNode alloc] initWithFileName: name path: path size: file->length index: i]; + [fileList addObject: node]; + [node release]; + } + + [pathComponents release]; } - else - path = @""; - [self insertPath: pathComponents forSiblings: fileList previousPath: path fileSize: file->length index: i]; - [pathComponents release]; + fFileList = [[NSArray alloc] initWithArray: fileList]; + [fileList release]; + } + else + { + FileListNode * node = [[FileListNode alloc] initWithFileName: [self name] path: @"" size: [self size] index: 0]; + fFileList = [[NSArray arrayWithObject: node] retain]; + [node release]; } - - fFileList = [[NSArray alloc] initWithArray: fileList]; - [fileList release]; } -- (void) insertPath: (NSMutableArray *) components forSiblings: (NSMutableArray *) siblings previousPath: (NSString *) previousPath - fileSize: (uint64_t) size index: (int) index +- (void) insertPath: (NSMutableArray *) components forParent: (FileListNode *) parent fileSize: (uint64_t) size index: (int) index { NSString * name = [components objectAtIndex: 0]; BOOL isFolder = [components count] > 1; - NSMutableDictionary * dict = nil; + FileListNode * node = nil; if (isFolder) { - NSEnumerator * enumerator = [siblings objectEnumerator]; - while ((dict = [enumerator nextObject])) - if ([[dict objectForKey: @"Name"] isEqualToString: name] && [[dict objectForKey: @"IsFolder"] boolValue]) + NSEnumerator * enumerator = [[parent children] objectEnumerator]; + while ((node = [enumerator nextObject])) + if ([[node name] isEqualToString: name] && [node isFolder]) break; } - NSString * currentPath = [previousPath stringByAppendingPathComponent: name]; - - //create new folder or item if it doesn't already exist - if (!dict) + //create new folder or file if it doesn't already exist + if (!node) { - dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: name, @"Name", - [NSNumber numberWithBool: isFolder], @"IsFolder", currentPath, @"Path", nil]; - [siblings addObject: dict]; - if (isFolder) - { - [dict setObject: [NSMutableArray array] forKey: @"Children"]; - [dict setObject: [NSMutableIndexSet indexSetWithIndex: index] forKey: @"Indexes"]; - } + node = [[FileListNode alloc] initWithFolderName: name path: [parent fullPath]]; else - { - [dict setObject: [NSIndexSet indexSetWithIndex: index] forKey: @"Indexes"]; - [dict setObject: [NSNumber numberWithUnsignedLongLong: size] forKey: @"Size"]; - - NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFileType: [name pathExtension]]; - [icon setFlipped: YES]; - [dict setObject: icon forKey: @"Icon"]; - } + node = [[FileListNode alloc] initWithFileName: name path: [parent fullPath] size: size index: index]; + + [parent insertChild: node]; } - else - [[dict objectForKey: @"Indexes"] addIndex: index]; if (isFolder) { + [node insertIndex: index]; + [components removeObjectAtIndex: 0]; - [self insertPath: components forSiblings: [dict objectForKey: @"Children"] previousPath: currentPath fileSize: size - index: index]; + [self insertPath: components forParent: node fileSize: size index: index]; } }