source: trunk/macosx/Torrent.m @ 855

Last change on this file since 855 was 855, checked in by livings124, 16 years ago

Use tableView:objectValueForTableColumn:row: instead of tableView:willDisplayCell:...

This required passing in a dictionary of values to display, but should make it 10.5 compatible and potentially a little more efficient. Those using Leopard please report any issues, because I don't have it to test.

  • Property svn:keywords set to Date Rev Author Id
File size: 21.5 KB
Line 
1/******************************************************************************
2 * $Id: Torrent.m 855 2006-09-11 23:52:03Z livings124 $
3 *
4 * Copyright (c) 2006 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "Torrent.h"
26#import "StringAdditions.h"
27
28@interface Torrent (Private)
29
30- (id) initWithHash: (NSString *) hashString path: (NSString *) path lib: (tr_handle_t *) lib
31        privateTorrent: (NSNumber *) privateTorrent publicTorrent: (NSNumber *) publicTorrent
32        date: (NSDate *) date stopRatioSetting: (NSNumber *) stopRatioSetting
33        ratioLimit: (NSNumber *) ratioLimit waitToStart: (NSNumber *) waitToStart
34        orderValue: (NSNumber *) orderValue;
35
36- (void) trashFile: (NSString *) path;
37
38@end
39
40@implementation Torrent
41
42- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
43{
44    self = [self initWithHash: nil path: path lib: lib privateTorrent: nil publicTorrent: nil
45            date: nil stopRatioSetting: nil ratioLimit: nil waitToStart: nil orderValue: nil];
46   
47    if (self)
48    {
49        if (!fPublicTorrent)
50            [self trashFile: path];
51    }
52    return self;
53}
54
55- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
56{
57    self = [self initWithHash: [history objectForKey: @"TorrentHash"]
58                path: [history objectForKey: @"TorrentPath"] lib: lib
59                privateTorrent: [history objectForKey: @"PrivateCopy"]
60                publicTorrent: [history objectForKey: @"PublicCopy"]
61                date: [history objectForKey: @"Date"]
62                stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
63                ratioLimit: [history objectForKey: @"RatioLimit"]
64                waitToStart: [history objectForKey: @"WaitToStart"]
65                orderValue: [history objectForKey: @"OrderValue"]];
66   
67    if (self)
68    {
69        NSString * downloadFolder;
70        if (!(downloadFolder = [history objectForKey: @"DownloadFolder"]))
71            downloadFolder = [[fDefaults stringForKey: @"DownloadFolder"] stringByExpandingTildeInPath];
72        [self setDownloadFolder: downloadFolder];
73
74        NSString * paused;
75        if (!(paused = [history objectForKey: @"Paused"]) || [paused isEqualToString: @"NO"])
76            tr_torrentStart(fHandle);
77    }
78    return self;
79}
80
81- (NSDictionary *) history
82{
83    NSMutableDictionary * history = [NSMutableDictionary dictionaryWithObjectsAndKeys:
84                    [NSNumber numberWithBool: fPrivateTorrent], @"PrivateCopy",
85                    [NSNumber numberWithBool: fPublicTorrent], @"PublicCopy",
86                    [self downloadFolder], @"DownloadFolder",
87                    [self isActive] ? @"NO" : @"YES", @"Paused",
88                    [self date], @"Date",
89                    [NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
90                    [NSNumber numberWithFloat: fRatioLimit], @"RatioLimit",
91                    [NSNumber numberWithBool: fWaitToStart], @"WaitToStart",
92                    [self orderValue], @"OrderValue", nil];
93           
94    if (fPrivateTorrent)
95        [history setObject: [self hashString] forKey: @"TorrentHash"];
96
97    if (fPublicTorrent)
98        [history setObject: [self publicTorrentLocation] forKey: @"TorrentPath"];
99   
100    return history;
101}
102
103- (void) dealloc
104{
105    if (fHandle)
106    {
107        tr_torrentClose(fLib, fHandle);
108       
109        if (fPublicTorrentLocation)
110            [fPublicTorrentLocation release];
111       
112        [fDate release];
113       
114        [fIcon release];
115        [fIconFlipped release];
116        [fIconSmall release];
117       
118        [fProgressString release];
119        [fStatusString release];
120        [fShortStatusString release];
121        [fRemainingTimeString release];
122    }
123    [super dealloc];
124}
125
126- (void) setDownloadFolder: (NSString *) path
127{
128    tr_torrentSetFolder(fHandle, [path UTF8String]);
129}
130
131- (NSString *) downloadFolder
132{
133    return [NSString stringWithUTF8String: tr_torrentGetFolder(fHandle)];
134}
135
136- (void) getAvailability: (int8_t *) tab size: (int) size
137{
138    tr_torrentAvailability(fHandle, tab, size);
139}
140
141- (void) update
142{
143    fStat = tr_torrentStat(fHandle);
144   
145    //notification when downloading finished
146    if ([self justFinished])
147        [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentFinishedDownloading" object: self];
148   
149    //check to stop for ratio
150    if ([self isSeeding] && ((fStopRatioSetting == RATIO_CHECK && [self ratio] >= fRatioLimit)
151            || (fStopRatioSetting == RATIO_GLOBAL && [fDefaults boolForKey: @"RatioCheck"]
152            && [self ratio] >= [fDefaults floatForKey: @"RatioLimit"])))
153    {
154        [self stopTransfer];
155        [self setStopRatioSetting: RATIO_NO_CHECK];
156        fFinishedSeeding = YES;
157       
158        fStat = tr_torrentStat(fHandle);
159       
160        [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentStoppedForRatio" object: self];
161    }
162
163    [fProgressString setString: @""];
164    if ([self progress] < 1.0)
165        [fProgressString appendFormat: @"%@ of %@ (%.2f%%)", [NSString stringForFileSize:
166                [self downloadedValid]], [NSString stringForFileSize: [self size]], 100.0 * [self progress]];
167    else
168        [fProgressString appendFormat: @"%@, uploaded %@ (Ratio: %@)", [NSString stringForFileSize:
169                [self size]], [NSString stringForFileSize: [self uploadedTotal]],
170                [NSString stringForRatioWithDownload: [self downloadedTotal] upload: [self uploadedTotal]]];
171
172    switch (fStat->status)
173    {
174        NSString * tempString;
175   
176        case TR_STATUS_PAUSE:
177            if (fFinishedSeeding)
178                tempString = @"Seeding complete";
179            else if (fWaitToStart && [[fDefaults stringForKey: @"StartSetting"] isEqualToString: @"Wait"])
180                tempString = [@"Waiting to start" stringByAppendingEllipsis];
181            else
182                tempString = @"Paused";
183           
184            [fStatusString setString: tempString];
185            [fShortStatusString setString: tempString];
186           
187            break;
188
189        case TR_STATUS_CHECK:
190            tempString = [@"Checking existing files" stringByAppendingEllipsis];
191           
192            [fStatusString setString: tempString];
193            [fShortStatusString setString: tempString];
194            [fRemainingTimeString setString: tempString];
195           
196            break;
197
198        case TR_STATUS_DOWNLOAD:
199            [fStatusString setString: @""];
200            [fStatusString appendFormat:
201                @"Downloading from %d of %d peer%s", [self peersUploading], [self totalPeers],
202                [self totalPeers] == 1 ? "" : "s"];
203           
204            [fRemainingTimeString setString: @""];
205            int eta = [self eta];
206            if (eta < 0)
207            {
208                [fRemainingTimeString setString: @"Unknown"];
209                [fProgressString appendString: @" - remaining time unknown"];
210            }
211            else
212            {
213                if (eta < 60)
214                    [fRemainingTimeString appendFormat: @"%d sec", eta];
215                else if (eta < 3600) //60 * 60
216                    [fRemainingTimeString appendFormat: @"%d min %02d sec", eta / 60, eta % 60];
217                else if (eta < 86400) //24 * 60 * 60
218                    [fRemainingTimeString appendFormat: @"%d hr %02d min", eta / 3600, (eta / 60) % 60];
219                else
220                    [fRemainingTimeString appendFormat: @"%d day%s %d hr",
221                                                eta / 86400, eta / 86400 == 1 ? "" : "s", (eta / 3600) % 24];
222               
223                [fProgressString appendFormat: @" - %@ remaining", fRemainingTimeString];
224            }
225           
226            break;
227
228        case TR_STATUS_SEED:
229            [fStatusString setString: @""];
230            [fStatusString appendFormat:
231                @"Seeding to %d of %d peer%s",
232                [self peersDownloading], [self totalPeers], [self totalPeers] == 1 ? "" : "s"];
233           
234            break;
235
236        case TR_STATUS_STOPPING:
237            tempString = [@"Stopping" stringByAppendingEllipsis];
238       
239            [fStatusString setString: tempString];
240            [fShortStatusString setString: tempString];
241           
242            break;
243    }
244   
245    if( fStat->error & TR_ETRACKER )
246        [fStatusString setString: [@"Error: " stringByAppendingString:
247                        [NSString stringWithUTF8String: fStat->trackerError]]];
248
249    if ([self isActive])
250    {
251        NSString * stringToAppend = @"";
252        if ([self progress] < 1.0)
253        {
254            stringToAppend = [NSString stringWithFormat: @"DL: %@, ", [NSString stringForSpeed: [self downloadRate]]];
255            [fShortStatusString setString: @""];
256        }
257        else
258        {
259            NSString * ratioString = [NSString stringForRatioWithDownload: [self downloadedTotal]
260                                                upload: [self uploadedTotal]];
261       
262            [fShortStatusString setString: [NSString stringWithFormat: @"Ratio: %@, ", ratioString]];
263            [fRemainingTimeString setString: [@"Ratio: " stringByAppendingString: ratioString]];
264        }
265       
266        stringToAppend = [stringToAppend stringByAppendingString: [@"UL: " stringByAppendingString:
267                                                [NSString stringForSpeed: [self uploadRate]]]];
268
269        [fStatusString appendFormat: @" - %@", stringToAppend];
270        [fShortStatusString appendString: stringToAppend];
271    }
272}
273
274- (NSDictionary *) infoForCurrentView
275{
276    NSMutableDictionary * info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
277                                    [self name], @"Name",
278                                    [NSNumber numberWithBool: [self isSeeding]], @"Seeding",
279                                    [NSNumber numberWithFloat: [self progress]], @"Progress",
280                                    [NSNumber numberWithBool: [self isActive]], @"Active",
281                                    [NSNumber numberWithBool: [self isError]], @"Error", nil];
282   
283    if (![fDefaults boolForKey: @"SmallView"])
284    {
285        [info setObject: fIconFlipped forKey: @"Icon"];
286        [info setObject: [self progressString] forKey: @"ProgressString"];
287        [info setObject: [self statusString] forKey: @"StatusString"];
288    }
289    else
290    {
291        [info setObject: fIconSmall forKey: @"Icon"];
292        [info setObject: [self remainingTimeString] forKey: @"RemainingTimeString"];
293        [info setObject: [self shortStatusString] forKey: @"ShortStatusString"];
294    }
295   
296    return info;
297}
298
299- (void) startTransfer
300{
301    if (![self isActive])
302    {
303        tr_torrentStart(fHandle);
304
305        fFinishedSeeding = NO;
306        fWaitToStart = NO;
307       
308        [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentSettingChange" object: self];
309    }
310}
311
312- (void) stopTransfer
313{
314    if ([self isActive])
315    {
316        BOOL wasSeeding = [self isSeeding];
317   
318        tr_torrentStop(fHandle);
319
320        if (!wasSeeding)
321            [[NSNotificationCenter defaultCenter] postNotificationName: @"StoppedDownloading" object: self];
322    }
323}
324
325- (void) stopTransferForQuit
326{
327    if ([self isActive])
328        tr_torrentStop(fHandle);
329}
330
331- (void) removeForever
332{
333    if (fPrivateTorrent)
334        tr_torrentRemoveSaved(fHandle);
335}
336
337- (void) sleep
338{
339    if ((fResumeOnWake = [self isActive]))
340        tr_torrentStop(fHandle);
341}
342
343- (void) wakeUp
344{
345    if (fResumeOnWake)
346        tr_torrentStart(fHandle);
347}
348
349- (float) ratio
350{
351    float downloaded = [self downloadedTotal];
352    return downloaded > 0 ? (float)[self uploadedTotal] / downloaded : -1;
353}
354
355- (int) stopRatioSetting
356{
357        return fStopRatioSetting;
358}
359
360- (void) setStopRatioSetting: (int) setting
361{
362    fStopRatioSetting = setting;
363}
364
365- (float) ratioLimit
366{
367    return fRatioLimit;
368}
369
370- (void) setRatioLimit: (float) limit
371{
372    if (limit >= 0)
373        fRatioLimit = limit;
374}
375
376- (void) setWaitToStart: (BOOL) wait
377{
378    fWaitToStart = wait;
379}
380
381- (BOOL) waitingToStart
382{
383    return fWaitToStart;
384}
385
386- (void) revealData
387{
388    [[NSWorkspace sharedWorkspace] selectFile: [self dataLocation] inFileViewerRootedAtPath: nil];
389}
390
391- (void) trashData
392{
393    [self trashFile: [self dataLocation]];
394}
395
396- (void) trashTorrent
397{
398    if (fPublicTorrent)
399        [self trashFile: [self publicTorrentLocation]];
400}
401
402- (NSImage *) icon
403{
404    return fIcon;
405}
406
407- (NSImage *) iconFlipped
408{
409    return fIconFlipped;
410}
411
412- (NSImage *) iconSmall
413{
414    return fIconSmall;
415}
416
417- (NSString *) name
418{
419    return [NSString stringWithUTF8String: fInfo->name];
420}
421
422- (uint64_t) size
423{
424    return fInfo->totalSize;
425}
426
427- (NSString *) tracker
428{
429    return [NSString stringWithFormat: @"%s:%d", fInfo->trackerAddress, fInfo->trackerPort];
430}
431
432- (NSString *) announce
433{
434    return [NSString stringWithUTF8String: fInfo->trackerAnnounce];
435}
436
437- (int) pieceSize
438{
439    return fInfo->pieceSize;
440}
441
442- (int) pieceCount
443{
444    return fInfo->pieceCount;
445}
446
447- (NSString *) hashString
448{
449    return [NSString stringWithUTF8String: fInfo->hashString];
450}
451
452- (NSString *) torrentLocation
453{
454    return [NSString stringWithUTF8String: fInfo->torrent];
455}
456
457- (NSString *) publicTorrentLocation
458{
459    return fPublicTorrentLocation;
460}
461
462- (NSString *) torrentLocationString
463{
464    return fPrivateTorrent ? @"Transmission Support Folder" : [fPublicTorrentLocation stringByAbbreviatingWithTildeInPath];
465}
466
467- (NSString *) dataLocation
468{
469    return [[self downloadFolder] stringByAppendingPathComponent: [self name]];
470}
471
472- (BOOL) publicTorrent
473{
474    return fPublicTorrent;
475}
476
477- (BOOL) privateTorrent
478{
479    return fPrivateTorrent;
480}
481
482- (NSString *) stateString
483{
484    switch( fStat->status )
485    {
486        case TR_STATUS_PAUSE:
487            return @"Paused";
488            break;
489
490        case TR_STATUS_CHECK:
491            return [@"Checking existing files" stringByAppendingEllipsis];
492            break;
493
494        case TR_STATUS_DOWNLOAD:
495            return @"Downloading";
496            break;
497
498        case TR_STATUS_SEED:
499            return @"Seeding";
500            break;
501
502        case TR_STATUS_STOPPING:
503            return [@"Stopping" stringByAppendingEllipsis];
504            break;
505       
506        default:
507            return @"N/A";
508    }
509}
510
511- (float) progress
512{
513    return fStat->progress;
514}
515
516- (int) eta
517{
518    return fStat->eta;
519}
520
521- (BOOL) isActive
522{
523    return fStat->status & TR_STATUS_ACTIVE;
524}
525
526- (BOOL) isSeeding
527{
528    return fStat->status == TR_STATUS_SEED;
529}
530
531- (BOOL) isPaused
532{
533    return fStat->status == TR_STATUS_PAUSE;
534}
535
536- (BOOL) isError
537{
538    return fStat->error & TR_ETRACKER;
539}
540
541- (BOOL) justFinished
542{
543    return tr_getFinished(fHandle);
544}
545
546- (NSArray *) peers
547{
548    int totalPeers, i;
549    tr_peer_stat_t * peers = tr_torrentPeers(fHandle, & totalPeers);
550   
551    NSMutableArray * peerDics = [NSMutableArray arrayWithCapacity: totalPeers];
552    tr_peer_stat_t peer;
553    NSString * client;
554    for (i = 0; i < totalPeers; i++)
555    {
556        peer = peers[i];
557        [peerDics addObject: [NSDictionary dictionaryWithObjectsAndKeys:
558            [NSNumber numberWithBool: peer.isConnected], @"Connected",
559            [NSString stringWithCString: (char *) peer.addr encoding: NSUTF8StringEncoding], @"IP",
560            [NSString stringWithCString: (char *) peer.client encoding: NSUTF8StringEncoding], @"Client",
561            [NSNumber numberWithBool: peer.isDownloading], @"UL To",
562            [NSNumber numberWithBool: peer.isUploading], @"DL From", nil]];
563    }
564   
565    tr_torrentPeersFree(peers, totalPeers);
566   
567    return peerDics;
568}
569
570- (NSString *) progressString
571{
572    return fProgressString;
573}
574
575- (NSString *) statusString
576{
577    return fStatusString;
578}
579
580- (NSString *) shortStatusString
581{
582    return fShortStatusString;
583}
584
585- (NSString *) remainingTimeString
586{
587    return fRemainingTimeString;
588}
589
590- (int) seeders
591{
592    return fStat->seeders;
593}
594
595- (int) leechers
596{
597    return fStat->leechers;
598}
599
600- (int) totalPeers
601{
602    return fStat->peersTotal;
603}
604
605//peers uploading to you
606- (int) peersUploading
607{
608    return fStat->peersUploading;
609}
610
611//peers downloading from you
612- (int) peersDownloading
613{
614    return fStat->peersDownloading;
615}
616
617- (float) downloadRate
618{
619    return fStat->rateDownload;
620}
621
622- (float) uploadRate
623{
624    return fStat->rateUpload;
625}
626
627- (float) downloadedValid
628{
629    return [self progress] * [self size];
630}
631
632- (uint64_t) downloadedTotal
633{
634    return fStat->downloaded;
635}
636
637- (uint64_t) uploadedTotal
638{
639    return fStat->uploaded;
640}
641
642- (float) swarmSpeed
643{
644    return fStat->swarmspeed;
645}
646
647- (NSNumber *) orderValue
648{
649    return [NSNumber numberWithInt: fOrderValue];
650}
651
652- (void) setOrderValue: (int) orderValue
653{
654    fOrderValue = orderValue;
655}
656
657- (NSArray *) fileList
658{
659    int count = fInfo->fileCount, i;
660    tr_file_t file;
661    NSMutableArray * files = [NSMutableArray arrayWithCapacity: count];
662   
663    for (i = 0; i < count; i++)
664    {
665        file = fInfo->files[i];
666        [files addObject: [NSDictionary dictionaryWithObjectsAndKeys:
667            [[self downloadFolder] stringByAppendingPathComponent: [NSString stringWithUTF8String: file.name]], @"Name",
668            [NSNumber numberWithUnsignedLongLong: file.length], @"Size", nil]];
669    }
670   
671    return files;
672}
673
674- (NSDate *) date
675{
676    return fDate;
677}
678
679- (NSNumber *) stateSortKey
680{
681    if (![self isActive])
682        return [NSNumber numberWithInt: 0];
683    else if ([self isSeeding])
684        return [NSNumber numberWithInt: 1];
685    else
686        return [NSNumber numberWithInt: 2];
687}
688
689- (NSNumber *) progressSortKey
690{
691    //if finished downloading sort by ratio instead of progress
692    float progress = [self progress];
693    return [NSNumber numberWithFloat: progress < 1.0 ? progress : 2.0 + [self ratio]];
694}
695
696@end
697
698
699@implementation Torrent (Private)
700
701//if a hash is given, attempt to load that; otherwise, attempt to open file at path
702- (id) initWithHash: (NSString *) hashString path: (NSString *) path lib: (tr_handle_t *) lib
703        privateTorrent: (NSNumber *) privateTorrent publicTorrent: (NSNumber *) publicTorrent
704        date: (NSDate *) date stopRatioSetting: (NSNumber *) stopRatioSetting
705        ratioLimit: (NSNumber *) ratioLimit waitToStart: (NSNumber *) waitToStart
706        orderValue: (NSNumber *) orderValue
707{
708    if (!(self = [super init]))
709        return nil;
710
711    fLib = lib;
712    fDefaults = [NSUserDefaults standardUserDefaults];
713
714    fPrivateTorrent = privateTorrent ? [privateTorrent boolValue] : [fDefaults boolForKey: @"SavePrivateTorrent"];
715    fPublicTorrent = !fPrivateTorrent || (publicTorrent ? [publicTorrent boolValue]
716                                            : ![fDefaults boolForKey: @"DeleteOriginalTorrent"]);
717
718    int error;
719    if (fPrivateTorrent && hashString)
720        fHandle = tr_torrentInitSaved(fLib, [hashString UTF8String], TR_FSAVEPRIVATE, & error);
721   
722    if (!fHandle && path)
723        fHandle = tr_torrentInit(fLib, [path UTF8String], fPrivateTorrent ? TR_FSAVEPRIVATE : 0, & error);
724
725    if (!fHandle)
726    {
727        [self release];
728        return nil;
729    }
730   
731    fInfo = tr_torrentInfo( fHandle );
732
733    if (fPublicTorrent)
734        fPublicTorrentLocation = [path retain];
735
736    fDate = date ? [date retain] : [[NSDate alloc] init];
737   
738    fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
739    fRatioLimit = ratioLimit ? [ratioLimit floatValue] : [fDefaults floatForKey: @"RatioLimit"];
740    fFinishedSeeding = NO;
741   
742    fWaitToStart = waitToStart ? [waitToStart boolValue]
743                    : ![[fDefaults stringForKey: @"StartSetting"] isEqualToString: @"Manual"];
744    fOrderValue = orderValue ? [orderValue intValue] : tr_torrentCount(fLib) - 1;
745   
746    NSString * fileType = fInfo->multifile ? NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
747    fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
748    [fIcon retain];
749   
750    fIconFlipped = [fIcon copy];
751    [fIconFlipped setFlipped: YES];
752   
753    fIconSmall = [fIconFlipped copy];
754    [fIconSmall setScalesWhenResized: YES];
755    [fIconSmall setSize: NSMakeSize(16.0, 16.0)];
756
757    fProgressString = [[NSMutableString alloc] initWithCapacity: 50];
758    fStatusString = [[NSMutableString alloc] initWithCapacity: 75];
759    fShortStatusString = [[NSMutableString alloc] initWithCapacity: 30];
760    fRemainingTimeString = [[NSMutableString alloc] initWithCapacity: 30];
761
762    [self update];
763    return self;
764}
765
766- (void) trashFile: (NSString *) path
767{
768    //attempt to move to trash
769    if (![[NSWorkspace sharedWorkspace] performFileOperation: NSWorkspaceRecycleOperation
770            source: [path stringByDeletingLastPathComponent] destination: @""
771            files: [NSArray arrayWithObject: [path lastPathComponent]] tag: nil])
772    {
773        //if cannot trash, just delete it (will work if it is on a remote volume)
774        if (![[NSFileManager defaultManager] removeFileAtPath: path handler: nil])
775            NSLog([@"Could not trash " stringByAppendingString: path]);
776    }
777}
778
779@end
Note: See TracBrowser for help on using the repository browser.