Changeset 256


Ignore:
Timestamp:
May 25, 2006, 12:22:19 PM (17 years ago)
Author:
titer
Message:

Merged Mitchell's changes, this includes:
Adds stop at ratio,
Adds sorting by name, date or state,
Seperates Info window into its own nib,
Adds option to enable or disabled autostarting downloads,
Seperates Network / Transfers in the Preferences

Location:
trunk/macosx
Files:
8 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/macosx/Badger.h

    r191 r256  
    1313@interface Badger : NSObject {
    1414
    15     NSImage             * fDockIcon, * fBadgedDockIcon,
    16                         * fBadge, * fUploadBadge, * fDownloadBadge;
     15    NSImage         * fDockIcon, * fBadgedDockIcon,
     16                    * fBadge, * fUploadBadge, * fDownloadBadge;
    1717                   
    18     NSMutableDictionary * fAttributes;
     18    NSDictionary    * fAttributes;
    1919   
    20     int                 fCompleted;
    21     BOOL                fSpeedShown;
     20    int             fCompleted;
     21    BOOL            fSpeedShown;
    2222}
    2323
  • trunk/macosx/Badger.m

    r191 r256  
    4343        fDownloadBadge = [NSImage imageNamed: @"DownloadBadge"];
    4444       
    45        
    46         fAttributes = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
     45        NSShadow * stringShadow = [[NSShadow alloc] init];
     46        [stringShadow setShadowOffset: NSMakeSize(2, -2)];
     47        [stringShadow setShadowBlurRadius: 4];
     48       
     49        fAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:
    4750            [NSColor whiteColor], NSForegroundColorAttributeName,
    4851            [NSFont fontWithName: @"Helvetica-Bold" size: 28], NSFontAttributeName,
     52            stringShadow, NSShadowAttributeName,
    4953            nil] retain];
    50 
    51         if( OSX_VERSION >= 10.3 )
    52         {
    53             NSShadow * stringShadow = [[NSShadow alloc] init];
    54             [stringShadow setShadowOffset: NSMakeSize(2, -2)];
    55             [stringShadow setShadowBlurRadius: 4];
    56             [fAttributes setObject: stringShadow
    57                 forKey: NSShadowAttributeName];
    58             [stringShadow release];
    59         }
     54       
     55        [stringShadow release];
    6056       
    6157        fCompleted = 0;
     
    8379    NSSize iconSize = [fDockIcon size];
    8480
    85     //set seeding and downloading badges if there was a change
    86     if (completed != fCompleted)
     81    //set completed badge
     82    if (fCompleted != completed)
    8783    {
    8884        fCompleted = completed;
     
    120116    }
    121117
    122     //display upload and download rates
    123     BOOL speedShown = NO;
    124     if (uploadRate || downloadRate)
    125     {
    126         speedShown = YES;
    127    
     118    //set upload and download rate badges
     119    BOOL speedShown = uploadRate || downloadRate;
     120    if (speedShown)
     121    {
    128122        NSRect badgeRect, stringRect;
    129123        badgeRect.size = [fUploadBadge size];
  • trunk/macosx/Controller.h

    r247 r256  
    2727#import <transmission.h>
    2828#import "PrefsController.h"
     29#import "InfoWindowController.h"
    2930#import "Badger.h"
    3031
     
    3637    int                         fCompleted;
    3738    NSMutableArray              * fTorrents;
     39   
     40    InfoWindowController        * fInfoController;
    3841
    3942    NSToolbar                   * fToolbar;
     
    5659    IBOutlet NSBox              * fStats;
    5760    BOOL                        fStatusBar;
    58 
    59     IBOutlet NSPanel            * fInfoPanel;
    60     IBOutlet NSImageView        * fInfoImageView;
    61     IBOutlet NSTextField        * fInfoName;
    62     IBOutlet NSTextField        * fInfoSize;
    63     IBOutlet NSTextField        * fInfoTracker;
    64     IBOutlet NSTextField        * fInfoAnnounce;
    65     IBOutlet NSTextField        * fInfoPieceSize;
    66     IBOutlet NSTextField        * fInfoPieces;
    67     IBOutlet NSTextField        * fInfoHash1;
    68     IBOutlet NSTextField        * fInfoHash2;
    69     IBOutlet NSTextField        * fInfoSeeders;
    70     IBOutlet NSTextField        * fInfoLeechers;
    71     IBOutlet NSTextField        * fInfoDownloaded;
    72     IBOutlet NSTextField        * fInfoUploaded;
    73     NSImage                     * fAppIcon;
     61   
     62    IBOutlet NSButton           * fActionButton;
     63   
     64    NSString                    * fSortType;
     65    IBOutlet NSMenuItem         * fNameSortItem,
     66                                * fStateSortItem,
     67                                * fDateSortItem;
     68    NSMenuItem                  * fCurrentSortItem;
    7469
    7570    io_connect_t                fRootPort;
     
    9186                        contextInfo: (void *) info;
    9287
    93 - (void) quitSheetDidEnd:   (NSWindow *)sheet returnCode:(int)returnCode
    94                             contextInfo:(void *)contextInfo;
    95                        
     88- (void) quitSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
     89                            contextInfo: (void *) contextInfo;
     90
     91- (NSArray *) torrentsAtIndexes: (NSIndexSet *) indexSet;
     92- (void) torrentNumberChanged;
     93
    9694- (void) resumeTorrent:             (id) sender;
    9795- (void) resumeAllTorrents:         (id) sender;
     
    109107                deleteData:         (BOOL) deleteData;
    110108               
    111 - (void) removeSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
    112                         contextInfo:(NSDictionary *)dict;
    113 - (void) confirmRemoveTorrentWithIndex: (NSIndexSet *) indexSet
     109- (void) removeSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
     110                        contextInfo: (NSDictionary *) dict;
     111- (void) confirmRemoveTorrents: (NSArray *) torrents
    114112            deleteTorrent: (BOOL) deleteTorrent
    115113            deleteData: (BOOL) deleteData;
     114
     115- (void) revealTorrent: (id) sender;
    116116                     
    117117- (void) showInfo:        (id) sender;
     118- (void) updateInfo;
     119- (void) updateInfoStats;
    118120
    119121- (void) updateUI:        (NSTimer *) timer;
    120122- (void) updateTorrentHistory;
     123
     124- (void) sortTorrents;
     125- (void) setSort: (id) sender;
     126
    121127- (void) sleepCallBack:   (natural_t) messageType argument:
    122128                        (void *) messageArgument;
    123129
    124 - (void) runCustomizationPalette: (id) sender;
    125 - (void) showHideToolbar: (id) sender;
    126130- (void) toggleStatusBar: (id) sender;
    127131
     
    132136- (void) linkForums:        (id) sender;
    133137- (void) notifyGrowl:       (NSString *) file;
    134 - (void) revealFromMenu:    (id) sender;
    135138- (void) growlRegister:     (id) sender;
    136139
  • trunk/macosx/Controller.m

    r247 r256  
    5656- (id) init
    5757{
    58     fLib      = tr_init();
    59     fTorrents = [[NSMutableArray alloc] initWithCapacity: 10];
     58    if ((self = [super init]))
     59    {
     60        fLib = tr_init();
     61        fTorrents = [[NSMutableArray alloc] initWithCapacity: 10];
     62    }
    6063    return self;
    6164}
     
    6467{
    6568    [fTorrents release];
     69   
     70    [fInfoController release];
     71   
    6672    tr_close( fLib );
    67     [fAppIcon release];
    6873    [super dealloc];
    6974}
     
    7176- (void) awakeFromNib
    7277{
    73     fAppIcon = [[NSApp applicationIconImage] copy];
    74 
    7578    [fPrefsController setPrefsWindow: fLib];
    7679    fDefaults = [NSUserDefaults standardUserDefaults];
    7780
    78     //check advanced bar menu item
     81    fInfoController = [[InfoWindowController alloc] initWithWindowNibName: @"InfoWindow"];
     82   
    7983    [fAdvancedBarItem setState: [fDefaults
    80         boolForKey:@"UseAdvancedBar"] ? NSOnState : NSOffState];
     84        boolForKey: @"UseAdvancedBar"] ? NSOnState : NSOffState];
    8185
    8286    fToolbar = [[NSToolbar alloc] initWithIdentifier: @"Transmission Toolbar"];
     
    9094    if (![fDefaults boolForKey: @"StatusBar"])
    9195        [self toggleStatusBar: nil];
     96   
     97    [fActionButton setToolTip: @"Shortcuts for performing special actions."];
    9298
    9399    [fTableView setTorrents: fTorrents];
     
    95101        [[TorrentCell alloc] init]];
    96102
    97     [fTableView registerForDraggedTypes: [NSArray arrayWithObjects:
    98         NSFilenamesPboardType, NULL]];
     103    [fTableView registerForDraggedTypes:
     104        [NSArray arrayWithObject: NSFilenamesPboardType]];
    99105
    100106    //Register for sleep notifications
    101     IONotificationPortRef  notify;
    102     io_object_t            anIterator;
    103 
    104     fRootPort = IORegisterForSystemPower( self, & notify, sleepCallBack,
    105                                           & anIterator);
    106     if (fRootPort)
     107    IONotificationPortRef notify;
     108    io_object_t anIterator;
     109    if (fRootPort= IORegisterForSystemPower(self, & notify,
     110                                sleepCallBack, & anIterator))
    107111    {
    108112        CFRunLoopAddSource( CFRunLoopGetCurrent(),
     
    113117        NSLog( @"Could not IORegisterForSystemPower" );
    114118
    115     NSString * torrentPath, * downloadFolder, * paused;
    116     NSDate * date;
    117     NSDictionary * dic;
    118 
     119    //load torrents from history
    119120    Torrent * torrent;
     121    NSDictionary * historyItem;
    120122    NSEnumerator * enumerator = [[fDefaults arrayForKey: @"History"] objectEnumerator];
    121     while ((dic = [enumerator nextObject]))
    122     {
    123         torrentPath    = [dic objectForKey: @"TorrentPath"];
    124         downloadFolder = [dic objectForKey: @"DownloadFolder"];
    125         paused         = [dic objectForKey: @"Paused"];
    126 
    127         if (!torrentPath || !downloadFolder || !paused)
    128             continue;
    129 
    130         if ((date = [dic objectForKey: @"Date"]))
    131             torrent = [[Torrent alloc] initWithPath: torrentPath lib: fLib date: date];
    132         else
    133             torrent = [[Torrent alloc] initWithPath: torrentPath lib: fLib];
    134            
    135         if( !torrent )
    136             continue;
    137 
    138         [fTorrents addObject: torrent];
    139 
    140         [torrent setFolder: downloadFolder];
    141 
    142         if ([paused isEqualToString: @"NO"])
    143             [torrent start];
    144     }
     123    while ((historyItem = [enumerator nextObject]))
     124        if ((torrent = [[Torrent alloc] initWithHistory: historyItem lib: fLib]))
     125        {
     126            [fTorrents addObject: torrent];
     127            [torrent release];
     128        }
     129   
     130    [self torrentNumberChanged];
     131   
     132    //set sort
     133    fSortType = [fDefaults stringForKey: @"Sort"];
     134    if ([fSortType isEqualToString: @"Name"])
     135        fCurrentSortItem = fNameSortItem;
     136    else if ([fSortType isEqualToString: @"State"])
     137        fCurrentSortItem = fStateSortItem;
     138    else
     139        fCurrentSortItem = fDateSortItem;
     140    [fCurrentSortItem setState: NSOnState];
    145141
    146142    //check and register Growl if it is installed for this user or all users
     
    154150    fBadger = [[Badger alloc] init];
    155151
    156     //update the interface every 500 ms
     152    //timer to update the interface
    157153    fCompleted = 0;
    158154    [self updateUI: nil];
     
    164160        forMode: NSEventTrackingRunLoopMode];
    165161
     162    //timer to check for updates
    166163    [self checkForUpdateTimer: nil];
    167164    fUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: 60.0
    168165        target: self selector: @selector( checkForUpdateTimer: )
    169166        userInfo: nil repeats: YES];
     167   
     168    [self sortTorrents];
     169   
     170    //show windows
     171    [fWindow makeKeyAndOrderFront: nil];
     172    if ([fDefaults boolForKey: @"InfoVisible"])
     173        [self showInfo: nil];
    170174}
    171175
     
    176180}
    177181
    178 - (void) windowDidResize: (NSNotification *) n
    179 {
    180     [fTableView sizeToFit];
    181 }
    182 
    183 - (BOOL) windowShouldClose: (id) sender
    184 {
    185     [fWindow orderOut: nil];
    186     return NO;
    187 }
    188 
    189182- (BOOL) applicationShouldHandleReopen: (NSApplication *) app
    190183    hasVisibleWindows: (BOOL) flag
     
    194187}
    195188
    196 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
     189- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender
    197190{
    198191    int active = 0;
     
    200193    NSEnumerator * enumerator = [fTorrents objectEnumerator];
    201194    while( ( torrent = [enumerator nextObject] ) )
    202     {
    203195        if( [torrent isActive] )
    204         {
    205196            active++;
    206         }
    207     }
    208197
    209198    if (active > 0 && [fDefaults boolForKey: @"CheckQuit"])
     
    226215}
    227216
    228 - (void) quitSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
    229                         contextInfo:(void  *)contextInfo
     217- (void) quitSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
     218                        contextInfo: (void *) contextInfo
    230219{
    231220    [NSApp stopModal];
     
    236225- (void) applicationWillTerminate: (NSNotification *) notification
    237226{
    238     NSEnumerator * enumerator;
    239     Torrent * torrent;
    240 
    241227    // Stop updating the interface
    242228    [fTimer invalidate];
     
    246232    [fBadger clearBadge];
    247233    [fBadger release];
    248 
    249     // Save history
     234   
     235    //remember info window state
     236    [fDefaults setBool: [[fInfoController window] isVisible] forKey: @"InfoVisible"];
     237
     238    //save history
    250239    [self updateTorrentHistory];
    251240
    252241    // Stop running torrents
    253     enumerator = [fTorrents objectEnumerator];
    254     while( ( torrent = [enumerator nextObject] ) )
    255     {
    256         [torrent stop];
    257     }
     242    [fTorrents makeObjectsPerformSelector: @selector(stop)];
    258243
    259244    // Wait for torrents to stop (5 seconds timeout)
    260245    NSDate * start = [NSDate date];
    261     while( [fTorrents count] )
     246    Torrent * torrent;
     247    while ([fTorrents count] > 0)
    262248    {
    263249        torrent = [fTorrents objectAtIndex: 0];
     
    269255        }
    270256        [fTorrents removeObject: torrent];
    271         [torrent release];
    272257    }
    273258}
     
    275260- (void) showPreferenceWindow: (id) sender
    276261{
    277     //place the window if not open
    278262    if (![fPrefsWindow isVisible])
    279     {
    280263        [fPrefsWindow center];
    281     }
    282 
    283     [fPrefsWindow makeKeyAndOrderFront:NULL];
     264
     265    [fPrefsWindow makeKeyAndOrderFront: nil];
    284266}
    285267
     
    289271    if (code == NSOKButton)
    290272    {
     273        [torrent setFolder: [[s filenames] objectAtIndex: 0]];
     274        if ([fDefaults boolForKey: @"AutoStartDownload"])
     275            [torrent start];
    291276        [fTorrents addObject: torrent];
    292         [torrent setFolder: [[s filenames] objectAtIndex: 0]];
    293         [torrent start];
    294     }
    295     else
    296     {
    297         [torrent release];
    298     }
     277       
     278        [self torrentNumberChanged];
     279    }
     280   
    299281    [NSApp stopModal];
    300282}
     
    303285         openFiles: (NSArray *) filenames
    304286{
    305     NSString * downloadChoice, * downloadFolder, * torrentPath;
     287    BOOL autoStart = [fDefaults boolForKey: @"AutoStartDownload"];
     288   
     289    NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
     290    NSString * torrentPath;
    306291    Torrent * torrent;
    307 
    308     downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
    309     downloadFolder = [fDefaults stringForKey: @"DownloadFolder"];
    310 
    311292    NSEnumerator * enumerator = [filenames objectEnumerator];
    312293    while ((torrentPath = [enumerator nextObject]))
    313294    {
    314         torrent = [[Torrent alloc] initWithPath: torrentPath lib: fLib];
    315         if( !torrent )
     295        if (!(torrent = [[Torrent alloc] initWithPath: torrentPath lib: fLib]))
    316296            continue;
    317297
     
    320300            noteNewRecentDocumentURL: [NSURL fileURLWithPath: torrentPath]];
    321301
    322         if( [downloadChoice isEqualToString: @"Constant"] )
    323         {
    324             [fTorrents addObject: torrent];
    325             [torrent setFolder: [downloadFolder stringByExpandingTildeInPath]];
    326             [torrent start];
    327         }
    328         else if( [downloadChoice isEqualToString: @"Torrent"] )
    329         {
    330             [fTorrents addObject: torrent];
    331             [torrent setFolder: [torrentPath stringByDeletingLastPathComponent]];
    332             [torrent start];
    333         }
    334         else
     302        if ([downloadChoice isEqualToString: @"Ask"])
    335303        {
    336304            NSOpenPanel * panel = [NSOpenPanel openPanel];
     
    341309            [panel setCanChooseDirectories: YES];
    342310
    343             if( [panel respondsToSelector: @selector(setMessage:)] )
    344                 /* >= 10.3 */
    345                 [panel setMessage: [NSString stringWithFormat:
    346                                     @"Select the download folder for %@",
    347                                     [torrentPath lastPathComponent]]];
    348 
    349             [panel beginSheetForDirectory: NULL file: NULL types: NULL
     311            [panel setMessage: [NSString stringWithFormat:
     312                                @"Select the download folder for %@",
     313                                [torrentPath lastPathComponent]]];
     314
     315            [panel beginSheetForDirectory: nil file: nil types: nil
    350316                modalForWindow: fWindow modalDelegate: self didEndSelector:
    351317                @selector( folderChoiceClosed:returnCode:contextInfo: )
     
    353319            [NSApp runModalForWindow: panel];
    354320        }
    355     }
     321        else
     322        {
     323            NSString * folder = [downloadChoice isEqualToString: @"Constant"]
     324                                ? [[fDefaults stringForKey: @"DownloadFolder"]
     325                                        stringByExpandingTildeInPath]
     326                                : [torrentPath stringByDeletingLastPathComponent];
     327
     328            [torrent setFolder: folder];
     329            if (autoStart)
     330                [torrent start];
     331            [fTorrents addObject: torrent];
     332        }
     333       
     334        [torrent release];
     335    }
     336
     337    [self torrentNumberChanged];
    356338
    357339    [self updateUI: nil];
     340    [self sortTorrents];
    358341    [self updateTorrentHistory];
    359342}
    360343
     344- (NSArray *) torrentsAtIndexes: (NSIndexSet *) indexSet
     345{
     346    NSMutableArray * torrents = [NSMutableArray arrayWithCapacity: [indexSet count]];
     347    unsigned int i;
     348    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
     349        [torrents addObject: [fTorrents objectAtIndex: i]];
     350
     351    return torrents;
     352}
     353
     354- (void) torrentNumberChanged
     355{
     356    int count = [fTorrents count];
     357    [fTotalTorrentsField setStringValue: [NSString stringWithFormat:
     358                @"%d Torrent%s", count, count == 1 ? "" : "s"]];
     359}
     360
    361361- (void) advancedChanged: (id) sender
    362362{
    363363    [fAdvancedBarItem setState: ![fAdvancedBarItem state]];
    364     [fDefaults setObject: [fAdvancedBarItem state] == NSOffState ? @"NO" : @"YES"
    365                 forKey:@"UseAdvancedBar"];
     364    [fDefaults setBool: [fAdvancedBarItem state] forKey: @"UseAdvancedBar"];
    366365
    367366    [fTableView display];
     
    377376- (void) openShowSheet: (id) sender
    378377{
    379     NSOpenPanel * panel;
    380     NSArray     * fileTypes;
    381 
    382     panel     = [NSOpenPanel openPanel];
    383     fileTypes = [NSArray arrayWithObject: @"torrent"];
     378    NSOpenPanel * panel = [NSOpenPanel openPanel];
     379    NSArray * fileTypes = [NSArray arrayWithObject: @"torrent"];
    384380
    385381    [panel setAllowsMultipleSelection: YES];
    386     [panel setCanChooseFiles:          YES];
    387     [panel setCanChooseDirectories:    NO];
    388 
    389     [panel beginSheetForDirectory: NULL file: NULL types: fileTypes
     382    [panel setCanChooseFiles: YES];
     383    [panel setCanChooseDirectories: NO];
     384
     385    [panel beginSheetForDirectory: nil file: nil types: fileTypes
    390386        modalForWindow: fWindow modalDelegate: self didEndSelector:
    391387        @selector( openSheetClosed:returnCode:contextInfo: )
    392         contextInfo: NULL];
     388        contextInfo: nil];
    393389}
    394390
     
    398394}
    399395
    400 - (void) openSheetClosed: (NSOpenPanel *) s returnCode: (int) code
     396- (void) openSheetClosed: (NSOpenPanel *) panel returnCode: (int) code
    401397    contextInfo: (void *) info
    402398{
    403399    if( code == NSOKButton )
    404400        [self performSelectorOnMainThread: @selector(cantFindAName:)
    405                     withObject: [s filenames] waitUntilDone: NO];
     401                    withObject: [panel filenames] waitUntilDone: NO];
    406402}
    407403
     
    421417    Torrent * torrent;
    422418    unsigned int i;
    423    
    424419    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
    425420    {
     
    429424   
    430425    [self updateUI: nil];
     426    [self sortTorrents];
    431427    [self updateTorrentHistory];
    432428}
     
    447443    Torrent * torrent;
    448444    unsigned int i;
    449    
    450445    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
    451446    {
     
    455450   
    456451    [self updateUI: nil];
     452    [self sortTorrents];
    457453    [self updateTorrentHistory];
    458454}
     
    462458                     deleteData: (BOOL) deleteData
    463459{
     460    NSArray * torrents = [[self torrentsAtIndexes: indexSet] retain];
    464461    int active = 0;
    465     unsigned int i;
    466     for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
    467         if ([[fTorrents objectAtIndex: i] isActive])
     462
     463    Torrent * torrent;
     464    NSEnumerator * enumerator = [torrents objectEnumerator];
     465    while ((torrent = [enumerator nextObject]))
     466        if ([torrent isActive])
    468467            active++;
    469468
     
    471470    {
    472471        NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
    473             [fTableView selectedRowIndexes], @"Index",
     472            torrents, @"Torrents",
    474473            [NSNumber numberWithBool: deleteTorrent], @"DeleteTorrent",
    475474            [NSNumber numberWithBool: deleteData], @"DeleteData",
     
    504503    else
    505504    {
    506         [self confirmRemoveTorrentWithIndex: indexSet
     505        [self confirmRemoveTorrents: torrents
    507506                deleteTorrent: deleteTorrent
    508507                deleteData: deleteData];
     
    510509}
    511510
    512 - (void) removeSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
    513                         contextInfo:(NSDictionary *)dict
     511- (void) removeSheetDidEnd: (NSWindow *) sheet returnCode: (int) returnCode
     512                        contextInfo: (NSDictionary *) dict
    514513{
    515514    [NSApp stopModal];
    516515
    517     if( returnCode == NSAlertDefaultReturn )
    518     {
    519         [self confirmRemoveTorrentWithIndex: [dict objectForKey:@"Index"]
    520             deleteTorrent: [[dict objectForKey:@"DeleteTorrent"] boolValue]
    521             deleteData: [[dict objectForKey:@"DeleteData"] boolValue]];
    522     }
    523 
     516    NSArray * torrents = [dict objectForKey: @"Torrents"];
     517    BOOL deleteTorrent = [[dict objectForKey: @"DeleteTorrent"] boolValue];
     518    BOOL deleteData = [[dict objectForKey: @"DeleteData"] boolValue];
    524519    [dict release];
    525 }
    526 
    527 - (void) confirmRemoveTorrentWithIndex: (NSIndexSet *) indexSet
     520   
     521    if (returnCode == NSAlertDefaultReturn)
     522    {
     523        [self confirmRemoveTorrents: torrents
     524            deleteTorrent: deleteTorrent
     525            deleteData: deleteData];
     526    }
     527    else
     528        [torrents release];
     529}
     530
     531- (void) confirmRemoveTorrents: (NSArray *) torrents
    528532            deleteTorrent: (BOOL) deleteTorrent
    529533            deleteData: (BOOL) deleteData
    530534{
    531535    Torrent * torrent;
    532     unsigned int i;
    533    
    534     for (i = [indexSet lastIndex]; i != NSNotFound; i = [indexSet indexLessThanIndex: i])
    535     {
    536         torrent = [fTorrents objectAtIndex: i];
    537    
     536    NSEnumerator * enumerator = [torrents objectEnumerator];
     537    while ((torrent = [enumerator nextObject]))
     538    {
    538539        [torrent stop];
    539540
     
    543544        if( deleteTorrent )
    544545            [torrent trashTorrent];
    545        
     546
    546547        [fTorrents removeObject: torrent];
    547         [torrent release];
    548     }
    549 
     548    }
     549    [torrents release];
     550   
     551    [self torrentNumberChanged];
     552
     553    [fTableView deselectAll: nil];
    550554    [self updateUI: nil];
    551555    [self updateTorrentHistory];
     
    554558- (void) removeTorrent: (id) sender
    555559{
    556     [self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: NO ];
     560    [self removeTorrentWithIndex: [fTableView selectedRowIndexes] deleteTorrent: NO deleteData: NO];
    557561}
    558562
     
    572576}
    573577
    574 - (void) showInfo: (id) sender
    575 {
    576     if( [fInfoPanel isVisible] )
    577     {
    578         [fInfoPanel close];
    579     }
    580     else
    581     {
    582         [fInfoPanel orderFront: sender];
    583     }
    584 }
    585 
    586 - (void) updateInfoPanel
    587 {
    588     int numberSelected = [fTableView numberOfSelectedRows];
    589     if( numberSelected != 1 )
    590     {
    591         [fInfoImageView setImage: fAppIcon];
    592        
    593         [fInfoName setStringValue: numberSelected == 0
    594                 ? @"No Torrent Selected"
    595                 : [[NSString stringWithInt: numberSelected]
    596                     stringByAppendingString: @" Torrents Selected"]];
    597                    
    598         [fInfoSize setStringValue: @""];
    599         [fInfoTracker setStringValue: @""];
    600         [fInfoAnnounce setStringValue: @""];
    601         [fInfoPieceSize setStringValue: @""];
    602         [fInfoPieces setStringValue: @""];
    603         [fInfoHash1 setStringValue: @""];
    604         [fInfoHash2 setStringValue: @""];
    605         [fInfoSeeders setStringValue: @""];
    606         [fInfoLeechers setStringValue: @""];
    607         [fInfoDownloaded setStringValue: @""];
    608         [fInfoUploaded setStringValue: @""];
    609         return;
    610     }
    611    
    612     int row = [fTableView selectedRow];
    613 
    614     Torrent * torrent = [fTorrents objectAtIndex: row];
    615     [fInfoImageView setImage: [torrent iconNonFlipped]];
    616     [fInfoName setStringValue: [torrent name]];
    617     [fInfoSize setStringValue: [NSString
    618         stringForFileSize: [torrent size]]];
    619     [fInfoTracker setStringValue: [torrent tracker]];
    620     [fInfoAnnounce setStringValue: [torrent announce]];
    621     [fInfoPieceSize setStringValue: [NSString
    622         stringForFileSize: [torrent pieceSize]]];
    623     [fInfoPieces setIntValue: [torrent pieceCount]];
    624     [fInfoHash1 setStringValue: [torrent hash1]];
    625     [fInfoHash2 setStringValue: [torrent hash2]];
    626     int seeders = [torrent seeders], leechers = [torrent leechers];
    627     [fInfoSeeders setStringValue: seeders < 0 ?
    628         @"?" : [NSString stringWithInt: seeders]];
    629     [fInfoLeechers setStringValue: leechers < 0 ?
    630         @"?" : [NSString stringWithInt: leechers]];
    631     [fInfoDownloaded setStringValue: [NSString
    632         stringForFileSize: [torrent downloaded]]];
    633     [fInfoUploaded setStringValue: [NSString
    634         stringForFileSize: [torrent uploaded]]];
     578- (void) revealTorrent: (id) sender
     579{
     580    Torrent * torrent;
     581    NSIndexSet * indexSet = [fTableView selectedRowIndexes];
     582    unsigned int i;
     583   
     584    for (i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
     585    {
     586        torrent = [fTorrents objectAtIndex: i];
     587        [torrent reveal];
     588    }
    635589}
    636590
    637591- (void) updateUI: (NSTimer *) t
    638592{
    639     float dl, ul;
    640     NSEnumerator * enumerator;
     593    NSEnumerator * enumerator = [fTorrents objectEnumerator];
    641594    Torrent * torrent;
    642 
    643     /* Update the TableView */
    644     enumerator = [fTorrents objectEnumerator];
    645595    while( ( torrent = [enumerator nextObject] ) )
    646596    {
     
    652602            [self notifyGrowl: [torrent name]];
    653603            if( ![fWindow isKeyWindow] )
    654             {
    655604                fCompleted++;
    656             }
    657         }
    658     }
     605               
     606            [self sortTorrents];
     607        }
     608    }
     609   
    659610    [fTableView reloadData];
    660 
     611   
    661612    //Update the global DL/UL rates
     613    float dl, ul;
    662614    tr_torrentRates( fLib, &dl, &ul );
    663615    NSString * downloadRate = [NSString stringForSpeed: dl];
     
    665617    [fTotalDLField setStringValue: downloadRate];
    666618    [fTotalULField setStringValue: uploadRate];
    667    
    668     int count = [fTorrents count];
    669     [fTotalTorrentsField setStringValue: [NSString stringWithFormat:
    670             @"%d Torrent%s", count, count == 1 ? "" : "s"]];
    671 
    672     [self updateInfoPanel];
     619
     620    [self updateInfoStats];
    673621
    674622    //badge dock
     
    688636    Torrent * torrent;
    689637    while( ( torrent = [enumerator nextObject] ) )
    690     {
    691         [history addObject: [NSDictionary dictionaryWithObjectsAndKeys:
    692             [torrent path],                      @"TorrentPath",
    693             [torrent getFolder],                 @"DownloadFolder",
    694             [torrent isActive] ? @"NO" : @"YES", @"Paused",
    695             [torrent date],                      @"Date",
    696             nil]];
    697     }
     638        [history addObject: [torrent history]];
    698639
    699640    [fDefaults setObject: history forKey: @"History"];
    700641}
    701642
     643- (void) showInfo: (id) sender
     644{
     645    if ([[fInfoController window] isVisible])
     646        [[fInfoController window] performClose: nil];
     647    else
     648    {
     649        [fInfoController updateInfoForTorrents: [self torrentsAtIndexes:
     650                                            [fTableView selectedRowIndexes]]];
     651        [[fInfoController window] orderFront: nil];
     652    }
     653}
     654
     655- (void) updateInfo
     656{
     657    if ([[fInfoController window] isVisible])
     658        [fInfoController updateInfoForTorrents: [self torrentsAtIndexes:
     659                                            [fTableView selectedRowIndexes]]];
     660}
     661
     662- (void) updateInfoStats
     663{
     664    if ([[fInfoController window] isVisible])
     665        [fInfoController updateInfoStatsForTorrents: [self torrentsAtIndexes:
     666                                            [fTableView selectedRowIndexes]]];
     667}
     668
     669- (void) sortTorrents
     670{
     671    //remember selected rows if needed
     672    NSArray * selectedTorrents = nil;
     673    int numSelected = [fTableView numberOfSelectedRows];
     674    if (numSelected > 0 && numSelected < [fTorrents count])
     675        selectedTorrents = [self torrentsAtIndexes: [fTableView selectedRowIndexes]];
     676
     677    NSSortDescriptor * nameDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     678                                            @"name" ascending: YES] autorelease],
     679                    * dateDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     680                                            @"date" ascending: YES] autorelease];
     681
     682    NSArray * descriptors;
     683    if ([fSortType isEqualToString: @"Name"])
     684        descriptors = [[NSArray alloc] initWithObjects: nameDescriptor, dateDescriptor, nil];
     685    else if ([fSortType isEqualToString: @"State"])
     686    {
     687        NSSortDescriptor * stateDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     688                                                @"stateSortKey" ascending: NO] autorelease];
     689        descriptors = [[NSArray alloc] initWithObjects: stateDescriptor, nameDescriptor, dateDescriptor, nil];
     690    }
     691    else
     692        descriptors = [[NSArray alloc] initWithObjects: dateDescriptor, nameDescriptor, nil];
     693
     694    [fTorrents sortUsingDescriptors: descriptors];
     695    [descriptors release];
     696   
     697    [fTableView reloadData];
     698   
     699    //set selected rows if needed
     700    if (selectedTorrents)
     701    {
     702        [fTableView deselectAll: nil];
     703       
     704        Torrent * torrent;
     705        NSEnumerator * enumerator = [selectedTorrents objectEnumerator];
     706        while ((torrent = [enumerator nextObject]))
     707            [fTableView selectRow: [fTorrents indexOfObject: torrent] byExtendingSelection: YES];
     708    }
     709}
     710
     711- (void) setSort: (id) sender
     712{
     713    [fCurrentSortItem setState: NSOffState];
     714    fCurrentSortItem = sender;
     715    [sender setState: NSOnState];
     716
     717    if (sender == fNameSortItem)
     718        fSortType = @"Name";
     719    else if (sender == fStateSortItem)
     720        fSortType = @"State";
     721    else
     722        fSortType = @"Date";
     723       
     724    [fDefaults setObject: fSortType forKey: @"Sort"];
     725
     726    [self sortTorrents];
     727}
     728
    702729- (int) numberOfRowsInTableView: (NSTableView *) t
    703730{
    704731    return [fTorrents count];
    705 }
    706 
    707 - (id) tableView: (NSTableView *) t objectValueForTableColumn:
    708     (NSTableColumn *) tableColumn row: (int) rowIndex
    709 {
    710     return nil;
    711732}
    712733
     
    716737    [cell setTorrent: [fTorrents objectAtIndex: rowIndex]];
    717738
    718     if( OSX_VERSION >= 10.3 && [fWindow isKeyWindow] &&
    719                     [fTableView isRowSelected: rowIndex] )
     739    if( [fWindow isKeyWindow] && [fTableView isRowSelected: rowIndex] )
    720740        [cell setTextColor: [NSColor whiteColor]];
    721741    else
     
    745765        return NSDragOperationNone;
    746766
    747     [fTableView setDropRow: [fTorrents count]
     767    [fTableView setDropRow: [fTableView numberOfRows]
    748768        dropOperation: NSTableViewDropAbove];
    749769    return NSDragOperationGeneric;
     
    752772- (void) tableViewSelectionDidChange: (NSNotification *) n
    753773{
    754     [self updateInfoPanel];
     774    [self updateInfo];
    755775}
    756776
     
    764784        [item setLabel: @"Open"];
    765785        [item setPaletteLabel: [item label]];
    766         [item setToolTip: @"Open a torrent"];
     786        [item setToolTip: @"Open torrent files"];
    767787        [item setImage: [NSImage imageNamed: @"Open.png"]];
    768788        [item setTarget: self];
     
    773793        [item setLabel: @"Remove"];
    774794        [item setPaletteLabel: [item label]];
    775         [item setToolTip: @"Remove torrent from list"];
     795        [item setToolTip: @"Remove selected torrents"];
    776796        [item setImage: [NSImage imageNamed: @"Remove.png"]];
    777797        [item setTarget: self];
     
    782802        [item setLabel: @"Info"];
    783803        [item setPaletteLabel: [item label]];
    784         [item setToolTip: @"Information"];
     804        [item setToolTip: @"Display torrent info"];
    785805        [item setImage: [NSImage imageNamed: @"Info.png"]];
    786806        [item setTarget: self];
     
    818838    return [NSArray arrayWithObjects:
    819839            TOOLBAR_OPEN, TOOLBAR_REMOVE,
    820             TOOLBAR_RESUME_ALL, TOOLBAR_PAUSE_ALL,
     840            TOOLBAR_PAUSE_ALL, TOOLBAR_RESUME_ALL,
    821841            TOOLBAR_INFO,
    822842            NSToolbarSeparatorItemIdentifier,
    823843            NSToolbarSpaceItemIdentifier,
    824844            NSToolbarFlexibleSpaceItemIdentifier,
    825             NSToolbarCustomizeToolbarItemIdentifier,
    826             NULL];
     845            NSToolbarCustomizeToolbarItemIdentifier, nil];
    827846}
    828847
     
    832851            TOOLBAR_OPEN, TOOLBAR_REMOVE,
    833852            NSToolbarSeparatorItemIdentifier,
    834             TOOLBAR_RESUME_ALL, TOOLBAR_PAUSE_ALL,
     853            TOOLBAR_PAUSE_ALL, TOOLBAR_RESUME_ALL,
    835854            NSToolbarFlexibleSpaceItemIdentifier,
    836             TOOLBAR_INFO,
    837             NULL];
    838 }
    839 
    840 - (void) runCustomizationPalette: (id) sender
    841 {
    842     [fToolbar runCustomizationPalette:sender];
    843 }
    844 
    845 - (void) showHideToolbar: (id) sender
    846 {
    847     [fWindow toggleToolbarShown:sender];
     855            TOOLBAR_INFO, nil];
    848856}
    849857
     
    866874}
    867875
    868 - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
     876- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem
    869877{
    870878    SEL action = [toolbarItem action];
     
    900908}
    901909
    902 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
     910- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
    903911{
    904912    SEL action = [menuItem action];
    905913
    906     //disable menus if customize sheet is active
    907     if ([fToolbar customizationPaletteIsRunning])
    908         return NO;
    909 
    910     //enable customize toolbar item
    911     if (action == @selector(showHideToolbar:))
    912     {
    913         [menuItem setTitle: [fToolbar isVisible] ? @"Hide Toolbar" : @"Show Toolbar"];
    914         return YES;
    915     }
     914    //only enable some menus if window is useable
     915    BOOL canUseWindow = [fWindow isKeyWindow] && ![fToolbar customizationPaletteIsRunning];
    916916
    917917    //enable show info
    918918    if (action == @selector(showInfo:))
    919919    {
    920         [menuItem setTitle: [fInfoPanel isVisible] ? @"Hide Info" : @"Show Info"];
     920        [menuItem setTitle: [[fInfoController window] isVisible] ? @"Hide Info" : @"Show Info"];
    921921        return YES;
    922922    }
     
    926926    {
    927927        [menuItem setTitle: fStatusBar ? @"Hide Status Bar" : @"Show Status Bar"];
    928         return YES;
     928        return canUseWindow;
    929929    }
    930930
     
    951951    }
    952952
    953     if (action == @selector(revealFromMenu:))
    954     {
    955         return [fTableView numberOfSelectedRows] > 0;
     953    if (action == @selector(revealTorrent:))
     954    {
     955        return canUseWindow && [fTableView numberOfSelectedRows] > 0;
    956956    }
    957957
     
    978978   
    979979        //append or remove ellipsis when needed
    980         if( active && [fDefaults boolForKey: @"CheckRemove"] )
    981         {
    982             if (![[menuItem title] hasSuffix:NS_ELLIPSIS])
    983                 [menuItem setTitle:[[menuItem title] stringByAppendingString:NS_ELLIPSIS]];
     980        NSString * title = [menuItem title];
     981        if (active && [fDefaults boolForKey: @"CheckRemove"])
     982        {
     983            if (![title hasSuffix: NS_ELLIPSIS])
     984                [menuItem setTitle: [title stringByAppendingString: NS_ELLIPSIS]];
    984985        }
    985986        else
    986987        {
    987             if ([[menuItem title] hasSuffix:NS_ELLIPSIS])
    988                 [menuItem setTitle:[[menuItem title] substringToIndex:[[menuItem title] length]-[NS_ELLIPSIS length]]];
    989         }
    990         return [fTableView numberOfSelectedRows] > 0;
     988            if ([title hasSuffix: NS_ELLIPSIS])
     989                [menuItem setTitle:[title substringToIndex:
     990                            [title rangeOfString: NS_ELLIPSIS].location]];
     991        }
     992        return canUseWindow && [fTableView numberOfSelectedRows] > 0;
    991993    }
    992994
     
    994996    if( action == @selector(stopTorrent:) )
    995997    {
     998        if (!canUseWindow)
     999            return NO;
     1000   
    9961001        Torrent * torrent;
    9971002        NSIndexSet * indexSet = [fTableView selectedRowIndexes];
     
    10101015    if( action == @selector(resumeTorrent:) )
    10111016    {
     1017        if (!canUseWindow)
     1018            return NO;
     1019   
    10121020        Torrent * torrent;
    10131021        NSIndexSet * indexSet = [fTableView selectedRowIndexes];
     
    10221030        return NO;
    10231031    }
     1032   
     1033    //enable resume item
     1034    if (action == @selector(setSort:))
     1035        return canUseWindow;
    10241036
    10251037    return YES;
     
    10381050            /* Close all connections before going to sleep and remember
    10391051               we should resume when we wake up */
    1040             enumerator = [fTorrents objectEnumerator];
    1041             while( ( torrent = [enumerator nextObject] ) )
    1042             {
    1043                 [torrent sleep];
    1044             }
     1052            [fTorrents makeObjectsPerformSelector: @selector(sleep)];
    10451053
    10461054            /* Wait for torrents to stop (5 seconds timeout) */
     
    10761084        case kIOMessageSystemHasPoweredOn:
    10771085            /* Resume download after we wake up */
    1078             enumerator = [fTorrents objectEnumerator];
    1079             while( ( torrent = [enumerator nextObject] ) )
    1080             {
    1081                 [torrent wakeUp];
    1082             }
     1086            [fTorrents makeObjectsPerformSelector: @selector(wakeUp)];
    10831087            break;
    10841088    }
     
    10881092    defaultFrame: (NSRect) defaultFrame
    10891093{
    1090     NSRect rectWin, rectView;
    1091     float  foo;
    1092 
    1093     rectWin  = [fWindow frame];
    1094     rectView = [fScrollView frame];
    1095     foo      = 10.0 - rectView.size.height + MAX( 1U, [fTorrents count] ) *
    1096         ( [fTableView rowHeight] + [fTableView intercellSpacing].height );
    1097 
    1098     rectWin.size.height += foo;
    1099     rectWin.origin.y    -= foo;
     1094    NSRect rectWin = [fWindow frame];
     1095    float newHeight = rectWin.size.height - [fScrollView frame].size.height
     1096            + [fTorrents count] * ([fTableView rowHeight] + [fTableView intercellSpacing].height);
     1097
     1098    float minHeight = [fWindow minSize].height;
     1099    if (newHeight < minHeight)
     1100        newHeight = minHeight;
     1101
     1102    rectWin.origin.y -= (newHeight - rectWin.size.height);
     1103    rectWin.size.height = newHeight;
    11001104
    11011105    return rectWin;
     
    11761180}
    11771181
    1178 - (void) revealFromMenu: (id) sender
    1179 {
    1180     Torrent * torrent;
    1181     torrent = [fTorrents objectAtIndex: [fTableView selectedRow]];
    1182     [torrent reveal];
    1183 }
    1184 
    11851182- (void) checkForUpdate: (id) sender
    11861183{
     
    11911188{
    11921189    NSString * check = [fDefaults stringForKey: @"VersionCheck"];
    1193     if( [check isEqualToString: @"Never"] )
    1194         return;
    11951190
    11961191    NSTimeInterval interval;
     
    12021197        return;
    12031198
    1204     id lastObject = [fDefaults objectForKey: @"VersionCheckLast"];
    1205     NSDate * lastDate = [lastObject isKindOfClass: [NSDate class]] ?
    1206         lastObject : nil;
     1199    NSDate * lastDate = [fDefaults objectForKey: @"VersionCheckLast"];
    12071200    if( lastDate )
    12081201    {
    1209         NSTimeInterval actualInterval =
    1210             [[NSDate date] timeIntervalSinceDate: lastDate];
     1202        NSTimeInterval actualInterval = [[NSDate date]
     1203                            timeIntervalSinceDate: lastDate];
    12111204        if( actualInterval > 0 && actualInterval < interval )
    1212         {
    12131205            return;
    1214         }
    12151206    }
    12161207
     
    12281219- (void) URLResourceDidFinishLoading: (NSURL *) sender
    12291220{
     1221    //check if plist was actually found and contains a version
    12301222    NSDictionary * dict = [NSPropertyListSerialization
    12311223                            propertyListFromData: [sender resourceDataUsingCache: NO]
    12321224                            mutabilityOption: NSPropertyListImmutable
    12331225                            format: nil errorDescription: nil];
    1234 
    1235     //check if plist was actually found and contains a version
    1236     NSString * webVersion = nil;
    1237     if (dict)
    1238         webVersion = [dict objectForKey: @"Version"];
    1239     if (!webVersion)
     1226    NSString * webVersion;
     1227    if (!dict || !(webVersion = [dict objectForKey: @"Version"]))
    12401228    {
    12411229        if (!fCheckIsAutomatic)
    12421230        {
    1243             if( OSX_VERSION >= 10.3 )
    1244             {
    1245                 NSAlert * dialog = [[NSAlert alloc] init];
    1246                 [dialog addButtonWithTitle: @"OK"];
    1247                 [dialog setMessageText: @"Error checking for updates."];
    1248                 [dialog setInformativeText:
    1249                         @"Transmission was not able to check the latest version available."];
    1250                 [dialog setAlertStyle: NSInformationalAlertStyle];
    1251 
    1252                 [dialog runModal];
    1253                 [dialog release];
    1254             }
    1255             else
    1256                 /* XXX */;
     1231            NSAlert * dialog = [[NSAlert alloc] init];
     1232            [dialog addButtonWithTitle: @"OK"];
     1233            [dialog setMessageText: @"Error checking for updates."];
     1234            [dialog setInformativeText:
     1235                    @"Transmission was not able to check the latest version available."];
     1236            [dialog setAlertStyle: NSInformationalAlertStyle];
     1237
     1238            [dialog runModal];
     1239            [dialog release];
    12571240        }
    12581241        return;
     
    12761259        }
    12771260
    1278         if( OSX_VERSION >= 10.3 )
    1279         {
    1280             result = [currentSub compare: webSub options: NSNumericSearch];
    1281             if (result != NSOrderedSame)
    1282             {
    1283                 if (result == NSOrderedAscending)
    1284                     webGreater = YES;
    1285                 break;
    1286             }
    1287         }
    1288         else
    1289             /* XXX */;
     1261        result = [currentSub compare: webSub options: NSNumericSearch];
     1262        if (result != NSOrderedSame)
     1263        {
     1264            if (result == NSOrderedAscending)
     1265                webGreater = YES;
     1266            break;
     1267        }
    12901268    }
    12911269
    12921270    if (webGreater)
    12931271    {
    1294         if( OSX_VERSION >= 10.3 )
    1295         {
    1296             NSAlert * dialog = [[NSAlert alloc] init];
    1297             [dialog addButtonWithTitle: @"Go to Website"];
    1298             [dialog addButtonWithTitle:@"Cancel"];
    1299             [dialog setMessageText: @"New version is available!"];
    1300             [dialog setInformativeText: [NSString stringWithFormat:
    1301                 @"A newer version (%@) is available for download from the Transmission website.", webVersion]];
    1302             [dialog setAlertStyle: NSInformationalAlertStyle];
    1303 
    1304             if ([dialog runModal] == NSAlertFirstButtonReturn)
    1305                 [self linkHomepage: nil];
    1306 
    1307             [dialog release];
    1308         }
    1309         else
    1310             /* XXX */;
     1272        NSAlert * dialog = [[NSAlert alloc] init];
     1273        [dialog addButtonWithTitle: @"Go to Website"];
     1274        [dialog addButtonWithTitle:@"Cancel"];
     1275        [dialog setMessageText: @"New version is available!"];
     1276        [dialog setInformativeText: [NSString stringWithFormat:
     1277            @"A newer version (%@) is available for download from the Transmission website.", webVersion]];
     1278        [dialog setAlertStyle: NSInformationalAlertStyle];
     1279
     1280        if ([dialog runModal] == NSAlertFirstButtonReturn)
     1281            [self linkHomepage: nil];
     1282
     1283        [dialog release];
    13111284    }
    13121285    else if (!fCheckIsAutomatic)
    13131286    {
    1314         if( OSX_VERSION >= 10.3 )
    1315         {
    1316             NSAlert * dialog = [[NSAlert alloc] init];
    1317             [dialog addButtonWithTitle: @"OK"];
    1318             [dialog setMessageText: @"No new versions are available."];
    1319             [dialog setInformativeText: [NSString stringWithFormat:
    1320                 @"You are running the most current version of Transmission (%@).", currentVersion]];
    1321             [dialog setAlertStyle: NSInformationalAlertStyle];
    1322 
    1323             [dialog runModal];
    1324             [dialog release];
    1325         }
    1326         else
    1327             /* XXX */;
     1287        NSAlert * dialog = [[NSAlert alloc] init];
     1288        [dialog addButtonWithTitle: @"OK"];
     1289        [dialog setMessageText: @"No new versions are available."];
     1290        [dialog setInformativeText: [NSString stringWithFormat:
     1291            @"You are running the most current version of Transmission (%@).", currentVersion]];
     1292        [dialog setAlertStyle: NSInformationalAlertStyle];
     1293
     1294        [dialog runModal];
     1295        [dialog release];
    13281296    }
    13291297    else;
  • trunk/macosx/Defaults.plist

    r247 r256  
    33<plist version="1.0">
    44<dict>
     5        <key>AutoStartDownload</key>
     6        <true/>
    57        <key>BadgeDownloadRate</key>
    68        <false/>
     
    2325        <key>DownloadLimit</key>
    2426        <integer>100</integer>
     27        <key>History</key>
     28        <array/>
    2529        <key>InfoVisible</key>
    2630        <false/>
     
    3135        <key>MoveFolder</key>
    3236        <string>~/Desktop</string>
     37        <key>RatioCheck</key>
     38        <false/>
     39        <key>RatioLimit</key>
     40        <integer>2</integer>
    3341        <key>ShowInspector</key>
    3442        <false/>
     43        <key>Sort</key>
     44        <string>Date</string>
    3545        <key>StatusBar</key>
    3646        <true/>
  • trunk/macosx/English.lproj/MainMenu.nib/classes.nib

    r247 r256  
    1515                resumeAllTorrents = id;
    1616                resumeTorrent = id;
    17                 revealFromMenu = id;
    18                 runCustomizationPalette = id;
    19                 showHideToolbar = id;
     17                revealTorrent = id;
     18                setSort = id;
    2019                showInfo = id;
    2120                showMainWindow = id;
     
    2827            LANGUAGE = ObjC;
    2928            OUTLETS = {
     29                fActionButton = NSButton;
    3030                fAdvancedBarItem = NSMenuItem;
    31                 fInfoAnnounce = NSTextField;
    32                 fInfoDownloaded = NSTextField;
    33                 fInfoHash1 = NSTextField;
    34                 fInfoHash2 = NSTextField;
    35                 fInfoImageView = NSImageView;
    36                 fInfoLeechers = NSTextField;
    37                 fInfoName = NSTextField;
    38                 fInfoPanel = NSPanel;
    39                 fInfoPieceSize = NSTextField;
    40                 fInfoPieces = NSTextField;
    41                 fInfoSeeders = NSTextField;
    42                 fInfoSize = NSTextField;
    43                 fInfoTracker = NSTextField;
    44                 fInfoUploaded = NSTextField;
     31                fDateSortItem = NSMenuItem;
     32                fNameSortItem = NSMenuItem;
    4533                fPauseResumeItem = NSMenuItem;
    4634                fPrefsController = PrefsController;
     
    5341                fScrollView = NSScrollView;
    5442                fShowHideToolbar = NSMenuItem;
     43                fStateSortItem = NSMenuItem;
    5544                fStats = NSBox;
    5645                fTableView = TorrentTableView;
     
    6958            ACTIONS = {
    7059                folderSheetShow = id;
     60                setAutoStart = id;
    7161                setBadge = id;
    7262                setDownloadLocation = id;
     
    7565                setLimitMenu = id;
    7666                setPort = id;
     67                setQuickRatio = id;
    7768                setQuickSpeed = id;
    78                 setQuitMessage = id;
    79                 setRemoveMessage = id;
     69                setRatio = id;
     70                setRatioCheck = id;
     71                setRatioMenu = id;
     72                setShowMessage = id;
    8073                setUpdate = id;
    8174            };
     
    8376            LANGUAGE = ObjC;
    8477            OUTLETS = {
     78                fAutoStartCheck = NSButton;
    8579                fBadgeDownloadRateCheck = NSButton;
    8680                fBadgeUploadRateCheck = NSButton;
     
    9791                fPrefsWindow = NSPanel;
    9892                fQuitCheck = NSButton;
     93                fRatioCheck = NSButton;
     94                fRatioField = NSTextField;
     95                fRatioNotSetItem = NSMenuItem;
     96                fRatioSetItem = NSMenuItem;
    9997                fRemoveCheck = NSButton;
     98                fTransfersView = NSView;
    10099                fUpdatePopUp = NSPopUpButton;
    101100                fUploadCheck = NSButton;
  • trunk/macosx/English.lproj/MainMenu.nib/info.nib

    r247 r256  
    88        <dict>
    99                <key>1041</key>
    10                 <string>344 478 204 68 0 0 1152 842 </string>
     10                <string>344 478 208 99 0 0 1152 842 </string>
     11                <key>1343</key>
     12                <string>344 526 463 104 0 0 1152 842 </string>
    1113                <key>29</key>
    12                 <string>79 778 371 44 0 0 1152 842 </string>
     14                <string>154 771 371 44 0 0 1152 842 </string>
    1315                <key>456</key>
    14                 <string>212 488 144 118 0 0 1152 842 </string>
     16                <string>212 488 144 137 0 0 1152 842 </string>
    1517                <key>581</key>
    1618                <string>324 628 112 68 0 0 1152 842 </string>
     
    1820                <string>54 521 103 68 0 0 1152 842 </string>
    1921                <key>783</key>
    20                 <string>366 453 420 250 0 0 1152 842 </string>
     22                <string>347 472 457 212 0 0 1152 842 </string>
    2123                <key>796</key>
    22                 <string>366 496 420 164 0 0 1152 842 </string>
     24                <string>347 461 457 234 0 0 1152 842 </string>
    2325                <key>825</key>
    24                 <string>498 525 155 107 0 0 1152 842 </string>
     26                <string>348 524 463 107 0 0 1152 842 </string>
    2527        </dict>
    2628        <key>IBFramework Version</key>
    27         <string>443.0</string>
     29        <string>446.1</string>
    2830        <key>IBOldestOS</key>
    2931        <integer>3</integer>
    30         <key>IBOpenObjects</key>
    31         <array>
    32                 <integer>21</integer>
    33         </array>
    3432        <key>IBSystem Version</key>
    3533        <string>8I127</string>
  • trunk/macosx/MenuButton.m

    r247 r256  
    88   [self highlight: YES];
    99   
    10    [NSMenu popUpContextMenu: [self menu] withEvent: event forView: self];
     10   NSPoint location = NSMakePoint(3, -2);
     11   
     12   NSEvent * theEvent= [NSEvent mouseEventWithType: [event type]
     13                        location: location
     14                        modifierFlags: [event modifierFlags]
     15                        timestamp: [event timestamp]
     16                        windowNumber: [event windowNumber]
     17                        context: [event context]
     18                        eventNumber: [event eventNumber]
     19                        clickCount: [event clickCount]
     20                        pressure: [event pressure]];
     21
     22   [NSMenu popUpContextMenu: [self menu] withEvent: theEvent forView: self];
    1123   
    1224   [self setState: NSOffState];
  • trunk/macosx/PrefsController.h

    r247 r256  
    3131    IBOutlet NSPanel        * fPrefsWindow;
    3232    NSToolbar               * fToolbar;
    33     IBOutlet NSView         * fGeneralView;
    34     IBOutlet NSView         * fNetworkView;
    35     IBOutlet NSView         * fBlankView;
     33    IBOutlet NSView         * fGeneralView, * fTransfersView,
     34                            * fNetworkView, * fBlankView;
    3635   
    3736    IBOutlet NSPopUpButton  * fFolderPopUp;
    38     IBOutlet NSButton       * fQuitCheck;
    39     IBOutlet NSButton       * fRemoveCheck;
    40     IBOutlet NSButton       * fBadgeDownloadRateCheck;
    41     IBOutlet NSButton       * fBadgeUploadRateCheck;                           
     37    IBOutlet NSButton       * fQuitCheck, * fRemoveCheck,
     38                            * fBadgeDownloadRateCheck, * fBadgeUploadRateCheck,
     39                            * fAutoStartCheck;                           
    4240    IBOutlet NSPopUpButton  * fUpdatePopUp;
    4341
     
    4745    IBOutlet NSButton       * fDownloadCheck;
    4846    IBOutlet NSTextField    * fDownloadField;
     47    IBOutlet NSButton       * fRatioCheck;
     48    IBOutlet NSTextField    * fRatioField;
    4949   
    5050    IBOutlet NSMenu         * fUploadMenu, * fDownloadMenu;
    5151    IBOutlet NSMenuItem     * fUploadLimitItem, * fUploadNoLimitItem,
    52                             * fDownloadLimitItem, * fDownloadNoLimitItem;
     52                            * fDownloadLimitItem, * fDownloadNoLimitItem,
     53                            * fRatioSetItem, * fRatioNotSetItem;
    5354   
    5455    IBOutlet NSWindow       * fWindow;
     
    6061- (void) setPrefsWindow: (tr_handle_t *) handle;
    6162
    62 - (void) setQuitMessage:        (id) sender;
    63 - (void) setRemoveMessage:      (id) sender;
     63- (void) setShowMessage:        (id) sender;
    6464- (void) setBadge:              (id) sender;
    6565- (void) setUpdate:             (id) sender;
     66- (void) setAutoStart:          (id) sender;
    6667- (void) setDownloadLocation:   (id) sender;
    6768- (void) folderSheetShow:       (id) sender;
     
    7374- (void) setQuickSpeed:         (id) sender;
    7475
     76- (void) setRatio:              (id) sender;
     77- (void) setRatioCheck:                 (id) sender;
     78- (void) setRatioMenu:          (id) sender;
     79- (void) setQuickRatio:         (id) sender;
     80
    7581@end
  • trunk/macosx/PrefsController.m

    r247 r256  
    2525#import "Utils.h"
    2626
    27 #define MIN_PORT            1
    28 #define MAX_PORT            65535
    29 
    3027#define DOWNLOAD_FOLDER     0
    3128#define DOWNLOAD_TORRENT    2
     
    3734
    3835#define TOOLBAR_GENERAL     @"General"
     36#define TOOLBAR_TRANSFERS    @"Transfers"
    3937#define TOOLBAR_NETWORK     @"Network"
    4038
     
    4240
    4341- (void) showGeneralPref: (id) sender;
     42- (void) showTransfersPref: (id) sender;
    4443- (void) showNetworkPref: (id) sender;
    4544
     
    6261}
    6362
    64 - (void)dealloc
     63- (void) dealloc
    6564{
    6665    [fDownloadFolder release];
     
    7675    [fToolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
    7776    [fToolbar setSizeMode: NSToolbarSizeModeRegular];
    78     [[fPrefsWindow standardWindowButton: NSWindowToolbarButton]
    79         setFrame: NSZeroRect];
    80 
    81     if( [fToolbar respondsToSelector: @selector(setSelectedItemIdentifier:) ] )
    82         [fToolbar setSelectedItemIdentifier: TOOLBAR_GENERAL];
    83     [self setPrefView: fGeneralView];
     77
     78    [fToolbar setSelectedItemIdentifier: TOOLBAR_GENERAL];
     79    [self showGeneralPref: nil];
    8480
    8581    fDefaults = [NSUserDefaults standardUserDefaults];
     82    fHandle = handle;
    8683   
    8784    //set download folder
     
    134131    tr_setUploadLimit( fHandle, checkUpload ? uploadLimit : -1 );
    135132
    136     //set download limit
     133        //set download limit
    137134    BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
    138135    int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
     
    150147   
    151148    tr_setDownloadLimit( fHandle, checkDownload ? downloadLimit : -1 );
     149   
     150    //set ratio limit
     151    BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
     152    float ratioLimit = [fDefaults floatForKey: @"RatioLimit"];
     153
     154    [fRatioCheck setState: ratioCheck ? NSOnState : NSOffState];
     155    [fRatioField setEnabled: ratioCheck];
     156    [fRatioField setFloatValue: ratioLimit];
     157   
     158    [fRatioSetItem setTitle: [NSString stringWithFormat: @"Stop at Ratio (%.1f)", ratioLimit]];
     159    if (ratioCheck)
     160        [fRatioSetItem setState: NSOnState];
     161    else
     162        [fRatioNotSetItem setState: NSOnState];
    152163   
    153164    //set remove and quit prompts
     
    160171    [fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
    161172    [fBadgeUploadRateCheck setState: [fDefaults boolForKey: @"BadgeUploadRate"]];
     173   
     174    //set auto start
     175    [fAutoStartCheck setState: [fDefaults boolForKey: @"AutoStartDownload"]];
    162176
    163177    /* Check for update */
     
    189203        [item setAction: @selector( showGeneralPref: )];
    190204    }
     205    else if ([ident isEqualToString: TOOLBAR_TRANSFERS])
     206    {
     207        [item setLabel: TOOLBAR_TRANSFERS];
     208        [item setImage: [NSImage imageNamed: @"Transfers.png"]];
     209        [item setTarget: self];
     210        [item setAction: @selector( showTransfersPref: )];
     211    }
    191212    else if ([ident isEqualToString: TOOLBAR_NETWORK])
    192213    {
     
    205226}
    206227
    207 /* Only used on OS X >= 10.3 */
    208 - (NSArray *) toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar
     228- (NSArray *) toolbarSelectableItemIdentifiers: (NSToolbar *) toolbar
    209229{
    210230    return [self toolbarDefaultItemIdentifiers: nil];
    211231}
    212232
    213 - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
     233- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
    214234{
    215235    return [self toolbarAllowedItemIdentifiers: nil];
    216236}
    217237
    218 - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
     238- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
    219239{
    220240    return [NSArray arrayWithObjects:
    221             TOOLBAR_GENERAL,
    222             TOOLBAR_NETWORK,
    223             nil];
     241            TOOLBAR_GENERAL, TOOLBAR_TRANSFERS,
     242            TOOLBAR_NETWORK, nil];
    224243}
    225244
     
    228247    int bindPort = [fPortField intValue];
    229248   
    230     //if value entered is not an int or is not in range do not change
    231     if (![[fPortField stringValue] isEqualToString:
    232             [NSString stringWithInt: bindPort]]
    233             || bindPort < MIN_PORT
    234             || bindPort > MAX_PORT)
    235     {
    236         NSBeep();
    237         bindPort = [fDefaults integerForKey: @"BindPort"];
    238         [fPortField setIntValue: bindPort];
    239     }
    240     else
    241     {
    242         tr_setBindPort( fHandle, bindPort );
    243         [fDefaults setInteger: bindPort forKey: @"BindPort"];
    244     }
     249    tr_setBindPort( fHandle, bindPort );
     250    [fDefaults setInteger: bindPort forKey: @"BindPort"];
    245251}
    246252
    247253- (void) setLimit: (id) sender
    248254{
    249     int limit = [sender intValue];
    250    
    251255    NSString * key;
    252256    NSMenuItem * menuItem;
     
    262266    }
    263267
    264     //if value entered is not an int or is less than 0 do not change
    265     if (![[sender stringValue] isEqualToString:
    266             [NSString stringWithInt: limit]] || limit < 0)
    267     {
    268         NSBeep();
    269         limit = [fDefaults integerForKey: key];
    270         [sender setIntValue: limit];
    271     }
    272     else
    273     {
    274         [menuItem setTitle: [NSString stringWithFormat: @"Limit (%d KB/s)", limit]];
    275         [fDefaults setInteger: limit forKey: key];
    276     }
     268    int limit = [sender intValue];
     269    [fDefaults setInteger: limit forKey: key];
     270   
     271    [menuItem setTitle: [NSString stringWithFormat: @"Limit (%d KB/s)", limit]];
    277272
    278273    if( sender == fUploadField )
     
    309304   
    310305    [fDefaults setBool: check forKey: key];
    311 
     306   
     307    [field setIntValue: [field intValue]]; //set to valid value
    312308    [self setLimit: field];
    313309   
     
    343339}
    344340
    345 - (void) setQuitMessage: (id) sender
    346 {
    347     [fDefaults setBool: ( [fQuitCheck state] == NSOnState )
    348         forKey: @"CheckQuit"];
    349 }
    350 
    351 - (void) setRemoveMessage: (id) sender
    352 {
    353     [fDefaults setBool: ( [fRemoveCheck state] == NSOnState )
    354         forKey: @"CheckRemove"];
     341- (void) setRatio: (id) sender
     342{
     343    float ratio = [sender floatValue];
     344    [fDefaults setFloat: ratio forKey: @"RatioLimit"];
     345   
     346    [fRatioSetItem setTitle: [NSString stringWithFormat: @"Stop at Ratio (%.1f)", ratio]];
     347}
     348
     349- (void) setRatioCheck: (id) sender
     350{
     351    BOOL check = [sender state] == NSOnState;
     352   
     353    [fDefaults setBool: check forKey: @"RatioCheck"];
     354   
     355    [fRatioField setFloatValue: [fRatioField floatValue]]; //set to valid value
     356    [self setRatio: fRatioField];
     357   
     358    [fRatioField setEnabled: check];
     359   
     360    [fRatioSetItem setState: check ? NSOnState : NSOffState];
     361    [fRatioNotSetItem setState: !check ? NSOnState : NSOffState];
     362}
     363
     364- (void) setRatioMenu: (id) sender
     365{
     366    int state = sender == fRatioSetItem ? NSOnState : NSOffState;
     367               
     368    [fRatioCheck setState: state];
     369    [self setRatioCheck: fRatioCheck];
     370}
     371
     372- (void) setQuickRatio: (id) sender
     373{
     374    float limit = [[sender title] floatValue];
     375
     376    [fRatioField setFloatValue: limit];
     377    [self setRatioMenu: fRatioSetItem];
     378}
     379
     380- (void) setShowMessage: (id) sender
     381{
     382    if (sender == fQuitCheck)
     383        [fDefaults setBool: [sender state] forKey: @"CheckQuit"];
     384    else if (sender == fRemoveCheck)
     385        [fDefaults setBool: [fRemoveCheck state] forKey: @"CheckRemove"];
     386    else;
    355387}
    356388
    357389- (void) setBadge: (id) sender
    358390{   
    359     BOOL state = [sender state];
    360    
    361391    if (sender == fBadgeDownloadRateCheck)
    362         [fDefaults setBool: state forKey: @"BadgeDownloadRate"];
     392        [fDefaults setBool: [sender state] forKey: @"BadgeDownloadRate"];
    363393    else if (sender == fBadgeUploadRateCheck)
    364         [fDefaults setBool: state forKey: @"BadgeUploadRate"];
     394        [fDefaults setBool: [sender state] forKey: @"BadgeUploadRate"];
    365395    else;
    366396}
     
    382412}
    383413
     414- (void) setAutoStart: (id) sender
     415{
     416    [fDefaults setBool: [sender state] forKey: @"AutoStartDownload"];
     417}
     418
    384419- (void) setDownloadLocation: (id) sender
    385420{
     
    423458}
    424459
     460- (void) showTransfersPref: (id) sender
     461{
     462    [self setPrefView: fTransfersView];
     463}
     464
    425465- (void) showNetworkPref: (id) sender
    426466{
     
    436476    windowRect.size.height += difference;
    437477   
    438     if( [fToolbar respondsToSelector: @selector(selectedItemIdentifier) ] )
    439         [fPrefsWindow setTitle: [fToolbar selectedItemIdentifier]];
     478    [fPrefsWindow setTitle: [fToolbar selectedItemIdentifier]];
    440479    [fPrefsWindow setContentView: fBlankView];
    441     [fPrefsWindow setFrame:windowRect display: YES animate: YES];
     480    [fPrefsWindow setFrame: windowRect display: YES animate: YES];
    442481    [fPrefsWindow setContentView: view];
    443482}
  • trunk/macosx/Torrent.h

    r244 r256  
    3333    NSDate       * fDate;
    3434
     35    NSUserDefaults  * fDefaults;
     36
    3537    NSImage         * fIcon;
    3638    NSImage         * fIconNonFlipped;
     
    3941    NSMutableString * fDownloadString;
    4042    NSMutableString * fUploadString;
     43   
     44    int     fStopRatioSetting;
     45    float   fRatioLimit;
    4146}
    4247
    43 - (id)         initWithPath: (NSString *) path lib: (tr_handle_t *) lib;
    44 - (id)         initWithPath: (NSString *) path lib: (tr_handle_t *) lib
    45                         date: (NSDate *) date;
     48- (id)          initWithPath: (NSString *) path lib: (tr_handle_t *) lib;
     49- (id)          initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib;
     50- (NSDictionary *) history;
     51                   
    4652- (void)       setFolder: (NSString *) path;
    4753- (NSString *) getFolder;
     
    5359- (void)       sleep;
    5460- (void)       wakeUp;
     61
     62- (float)      ratio;
     63- (int)        stopRatioSetting;
     64- (void)       setStopRatioSetting: (int) setting;
     65- (float)      ratioLimit;
     66- (void)       setRatioLimit: (float) limit;
     67
     68- (NSNumber *) stateSortKey;
     69
    5570- (void)       reveal;
    5671- (void)       trashTorrent;
     
    6681- (int)        pieceSize;
    6782- (int)        pieceCount;
    68 - (NSString *) hash1;
    69 - (NSString *) hash2;
     83- (NSString *) hash;
    7084
    7185- (float)      progress;
  • trunk/macosx/Torrent.m

    r244 r256  
    2828
    2929- (void) trashPath: (NSString *) path;
     30- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
     31        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
    3032
    3133@end
     
    3436@implementation Torrent
    3537
    36 - (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
    37 {
    38     fLib = lib;
    39 
    40     int error;
    41     fHandle = tr_torrentInit( fLib, [path UTF8String], &error );
    42     if( !fHandle )
    43     {
    44         [self release];
    45         return nil;
    46     }
    47 
    48     fDate = [date retain];
    49     fInfo = tr_torrentInfo( fHandle );
    50 
    51     NSString * fileType = ( fInfo->fileCount > 1 ) ?
    52         NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
    53     fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
    54     [fIcon setFlipped: YES];
    55     [fIcon retain];
    56     fIconNonFlipped = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
    57     [fIconNonFlipped retain];
    58 
    59     fStatusString   = [[NSMutableString alloc] initWithCapacity: 50];
    60     fInfoString     = [[NSMutableString alloc] initWithCapacity: 50];
    61     fDownloadString = [[NSMutableString alloc] initWithCapacity: 10];
    62     fUploadString   = [[NSMutableString alloc] initWithCapacity: 10];
    63 
    64     [self update];
     38- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
     39{
     40    return [self initWithPath: path lib: lib
     41            date: nil stopRatioSetting: nil
     42            ratioLimit: nil];
     43}
     44
     45- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
     46{
     47    self = [self initWithPath: [history objectForKey: @"TorrentPath"]
     48            lib: lib date: [history objectForKey: @"Date"]
     49            stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
     50            ratioLimit: [history objectForKey: @"RatioLimit"]];
     51           
     52    if (self)
     53    {
     54        NSString * downloadFolder;
     55        if (!(downloadFolder = [history objectForKey: @"DownloadFolder"]))
     56            downloadFolder = [[fDefaults stringForKey: @"DownloadFolder"]
     57                                stringByExpandingTildeInPath];
     58        [self setFolder: downloadFolder];
     59
     60        NSString * paused;
     61        if (!(paused = [history objectForKey: @"Paused"]) || [paused isEqualToString: @"NO"])
     62            [self start];
     63    }
     64   
    6565    return self;
    6666}
    6767
    68 - (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
    69 {
    70     return [self initWithPath: path lib: lib date: [NSDate date]];
     68- (NSDictionary *) history
     69{
     70    return [NSDictionary dictionaryWithObjectsAndKeys:
     71            [self path], @"TorrentPath",
     72            [self getFolder], @"DownloadFolder",
     73            [self isActive] ? @"NO" : @"YES", @"Paused",
     74            [self date], @"Date",
     75            [NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
     76            [NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
    7177}
    7278
     
    7682    {
    7783        tr_torrentClose( fLib, fHandle );
     84       
    7885        [fDate release];
    7986        [fIcon release];
     
    105112{
    106113    fStat = tr_torrentStat( fHandle );
     114   
     115    if ([self isSeeding])
     116        if ((fStopRatioSetting == 1 && [self ratio] >= fRatioLimit)
     117            || (fStopRatioSetting == -1 && [fDefaults boolForKey: @"RatioCheck"]
     118                && [self ratio] >= [fDefaults floatForKey: @"RatioLimit"]))
     119        {
     120            [self stop];
     121            [self setStopRatioSetting: 0];
     122           
     123            fStat = tr_torrentStat( fHandle );
     124        }
    107125
    108126    [fStatusString setString: @""];
    109     [fInfoString   setString: @""];
     127    [fInfoString setString: @""];
    110128
    111129    switch( fStat->status )
     
    208226}
    209227
     228- (float) ratio
     229{
     230    uint64_t downloaded = [self downloaded];
     231    return downloaded > 0 ? [self uploaded] / downloaded : -1;
     232}
     233
     234/*  1: Check ratio
     235    0: Don't check ratio
     236   -1: Use defaults */
     237- (int) stopRatioSetting
     238{
     239        return fStopRatioSetting;
     240}
     241
     242- (void) setStopRatioSetting: (int) setting
     243{
     244    fStopRatioSetting = setting;
     245}
     246
     247- (float) ratioLimit
     248{
     249    return fRatioLimit;
     250}
     251
     252- (void) setRatioLimit: (float) limit
     253{
     254    if (limit >= 0)
     255        fRatioLimit = limit;
     256}
     257
    210258- (void) reveal
    211259{
     
    272320}
    273321
    274 - (NSString *) hash1
     322- (NSString *) hash
    275323{
    276324    NSMutableString * string = [NSMutableString
    277325        stringWithCapacity: SHA_DIGEST_LENGTH];
    278326    int i;
    279     for( i = 0; i < SHA_DIGEST_LENGTH / 2; i++ )
     327    for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
    280328    {
    281329        [string appendFormat: @"%02x", fInfo->hash[i]];
     
    283331    return string;
    284332}
    285 - (NSString *) hash2
    286 {
    287     NSMutableString * string = [NSMutableString
    288         stringWithCapacity: SHA_DIGEST_LENGTH];
    289     int i;
    290     for( i = SHA_DIGEST_LENGTH / 2; i < SHA_DIGEST_LENGTH; i++ )
    291     {
    292         [string appendFormat: @"%02x", fInfo->hash[i]];
    293     }
    294     return string;
    295 }
    296333
    297334- (float) progress
     
    365402}
    366403
     404- (NSNumber *) stateSortKey
     405{
     406    if (fStat->status & TR_STATUS_INACTIVE)
     407        return [NSNumber numberWithInt: 0];
     408    else if (fStat->status == TR_STATUS_SEED)
     409        return [NSNumber numberWithInt: 1];
     410    else
     411        return [NSNumber numberWithInt: 2];
     412}
     413
    367414@end
    368415
    369416
    370417@implementation Torrent (Private)
     418
     419- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
     420        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
     421{
     422    if (!(self = [super init]))
     423        return nil;
     424
     425    fLib = lib;
     426
     427    int error;
     428    if (!path || !(fHandle = tr_torrentInit(fLib, [path UTF8String], &error)))
     429    {
     430        [self release];
     431        return nil;
     432    }
     433   
     434    fInfo = tr_torrentInfo( fHandle );
     435   
     436    fDefaults = [NSUserDefaults standardUserDefaults];
     437
     438    fDate = date ? [date retain] : [[NSDate alloc] init];
     439    fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
     440    fRatioLimit = ratioLimit ? [ratioLimit floatValue] : [fDefaults floatForKey: @"RatioLimit"];
     441   
     442    NSString * fileType = ( fInfo->fileCount > 1 ) ?
     443        NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
     444    fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
     445    [fIcon setFlipped: YES];
     446    [fIcon retain];
     447    fIconNonFlipped = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
     448    [fIconNonFlipped retain];
     449
     450    fStatusString   = [[NSMutableString alloc] initWithCapacity: 50];
     451    fInfoString     = [[NSMutableString alloc] initWithCapacity: 50];
     452    fDownloadString = [[NSMutableString alloc] initWithCapacity: 10];
     453    fUploadString   = [[NSMutableString alloc] initWithCapacity: 10];
     454
     455    [self update];
     456    return self;
     457}
    371458
    372459- (void) trashPath: (NSString *) path
  • trunk/macosx/TorrentTableView.m

    r247 r256  
    7171}
    7272
    73 
    7473- (void) mouseDown: (NSEvent *) e
    7574{
     
    139138    {
    140139        if (![self isRowSelected: row])
    141         {
    142             if( OSX_VERSION >= 10.3 )
    143                 [self selectRowIndexes: [NSIndexSet indexSetWithIndex: row]
    144                     byExtendingSelection: NO];
    145             else
    146                 [self selectRow: row byExtendingSelection: NO];
    147         }
     140            [self selectRowIndexes: [NSIndexSet indexSetWithIndex: row]
     141                byExtendingSelection: NO];
     142               
    148143        return fContextRow;
    149144    }
Note: See TracChangeset for help on using the changeset viewer.