First commit of collapsable groups. A lot more needs to still be done.

This commit is contained in:
Mitchell Livingston 2008-02-06 23:45:44 +00:00
parent e372450e98
commit a0061f43fb
12 changed files with 2901 additions and 2971 deletions

View File

@ -86,7 +86,6 @@
A2265F420B5EF5F40093DDA5 /* FileNameCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A2265F400B5EF5F40093DDA5 /* FileNameCell.m */; };
A226FDAC0D0CDF20005A7F71 /* libnatpmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C7A118D0D0B2EB800B5701F /* libnatpmp.a */; };
A22A8D560AEEAFA5007E9CB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A22A8D540AEEAFA5007E9CB9 /* Localizable.strings */; };
A22B862D0D47D91300F9BAD9 /* NSMutableArrayAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A22B862C0D47D91300F9BAD9 /* NSMutableArrayAdditions.m */; };
A22D3AA60D00D1790079CFED /* Turtle.png in Resources */ = {isa = PBXBuildFile; fileRef = A22D3AA30D00D1790079CFED /* Turtle.png */; };
A22D3AA70D00D1790079CFED /* TurtleBlue.png in Resources */ = {isa = PBXBuildFile; fileRef = A22D3AA40D00D1790079CFED /* TurtleBlue.png */; };
A231274C0D11D0B7003F9AFF /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A231274B0D11D0B7003F9AFF /* AboutWindow.xib */; };
@ -460,8 +459,6 @@
A223AABB0D22ECE800840069 /* it */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = it; path = macosx/it.lproj/StatsWindow.xib; sourceTree = "<group>"; };
A2265F3F0B5EF5F40093DDA5 /* FileNameCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FileNameCell.h; path = macosx/FileNameCell.h; sourceTree = "<group>"; };
A2265F400B5EF5F40093DDA5 /* FileNameCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = FileNameCell.m; path = macosx/FileNameCell.m; sourceTree = "<group>"; };
A22B862B0D47D91300F9BAD9 /* NSMutableArrayAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSMutableArrayAdditions.h; path = macosx/NSMutableArrayAdditions.h; sourceTree = "<group>"; };
A22B862C0D47D91300F9BAD9 /* NSMutableArrayAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSMutableArrayAdditions.m; path = macosx/NSMutableArrayAdditions.m; sourceTree = "<group>"; };
A22D3AA30D00D1790079CFED /* Turtle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Turtle.png; path = macosx/Images/Turtle.png; sourceTree = "<group>"; };
A22D3AA40D00D1790079CFED /* TurtleBlue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TurtleBlue.png; path = macosx/Images/TurtleBlue.png; sourceTree = "<group>"; };
A231274B0D11D0B7003F9AFF /* AboutWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AboutWindow.xib; path = macosx/AboutWindow.xib; sourceTree = "<group>"; };
@ -1114,8 +1111,6 @@
A21576090C0D449A0057A26A /* NSBezierPathAdditions.m */,
A234D0CF0C79FB3600A82373 /* NSMenuAdditions.h */,
A234D0D00C79FB3600A82373 /* NSMenuAdditions.m */,
A22B862B0D47D91300F9BAD9 /* NSMutableArrayAdditions.h */,
A22B862C0D47D91300F9BAD9 /* NSMutableArrayAdditions.m */,
);
name = Additions;
sourceTree = "<group>";
@ -1798,7 +1793,6 @@
A22180980D148A71007D09ED /* GroupsWindowController.m in Sources */,
A26AF21A0D2DA35A00FF7140 /* FileOutlineController.m in Sources */,
A26AF2840D2DC27C00FF7140 /* AddWindowController.m in Sources */,
A22B862D0D47D91300F9BAD9 /* NSMutableArrayAdditions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -52,7 +52,6 @@ typedef enum
tr_handle * fLib;
NSMutableArray * fTorrents, * fDisplayedTorrents;
NSMutableIndexSet * fDisplayedGroupIndexes;
PrefsController * fPrefsController;
InfoWindowController * fInfoController;
@ -63,7 +62,6 @@ typedef enum
IBOutlet NSWindow * fWindow;
DragOverlayWindow * fOverlayWindow;
IBOutlet NSScrollView * fScrollView;
IBOutlet TorrentTableView * fTableView;
IBOutlet NSMenuItem * fOpenIgnoreDownloadFolder;
@ -183,6 +181,8 @@ typedef enum
- (void) updateUI;
- (void) setBottomCountTextFiltering: (BOOL) filtering;
- (void) updateTorrentsInQueue;
- (int) numToStartFromQueue: (BOOL) downloadQueue;
@ -247,6 +247,8 @@ typedef enum
- (void) setWindowSizeToFit;
- (NSRect) sizedWindowFrame;
- (void) updateForExpandCollape;
- (void) showMainWindow: (id) sender;
- (void) linkHomepage: (id) sender;

View File

@ -38,7 +38,6 @@
#import "NSApplicationAdditions.h"
#import "NSStringAdditions.h"
#import "NSMenuAdditions.h"
#import "NSMutableArrayAdditions.h"
#import "UKKQueue.h"
#import "ExpandedPathToPathTransformer.h"
#import "ExpandedPathToIconTransformer.h"
@ -212,7 +211,6 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
fTorrents = [[NSMutableArray alloc] init];
fDisplayedTorrents = [[NSMutableArray alloc] init];
fDisplayedGroupIndexes = [[NSMutableIndexSet alloc] init];
fMessageController = [[MessageWindowController alloc] init];
fInfoController = [[InfoWindowController alloc] init];
@ -252,7 +250,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
//window min height
NSSize contentMinSize = [fWindow contentMinSize];
contentMinSize.height = [[fWindow contentView] frame].size.height - [fScrollView frame].size.height
contentMinSize.height = [[fWindow contentView] frame].size.height - [[fTableView enclosingScrollView] frame].size.height
+ [fTableView rowHeight] + [fTableView intercellSpacing].height;
[fWindow setContentMinSize: contentMinSize];
@ -324,10 +322,8 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fPrefsController setUpdater: fUpdater];
[fTableView setTorrents: fDisplayedTorrents];
[fTableView setGroupIndexes: fDisplayedGroupIndexes];
[fTableView registerForDraggedTypes: [NSArray arrayWithObject: TORRENT_TABLE_VIEW_DATA_TYPE]];
#warning fix
//[fTableView registerForDraggedTypes: [NSArray arrayWithObject: TORRENT_TABLE_VIEW_DATA_TYPE]];
[fWindow registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, NSURLPboardType, nil]];
//register for sleep notifications
@ -415,7 +411,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
//avoids need of setting delegate
[nc addObserver: self selector: @selector(torrentTableViewSelectionDidChange:)
name: NSTableViewSelectionDidChangeNotification object: fTableView];
name: NSOutlineViewSelectionDidChangeNotification object: fTableView];
[nc addObserver: self selector: @selector(prepareForUpdate:)
name: SUUpdaterWillRestartNotification object: nil];
@ -430,6 +426,9 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[nc addObserver: self selector: @selector(setWindowSizeToFit)
name: @"AutoSizeSettingChange" object: nil];
[nc addObserver: self selector: @selector(updateForExpandCollape)
name: @"OutlineExpandCollapse" object: nil];
[nc addObserver: fWindow selector: @selector(makeKeyWindow)
name: @"MakeWindowKey" object: nil];
@ -589,7 +588,6 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fTorrents release];
[fDisplayedTorrents release];
[fDisplayedGroupIndexes release];
[fOverlayWindow release];
[fIPCController release];
@ -1199,26 +1197,22 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
- (void) removeNoDelete: (id) sender
{
[self removeTorrents: [fTableView selectedTorrents]
deleteData: NO deleteTorrent: NO];
[self removeTorrents: [fTableView selectedTorrents] deleteData: NO deleteTorrent: NO];
}
- (void) removeDeleteData: (id) sender
{
[self removeTorrents: [fTableView selectedTorrents]
deleteData: YES deleteTorrent: NO];
[self removeTorrents: [fTableView selectedTorrents] deleteData: YES deleteTorrent: NO];
}
- (void) removeDeleteTorrent: (id) sender
{
[self removeTorrents: [fTableView selectedTorrents]
deleteData: NO deleteTorrent: YES];
[self removeTorrents: [fTableView selectedTorrents] deleteData: NO deleteTorrent: YES];
}
- (void) removeDeleteDataAndTorrent: (id) sender
{
[self removeTorrents: [fTableView selectedTorrents]
deleteData: YES deleteTorrent: YES];
[self removeTorrents: [fTableView selectedTorrents] deleteData: YES deleteTorrent: YES];
}
- (void) moveDataFiles: (id) sender
@ -1258,8 +1252,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
- (void) copyTorrentFiles: (id) sender
{
[self copyTorrentFileForTorrents: [[NSMutableArray alloc] initWithArray:
[fTableView selectedTorrents]]];
[self copyTorrentFileForTorrents: [[NSMutableArray alloc] initWithArray: [fTableView selectedTorrents]]];
}
- (void) copyTorrentFileForTorrents: (NSMutableArray *) torrents
@ -1457,6 +1450,35 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fBadger updateBadge];
}
- (void) setBottomCountTextFiltering: (BOOL) filtering
{
NSString * totalTorrentsString;
int totalCount = [fTorrents count];
if (totalCount != 1)
totalTorrentsString = [NSString stringWithFormat: NSLocalizedString(@"%d transfers", "Status bar transfer count"), totalCount];
else
totalTorrentsString = NSLocalizedString(@"1 transfer", "Status bar transfer count");
if (filtering)
{
int count = 0, rows = [fTableView numberOfRows];
if (rows > 0 && ![[fTableView itemAtRow: 0] isKindOfClass: [Torrent class]])
{
int i;
for (i = 1; i < [fTableView numberOfRows]; i++)
if ([[fTableView itemAtRow: i] isKindOfClass: [Torrent class]])
count++;
}
else
count = rows;
totalTorrentsString = [NSString stringWithFormat: NSLocalizedString(@"%d of %@", "Status bar transfer count"),
count, totalTorrentsString];
}
[fTotalTorrentsField setStringValue: totalTorrentsString];
}
- (void) updateTorrentsInQueue
{
BOOL download = [fDefaults boolForKey: @"Queue"],
@ -1738,15 +1760,10 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
//actually sort
if ([fDefaults boolForKey: @"SortByGroup"] && [NSApp isOnLeopardOrBetter])
{
NSUInteger i, nextGroup;
for (i = [fDisplayedGroupIndexes firstIndex]; i != NSNotFound; i = nextGroup)
{
nextGroup = [fDisplayedGroupIndexes indexGreaterThanIndex: i];
NSUInteger count = (nextGroup != NSNotFound ? nextGroup : [fDisplayedTorrents count]) - i - 1;
[fDisplayedTorrents sortIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(i+1, count)]
usingDescriptors: descriptors];
}
NSEnumerator * enumerator = [fDisplayedTorrents objectEnumerator];
NSDictionary * dict;
while ((dict = [enumerator nextObject]))
[[dict objectForKey: @"Torrents"] sortUsingDescriptors: descriptors];
}
else
[fDisplayedTorrents sortUsingDescriptors: descriptors];
@ -1758,8 +1775,17 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
- (void) applyFilter: (id) sender
{
NSMutableArray * previousTorrents = [fDisplayedTorrents mutableCopy];
[previousTorrents removeObjectsAtIndexes: fDisplayedGroupIndexes];
//get all the torrents in the table
NSMutableArray * previousTorrents = [NSMutableArray array];
if ([fDisplayedTorrents count] > 0 && ![[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [Torrent class]])
{
NSEnumerator * enumerator = [fDisplayedTorrents objectEnumerator];
NSDictionary * dict;
while ((dict = [enumerator nextObject]))
[previousTorrents addObjectsFromArray: [dict objectForKey: @"Torrents"]];
}
else
[previousTorrents setArray: fDisplayedTorrents];
NSArray * selectedValues = [fTableView selectedValues];
@ -1790,7 +1816,6 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
NSEnumerator * enumerator = [fTorrents objectEnumerator];
Torrent * torrent;
int i = -1;
BOOL isActive;
while ((torrent = [enumerator nextObject]))
{
i++;
@ -1801,7 +1826,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
if ([torrent isSeeding])
{
seeding++;
isActive = ![torrent isStalled];
BOOL isActive = ![torrent isStalled];
if (isActive)
active++;
@ -1811,7 +1836,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
else
{
downloading++;
isActive = ![torrent isStalled];
BOOL isActive = ![torrent isStalled];
if (isActive)
active++;
@ -1874,53 +1899,45 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fPauseFilterButton setCount: paused];
//clear display cache for not-shown torrents
[previousTorrents removeObjectsInArray: fDisplayedTorrents]; //neither array should currently have group items
[previousTorrents removeObjectsInArray: fDisplayedTorrents];
enumerator = [previousTorrents objectEnumerator];
while ((torrent = [enumerator nextObject]))
[torrent setPreviousAmountFinished: NULL];
[previousTorrents release];
//add group items
[fDisplayedGroupIndexes removeAllIndexes];
if ([fDefaults boolForKey: @"SortByGroup"] && [fDisplayedTorrents count] > 0 && [NSApp isOnLeopardOrBetter])
//place torrents into groups
BOOL groupRows = [fDefaults boolForKey: @"SortByGroup"];
if (groupRows && [fDisplayedTorrents count] > 0 && [NSApp isOnLeopardOrBetter])
{
NSSortDescriptor * groupDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"groupOrderValue" ascending: YES] autorelease];
[fDisplayedTorrents sortUsingDescriptors: [NSArray arrayWithObject: groupDescriptor]];
NSMutableArray * groups = [NSMutableArray array], * groupTorrents;
int i, oldGroupValue = -2;
for (i = 0; i < [fDisplayedTorrents count]; i++)
{
int groupValue = [[fDisplayedTorrents objectAtIndex: i] groupValue];
Torrent * torrent = [fDisplayedTorrents objectAtIndex: i];
int groupValue = [torrent groupValue];
if (groupValue != oldGroupValue)
{
[fDisplayedTorrents insertObject: [NSNumber numberWithInt: groupValue] atIndex: i];
[fDisplayedGroupIndexes addIndex: i];
groupTorrents = [NSMutableArray array];
NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: groupValue], @"Group",
groupTorrents, @"Torrents", nil];
[groups addObject: dict];
i++;
oldGroupValue = groupValue;
}
[groupTorrents addObject: torrent];
}
[fDisplayedTorrents setArray: groups];
}
//actually sort
[self sortTorrentsIgnoreSelected];
[fTableView selectValues: selectedValues];
//set status bar torrent count text
NSString * totalTorrentsString;
int totalCount = [fTorrents count];
if (totalCount != 1)
totalTorrentsString = [NSString stringWithFormat: NSLocalizedString(@"%d transfers", "Status bar transfer count"), totalCount];
else
totalTorrentsString = NSLocalizedString(@"1 transfer", "Status bar transfer count");
if (filterStatus || filterGroup || filterText)
totalTorrentsString = [NSString stringWithFormat: NSLocalizedString(@"%d of %@", "Status bar transfer count"),
[fDisplayedTorrents count] - [fDisplayedGroupIndexes count], totalTorrentsString];
[fTotalTorrentsField setStringValue: totalTorrentsString];
[self setBottomCountTextFiltering: groupRows || filterStatus || filterGroup || filterText];
[self setWindowSizeToFit];
}
@ -2397,20 +2414,39 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fAutoImportedNames addObject: [location lastPathComponent]];
}
- (int) numberOfRowsInTableView: (NSTableView *) tableview
- (NSInteger) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item
{
if (item)
return [[item objectForKey: @"Torrents"] count];
else
return [fDisplayedTorrents count];
}
- (id) tableView: (NSTableView *) tableView objectValueForTableColumn: (NSTableColumn *) tableColumn row: (int) row
- (id) outlineView: (NSOutlineView *) outlineView child: (NSInteger) index ofItem: (id) item
{
if (![fDisplayedGroupIndexes containsIndex: row])
return nil;
int group = [[fDisplayedTorrents objectAtIndex: row] intValue];
return group != -1 ? [[GroupsWindowController groups] nameForIndex: group] : NSLocalizedString(@"No Group", "Group table row");
if (item)
return [[item objectForKey: @"Torrents"] objectAtIndex: index];
else
return [fDisplayedTorrents objectAtIndex: index];
}
- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item
{
return ![item isKindOfClass: [Torrent class]];
}
- (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item
{
if (![item isKindOfClass: [Torrent class]])
{
int group = [[item objectForKey: @"Group"] intValue];
return group != -1 ? [[GroupsWindowController groups] nameForIndex: group] : NSLocalizedString(@"No Group", "Group table row");
}
else
return [item hashString];
}
#warning fix
- (BOOL) tableView: (NSTableView *) tableView writeRowsWithIndexes: (NSIndexSet *) indexes toPasteboard: (NSPasteboard *) pasteboard
{
//only allow reordering of rows if sorting by order
@ -2626,15 +2662,12 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[fTableView setRowHeight: makeSmall ? ROW_HEIGHT_SMALL : ROW_HEIGHT_REGULAR];
//non-group rows are being resized
NSMutableIndexSet * indexes = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTableView numberOfRows])];
[indexes removeIndexes: fDisplayedGroupIndexes];
[fTableView noteHeightOfRowsWithIndexesChanged: indexes];
[fTableView noteHeightOfRowsWithIndexesChanged: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fTableView numberOfRows])]];
//window min height
NSSize contentMinSize = [fWindow contentMinSize],
contentSize = [[fWindow contentView] frame].size;
contentMinSize.height = contentSize.height - [fScrollView frame].size.height
contentMinSize.height = contentSize.height - [[fTableView enclosingScrollView] frame].size.height
+ [fTableView rowHeight] + [fTableView intercellSpacing].height;
[fWindow setContentMinSize: contentMinSize];
@ -2675,20 +2708,22 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
- (NSRect) windowFrameByAddingHeight: (float) height checkLimits: (BOOL) check
{
NSScrollView * scrollView = [fTableView enclosingScrollView];
//convert pixels to points
NSRect windowFrame = [fWindow frame];
NSSize windowSize = [fScrollView convertSize: windowFrame.size fromView: nil];
NSSize windowSize = [scrollView convertSize: windowFrame.size fromView: nil];
windowSize.height += height;
if (check)
{
NSSize minSize = [fScrollView convertSize: [fWindow minSize] fromView: nil];
NSSize minSize = [scrollView convertSize: [fWindow minSize] fromView: nil];
if (windowSize.height < minSize.height)
windowSize.height = minSize.height;
else
{
NSSize maxSize = [fScrollView convertSize: [[fWindow screen] visibleFrame].size fromView: nil];
NSSize maxSize = [scrollView convertSize: [[fWindow screen] visibleFrame].size fromView: nil];
if ([fStatusBar isHidden])
maxSize.height -= [fStatusBar frame].size.height;
if ([fFilterBar isHidden])
@ -2699,7 +2734,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
}
//convert points to pixels
windowSize = [fScrollView convertSize: windowSize toView: nil];
windowSize = [scrollView convertSize: windowSize toView: nil];
windowFrame.origin.y -= (windowSize.height - windowFrame.size.height);
windowFrame.size.height = windowSize.height;
@ -2735,13 +2770,15 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
[self updateUI];
NSScrollView * scrollView = [fTableView enclosingScrollView];
//set views to not autoresize
unsigned int statsMask = [fStatusBar autoresizingMask];
unsigned int filterMask = [fFilterBar autoresizingMask];
unsigned int scrollMask = [fScrollView autoresizingMask];
unsigned int scrollMask = [scrollView autoresizingMask];
[fStatusBar setAutoresizingMask: NSViewNotSizable];
[fFilterBar setAutoresizingMask: NSViewNotSizable];
[fScrollView setAutoresizingMask: NSViewNotSizable];
[scrollView setAutoresizingMask: NSViewNotSizable];
frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
[fWindow setFrame: frame display: YES animate: animate];
@ -2749,7 +2786,7 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
//re-enable autoresize
[fStatusBar setAutoresizingMask: statsMask];
[fFilterBar setAutoresizingMask: filterMask];
[fScrollView setAutoresizingMask: scrollMask];
[scrollView setAutoresizingMask: scrollMask];
//change min size
NSSize minSize = [fWindow contentMinSize];
@ -2801,18 +2838,20 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
}
}
NSScrollView * scrollView = [fTableView enclosingScrollView];
//set views to not autoresize
unsigned int filterMask = [fFilterBar autoresizingMask];
unsigned int scrollMask = [fScrollView autoresizingMask];
unsigned int scrollMask = [scrollView autoresizingMask];
[fFilterBar setAutoresizingMask: NSViewNotSizable];
[fScrollView setAutoresizingMask: NSViewNotSizable];
[scrollView setAutoresizingMask: NSViewNotSizable];
frame = [self windowFrameByAddingHeight: heightChange checkLimits: NO];
[fWindow setFrame: frame display: YES animate: animate];
//re-enable autoresize
[fFilterBar setAutoresizingMask: filterMask];
[fScrollView setAutoresizingMask: scrollMask];
[scrollView setAutoresizingMask: scrollMask];
//change min size
NSSize minSize = [fWindow contentMinSize];
@ -3622,21 +3661,32 @@ void sleepCallBack(void * controller, io_service_t y, natural_t messageType, voi
{
if ([fDefaults boolForKey: @"AutoSize"])
{
[fScrollView setHasVerticalScroller: NO];
NSScrollView * scrollView = [fTableView enclosingScrollView];
[scrollView setHasVerticalScroller: NO];
[fWindow setFrame: [self sizedWindowFrame] display: YES animate: YES];
[fScrollView setHasVerticalScroller: YES];
[scrollView setHasVerticalScroller: YES];
}
}
- (NSRect) sizedWindowFrame
{
float heightChange = (GROUP_SEPARATOR_HEIGHT + [fTableView intercellSpacing].height) * [fDisplayedGroupIndexes count]
+ ([fTableView rowHeight] + [fTableView intercellSpacing].height) * ([fDisplayedTorrents count]
- [fDisplayedGroupIndexes count]) - [fScrollView frame].size.height;
int groups = ([fDisplayedTorrents count] > 0 && ![[fDisplayedTorrents objectAtIndex: 0] isKindOfClass: [Torrent class]])
? [fDisplayedTorrents count] : 0;
float heightChange = (GROUP_SEPARATOR_HEIGHT + [fTableView intercellSpacing].height) * groups
+ ([fTableView rowHeight] + [fTableView intercellSpacing].height) * ([fTableView numberOfRows] - groups)
- [[fTableView enclosingScrollView] frame].size.height;
return [self windowFrameByAddingHeight: heightChange checkLimits: YES];
}
- (void) updateForExpandCollape
{
[self setWindowSizeToFit];
[self setBottomCountTextFiltering: YES];
}
- (void) showMainWindow: (id) sender
{
[fWindow makeKeyAndOrderFront: nil];

File diff suppressed because it is too large Load Diff

View File

@ -161,10 +161,7 @@ GroupsWindowController * fGroupsWindowInstance = nil;
- (NSImage *) imageForIndex: (int) index isSmall: (BOOL) small
{
int orderIndex = [self orderValueForIndex: index];
if (orderIndex == -1)
return nil;
return [self imageForGroup: [fGroups objectAtIndex: orderIndex] isSmall: small];
return orderIndex != -1 ? [self imageForGroup: [fGroups objectAtIndex: orderIndex] isSmall: small] : nil;
}
- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableview
@ -262,14 +259,13 @@ GroupsWindowController * fGroupsWindowInstance = nil;
if ([selectedGroups count] > 0)
{
NSMutableIndexSet * indexSet = [NSMutableIndexSet indexSet];
NSEnumerator * enumerator = [selectedGroups objectEnumerator];
NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
NSDictionary * dict;
while ((dict = [enumerator nextObject]))
[indexSet addIndex: [fGroups indexOfObject: dict]];
[fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
[indexSet release];
}
[fTableView reloadData];

View File

@ -1,29 +0,0 @@
/******************************************************************************
* $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.
*****************************************************************************/
@interface NSMutableArray (NSMutableArrayAdditions)
- (void) sortIndexes: (NSIndexSet *) indexes usingDescriptors: (NSArray *) sortDescriptors;
@end

View File

@ -1,39 +0,0 @@
/******************************************************************************
* $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 "NSMutableArrayAdditions.h"
@implementation NSMutableArray (NSMutableArrayAdditions)
- (void) sortIndexes: (NSIndexSet *) indexes usingDescriptors: (NSArray *) sortDescriptors
{
if ([indexes count] <= 1)
return;
NSArray * items = [self objectsAtIndexes: indexes];
items = [items sortedArrayUsingDescriptors: sortDescriptors];
[self replaceObjectsAtIndexes: indexes withObjects: items];
}
@end

View File

@ -56,6 +56,8 @@ typedef enum
NSImage * fIcon;
NSString * fHashString;
tr_file_stat * fileStat;
NSArray * fFileList;

View File

@ -175,6 +175,8 @@ void completenessChangeCallback(tr_torrent * torrent, cp_status_t status, void *
free(fPreviousFinishedPieces);
[fFinishedPiecesDate release];
[fHashString release];
[fDownloadFolder release];
[fIncompleteFolder release];
@ -732,7 +734,7 @@ void completenessChangeCallback(tr_torrent * torrent, cp_status_t status, void *
- (NSString *) hashString
{
return [NSString stringWithUTF8String: fInfo->hashString];
return fHashString;
}
- (BOOL) privateTorrent
@ -1572,6 +1574,8 @@ void completenessChangeCallback(tr_torrent * torrent, cp_status_t status, void *
fInfo = tr_torrentInfo(fHandle);
fHashString = [[NSString alloc] initWithUTF8String: fInfo->hashString];
fDateAdded = dateAdded ? [dateAdded retain] : [[NSDate alloc] init];
if (dateCompleted)
fDateCompleted = [dateCompleted retain];

View File

@ -453,14 +453,14 @@
fMouseDownActionButton = pushed;
}
- (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
- (void) drawInteriorWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
{
[super drawWithFrame: cellFrame inView: controlView];
Torrent * torrent = [self representedObject];
BOOL minimal = [fDefaults boolForKey: @"SmallView"];
#warning use inset instead of edges
//group coloring
NSRect iconRect = [self iconRectForBounds: cellFrame];

View File

@ -26,14 +26,13 @@
#import <transmission.h>
#import <Controller.h>
#define GROUP_SEPARATOR_HEIGHT 18.0
@class TorrentCell;
@interface TorrentTableView : NSTableView
#define GROUP_SEPARATOR_HEIGHT 18.0
@interface TorrentTableView : NSOutlineView
{
IBOutlet Controller * fController;
NSArray * fTorrents;
NSIndexSet * fGroupIndexes;
TorrentCell * fTorrentCell;
@ -45,8 +44,6 @@
int fMouseControlRow, fMouseRevealRow, fMouseActionRow, fActionPushedRow;
NSArray * fSelectedValues;
NSMutableArray * fKeyStrokes;
IBOutlet NSMenu * fActionMenu, * fUploadMenu, * fDownloadMenu, * fRatioMenu;
Torrent * fMenuTorrent;
@ -54,9 +51,6 @@
NSTimer * fPiecesBarTimer;
}
- (void) setTorrents: (NSArray *) torrents;
- (void) setGroupIndexes: (NSIndexSet *) indexes;
- (void) removeButtonTrackingAreas;
- (void) setControlButtonHover: (int) row;
- (void) setRevealButtonHover: (int) row;

View File

@ -24,7 +24,6 @@
#import "TorrentTableView.h"
#import "TorrentCell.h"
#import "Controller.h"
#import "Torrent.h"
#import "NSApplicationAdditions.h"
#import "NSMenuAdditions.h"
@ -75,90 +74,86 @@
return self;
}
- (void) awakeFromNib
{
[self setGridStyleMask: NSTableViewSolidVerticalGridLineMask]; //weird redrawing issues if set to none
}
- (void) dealloc
{
[fPiecesBarTimer invalidate];
[fMenuTorrent release];
[fSelectedValues release];
[fKeyStrokes release];
[fMenuTorrent release];
[fTorrentCell release];
[super dealloc];
}
- (void) setTorrents: (NSArray *) torrents
- (BOOL) outlineView: (NSOutlineView *) outlineView isGroupItem: (id) item
{
fTorrents = torrents;
return ![item isKindOfClass: [Torrent class]];
}
- (void) setGroupIndexes: (NSIndexSet *) indexes
- (CGFloat) outlineView: (NSOutlineView *) outlineView heightOfRowByItem: (id) item
{
fGroupIndexes = indexes;
return [item isKindOfClass: [Torrent class]] ? [self rowHeight] : GROUP_SEPARATOR_HEIGHT;
}
- (BOOL) tableView: (NSTableView *) tableView isGroupRow: (NSInteger) row
- (NSCell *) outlineView: (NSOutlineView *) outlineView dataCellForTableColumn: (NSTableColumn *) tableColumn item: (id) item
{
return [fGroupIndexes containsIndex: row];
if (!tableColumn)
return nil;
return [item isKindOfClass: [Torrent class]] ? fTorrentCell : nil;
}
- (CGFloat) tableView: (NSTableView *) tableView heightOfRow: (NSInteger) row
- (void) outlineView: (NSOutlineView *) outlineView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn
item: (id) item
{
return ![fGroupIndexes containsIndex: row] ? [self rowHeight] : GROUP_SEPARATOR_HEIGHT;
}
- (NSCell *) tableView: (NSTableView *) tableView dataCellForTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row
{
return ![fGroupIndexes containsIndex: row] ? fTorrentCell : nil;
}
- (void) tableView: (NSTableView *) tableView willDisplayCell: (id) cell forTableColumn: (NSTableColumn *) tableColumn row: (int) row
{
if ([fGroupIndexes containsIndex: row])
if (![item isKindOfClass: [Torrent class]])
return;
[cell setRepresentedObject: [fTorrents objectAtIndex: row]];
[cell setRepresentedObject: item];
int row = [self rowForItem: item];
[cell setControlHover: row == fMouseControlRow];
[cell setRevealHover: row == fMouseRevealRow];
[cell setActionHover: row == fMouseActionRow];
[cell setActionPushed: row == fActionPushedRow];
}
- (NSString *) tableView: (NSTableView *) tableView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn row: (int) row
- (NSRect) frameOfCellAtColumn: (NSInteger) column row: (NSInteger) row
{
return ![fGroupIndexes containsIndex: row] ? [[fTorrents objectAtIndex: row] name]
: [[self preparedCellAtColumn: 0 row: row] stringValue];
NSRect rect = [super frameOfCellAtColumn: column row: row];
if ([[self itemAtRow: row] isKindOfClass: [Torrent class]])
{
rect.size.width += rect.origin.x;
rect.origin.x = 0.0;
}
- (BOOL) tableView: (NSTableView *) tableView shouldEditTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row
return rect;
}
- (NSString *) outlineView: (NSOutlineView *) outlineView typeSelectStringForTableColumn: (NSTableColumn *) tableColumn item: (id) item
{
return NO;
return [item isKindOfClass: [Torrent class]] ? [item name]
: [[self preparedCellAtColumn: 0 row: [self rowForItem: item]] stringValue];
}
- (void) updateTrackingAreas
{
[super updateTrackingAreas];
[self removeButtonTrackingAreas];
NSMutableIndexSet * indexes = [NSMutableIndexSet indexSetWithIndexesInRange: [self rowsInRect: [self visibleRect]]];
[indexes removeIndexes: fGroupIndexes];
if ([indexes count] == 0)
NSRange rows = [self rowsInRect: [self visibleRect]];
if (rows.length == 0)
return;
NSPoint mouseLocation = [self convertPoint: [[self window] convertScreenToBase: [NSEvent mouseLocation]] fromView: nil];
NSUInteger row;
for (row = [indexes firstIndex]; row != NSNotFound; row = [indexes indexGreaterThanIndex: row])
for (row = rows.location; row < NSMaxRange(rows); row++)
{
if (![[self itemAtRow: row] isKindOfClass: [Torrent class]])
continue;
NSDictionary * userInfo = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: row] forKey: @"Row"];
TorrentCell * cell = (TorrentCell *)[self preparedCellAtColumn: 0 row: row];
[cell addTrackingAreasForView: self inRect: [self frameOfCellAtColumn: 0 row: row] withUserInfo: userInfo
@ -244,12 +239,22 @@
}
}
- (void) tableViewSelectionIsChanging: (NSNotification *) notification
- (void) outlineViewSelectionIsChanging: (NSNotification *) notification
{
if (fSelectedValues)
[self selectValues: fSelectedValues];
}
- (void) outlineViewItemDidExpand: (NSNotification *) notification
{
[[NSNotificationCenter defaultCenter] postNotificationName: @"OutlineExpandCollapse" object: self];
}
- (void) outlineViewItemDidCollapse: (NSNotification *) notification
{
[[NSNotificationCenter defaultCenter] postNotificationName: @"OutlineExpandCollapse" object: self];
}
- (void) mouseDown: (NSEvent *) event
{
NSPoint point = [self convertPoint: [event locationInWindow] fromView: nil];
@ -280,7 +285,19 @@
[self setNeedsDisplayInRect: [self rectOfRow: row]];
}
else if (!pushed && [event clickCount] == 2) //double click
{
id item = [self itemAtRow: [self rowAtPoint: point]];
if ([item isKindOfClass: [Torrent class]])
[fController showInfo: nil];
else
{
if ([self isItemExpanded: item])
[self collapseItem: item];
else
[self expandItem: item];
}
}
else;
}
@ -289,44 +306,61 @@
NSMutableIndexSet * indexSet = [NSMutableIndexSet indexSet];
NSEnumerator * enumerator = [values objectEnumerator];
id object;
while ((object = [enumerator nextObject]))
id item;
while ((item = [enumerator nextObject]))
{
unsigned index = [fTorrents indexOfObject: object]; //works with torrents and groups
if (index != NSNotFound)
if ([item isKindOfClass: [Torrent class]])
{
NSUInteger index = [self rowForItem: item];
if (index != -1)
[indexSet addIndex: index];
}
else
{
int group = [[item objectForKey: @"Group"] intValue], i;
for (i = 0; i < [self numberOfRows]; i++)
{
id tableItem = [self itemAtRow: i];
if (![tableItem isKindOfClass: [Torrent class]] && [[tableItem objectForKey: @"Group"] intValue] == group)
[indexSet addIndex: i];
}
}
}
[self selectRowIndexes: indexSet byExtendingSelection: NO];
}
- (NSArray *) selectedValues
{
return [fTorrents objectsAtIndexes: [self selectedRowIndexes]];
NSIndexSet * selectedIndexes = [self selectedRowIndexes];
NSMutableArray * values = [NSMutableArray arrayWithCapacity: [selectedIndexes count]];
NSUInteger i;
for (i = [selectedIndexes firstIndex]; i != NSNotFound; i = [selectedIndexes indexGreaterThanIndex: i])
[values addObject: [self itemAtRow: i]];
return values;
}
- (NSArray *) selectedTorrents
{
NSIndexSet * selectedIndexes = [self selectedRowIndexes];
NSMutableIndexSet * indexSet = [NSMutableIndexSet indexSet];
NSMutableArray * torrents = [NSMutableArray array];
NSUInteger i;
for (i = [selectedIndexes firstIndex]; i != NSNotFound; i = [selectedIndexes indexGreaterThanIndex: i])
{
if (![fGroupIndexes containsIndex: i])
[indexSet addIndex: i];
else
id item = [self itemAtRow: i];
if ([item isKindOfClass: [Torrent class]])
{
NSUInteger nextGroup = [fGroupIndexes indexGreaterThanIndex: i];
if (nextGroup == NSNotFound)
nextGroup = [fTorrents count];
[indexSet addIndexesInRange: NSMakeRange(i+1, nextGroup - i - 1)];
i = nextGroup - 1;
if (![torrents containsObject: item])
[torrents addObject: item];
}
else
[torrents addObjectsFromArray: [item objectForKey: @"Torrents"]];
}
[fTorrents objectsAtIndexes: indexSet];
return torrents;
}
- (NSMenu *) menuForEvent: (NSEvent *) event
@ -352,66 +386,6 @@
[super flagsChanged: event];
}
- (void) keyDown: (NSEvent *) event
{
//this is handled by the delegate in Leopard
if ([NSApp isOnLeopardOrBetter])
{
[super keyDown: event];
return;
}
if (!fKeyStrokes)
fKeyStrokes = [[NSMutableArray alloc] init];
unichar newChar = [[event characters] characterAtIndex: 0];
if (newChar == ' ' || [[NSCharacterSet alphanumericCharacterSet] characterIsMember: newChar]
|| [[NSCharacterSet symbolCharacterSet] characterIsMember: newChar]
|| [[NSCharacterSet punctuationCharacterSet] characterIsMember: newChar])
{
if ([fKeyStrokes count] > 0 && [event timestamp] - [[fKeyStrokes lastObject] timestamp] > 1.0)
[fKeyStrokes removeAllObjects];
[fKeyStrokes addObject: event];
[self interpretKeyEvents: fKeyStrokes];
}
else
{
[fKeyStrokes removeAllObjects];
[super keyDown: event];
}
}
- (void) insertText: (NSString *) text
{
//this is handled by the delegate in Leopard
if ([NSApp isOnLeopardOrBetter])
{
[super insertText: text];
return;
}
//sort torrents by name before finding closest match
NSSortDescriptor * nameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"name" ascending: YES
selector: @selector(caseInsensitiveCompare:)] autorelease];
NSArray * tempTorrents = [fTorrents sortedArrayUsingDescriptors: [NSArray arrayWithObject: nameDescriptor]];
text = [text lowercaseString];
//select torrent closest to text that isn't before text alphabetically
NSEnumerator * enumerator = [tempTorrents objectEnumerator];
Torrent * torrent;
while ((torrent = [enumerator nextObject]))
if ([[[torrent name] lowercaseString] hasPrefix: text])
{
int row = [fTorrents indexOfObject: torrent];
[self selectRow: row byExtendingSelection: NO];
[self scrollRowToVisible: row];
return;
}
}
- (void) toggleControlForTorrent: (Torrent *) torrent
{
if ([torrent isActive])
@ -434,7 +408,7 @@
return;
//get and update file menu
fMenuTorrent = [[fTorrents objectAtIndex: row] retain];
fMenuTorrent = [[self itemAtRow: row] retain];
NSMenu * fileMenu = [fMenuTorrent fileMenu];
[self updateFileMenu: fileMenu forFiles: [fMenuTorrent fileList]];
@ -638,7 +612,7 @@
- (BOOL) pointInControlRect: (NSPoint) point
{
int row = [self rowAtPoint: point];
if (row < 0 || [fGroupIndexes containsIndex: row])
if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
return NO;
return NSPointInRect(point, [fTorrentCell controlButtonRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
@ -647,7 +621,7 @@
- (BOOL) pointInRevealRect: (NSPoint) point
{
int row = [self rowAtPoint: point];
if (row < 0 || [fGroupIndexes containsIndex: row])
if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
return NO;
return NSPointInRect(point, [fTorrentCell revealButtonRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
@ -656,7 +630,7 @@
- (BOOL) pointInActionRect: (NSPoint) point
{
int row = [self rowAtPoint: point];
if (row < 0 || [fGroupIndexes containsIndex: row])
if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]])
return NO;
return NSPointInRect(point, [fTorrentCell iconRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
@ -665,7 +639,7 @@
- (BOOL) pointInProgressRect: (NSPoint) point
{
int row = [self rowAtPoint: point];
if (row < 0 || [fGroupIndexes containsIndex: row] || [fDefaults boolForKey: @"SmallView"])
if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]] || [fDefaults boolForKey: @"SmallView"])
return NO;
TorrentCell * cell;
@ -674,7 +648,7 @@
else
{
cell = fTorrentCell;
[cell setRepresentedObject: [fTorrents objectAtIndex: row]];
[cell setRepresentedObject: [self itemAtRow: row]];
}
return NSPointInRect(point, [cell progressRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
}
@ -682,7 +656,7 @@
- (BOOL) pointInMinimalStatusRect: (NSPoint) point
{
int row = [self rowAtPoint: point];
if (row < 0 || [fGroupIndexes containsIndex: row] || ![fDefaults boolForKey: @"SmallView"])
if (row < 0 || ![[self itemAtRow: row] isKindOfClass: [Torrent class]] || ![fDefaults boolForKey: @"SmallView"])
return NO;
TorrentCell * cell;
@ -691,7 +665,7 @@
else
{
cell = fTorrentCell;
[cell setRepresentedObject: [fTorrents objectAtIndex: row]];
[cell setRepresentedObject: [self itemAtRow: row]];
}
return NSPointInRect(point, [cell minimalStatusRectForBounds: [self frameOfCellAtColumn: 0 row: row]]);
}