source: trunk/macosx/Torrent.m @ 925

Last change on this file since 925 was 925, checked in by livings124, 15 years ago

The advance bar should have the same default number of pieces as the pieces view.

  • Property svn:keywords set to Date Rev Author Id
File size: 24.1 KB
Line 
1/******************************************************************************
2 * $Id: Torrent.m 925 2006-09-25 21:24:25Z 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#define BAR_HEIGHT 12.0
29
30@interface Torrent (Private)
31
32- (id) initWithHash: (NSString *) hashString path: (NSString *) path lib: (tr_handle_t *) lib
33        privateTorrent: (NSNumber *) privateTorrent publicTorrent: (NSNumber *) publicTorrent
34        date: (NSDate *) date stopRatioSetting: (NSNumber *) stopRatioSetting
35        ratioLimit: (NSNumber *) ratioLimit waitToStart: (NSNumber *) waitToStart
36        orderValue: (NSNumber *) orderValue;
37
38- (NSImage *) advancedBar;
39
40- (void) trashFile: (NSString *) path;
41
42@end
43
44@implementation Torrent
45
46// Used to optimize drawing. They contain packed RGBA pixels for every color needed.
47#define BE OSSwapBigToHostConstInt32
48
49static uint32_t kRed   = BE(0xFF6450FF), //255, 100, 80
50                kBlue1 = BE(0xA0DCFFFF), //160, 220, 255
51                kBlue2 = BE(0x78BEFFFF), //120, 190, 255
52                kBlue3 = BE(0x50A0FFFF), //80, 160, 255
53                kBlue4 = BE(0x1E46B4FF), //30, 70, 180
54                kGray  = BE(0x969696FF), //150, 150, 150
55                kGreen = BE(0x00FF00FF), //0, 255, 0
56                kWhite = BE(0xFFFFFFFF); //255, 255, 255
57
58- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
59{
60    self = [self initWithHash: nil path: path lib: lib privateTorrent: nil publicTorrent: nil
61            date: nil stopRatioSetting: nil ratioLimit: nil waitToStart: nil orderValue: nil];
62   
63    if (self)
64    {
65        if (!fPublicTorrent)
66            [self trashFile: path];
67    }
68    return self;
69}
70
71- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
72{
73    self = [self initWithHash: [history objectForKey: @"TorrentHash"]
74                path: [history objectForKey: @"TorrentPath"] lib: lib
75                privateTorrent: [history objectForKey: @"PrivateCopy"]
76                publicTorrent: [history objectForKey: @"PublicCopy"]
77                date: [history objectForKey: @"Date"]
78                stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
79                ratioLimit: [history objectForKey: @"RatioLimit"]
80                waitToStart: [history objectForKey: @"WaitToStart"]
81                orderValue: [history objectForKey: @"OrderValue"]];
82   
83    if (self)
84    {
85        NSString * downloadFolder;
86        if (!(downloadFolder = [history objectForKey: @"DownloadFolder"]))
87            downloadFolder = [[fDefaults stringForKey: @"DownloadFolder"] stringByExpandingTildeInPath];
88        [self setDownloadFolder: downloadFolder];
89
90        NSString * paused;
91        if (!(paused = [history objectForKey: @"Paused"]) || [paused isEqualToString: @"NO"])
92            tr_torrentStart(fHandle);
93    }
94    return self;
95}
96
97- (NSDictionary *) history
98{
99    NSMutableDictionary * history = [NSMutableDictionary dictionaryWithObjectsAndKeys:
100                    [NSNumber numberWithBool: fPrivateTorrent], @"PrivateCopy",
101                    [NSNumber numberWithBool: fPublicTorrent], @"PublicCopy",
102                    [self downloadFolder], @"DownloadFolder",
103                    [self isActive] ? @"NO" : @"YES", @"Paused",
104                    [self date], @"Date",
105                    [NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
106                    [NSNumber numberWithFloat: fRatioLimit], @"RatioLimit",
107                    [NSNumber numberWithBool: fWaitToStart], @"WaitToStart",
108                    [self orderValue], @"OrderValue", nil];
109           
110    if (fPrivateTorrent)
111        [history setObject: [self hashString] forKey: @"TorrentHash"];
112
113    if (fPublicTorrent)
114        [history setObject: [self publicTorrentLocation] forKey: @"TorrentPath"];
115   
116    return history;
117}
118
119- (void) dealloc
120{
121    if (fHandle)
122    {
123        tr_torrentClose(fLib, fHandle);
124       
125        if (fPublicTorrentLocation)
126            [fPublicTorrentLocation release];
127       
128        [fDate release];
129       
130        [fIcon release];
131        [fIconFlipped release];
132        [fIconSmall release];
133       
134        [fProgressString release];
135        [fStatusString release];
136        [fShortStatusString release];
137        [fRemainingTimeString release];
138    }
139    [super dealloc];
140}
141
142- (void) setDownloadFolder: (NSString *) path
143{
144    tr_torrentSetFolder(fHandle, [path UTF8String]);
145}
146
147- (NSString *) downloadFolder
148{
149    return [NSString stringWithUTF8String: tr_torrentGetFolder(fHandle)];
150}
151
152- (void) getAvailability: (int8_t *) tab size: (int) size
153{
154    tr_torrentAvailability(fHandle, tab, size);
155}
156
157- (void) update
158{
159    fStat = tr_torrentStat(fHandle);
160   
161    //notification when downloading finished
162    if ([self justFinished])
163        [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentFinishedDownloading" object: self];
164   
165    //check to stop for ratio
166    if ([self isSeeding] && ((fStopRatioSetting == RATIO_CHECK && [self ratio] >= fRatioLimit)
167            || (fStopRatioSetting == RATIO_GLOBAL && [fDefaults boolForKey: @"RatioCheck"]
168            && [self ratio] >= [fDefaults floatForKey: @"RatioLimit"])))
169    {
170        [self stopTransfer];
171        [self setStopRatioSetting: RATIO_NO_CHECK];
172        fFinishedSeeding = YES;
173       
174        fStat = tr_torrentStat(fHandle);
175       
176        [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentStoppedForRatio" object: self];
177    }
178
179    [fProgressString setString: @""];
180    if ([self progress] < 1.0)
181        [fProgressString appendFormat: @"%@ of %@ (%.2f%%)", [NSString stringForFileSize:
182                [self downloadedValid]], [NSString stringForFileSize: [self size]], 100.0 * [self progress]];
183    else
184        [fProgressString appendFormat: @"%@, uploaded %@ (Ratio: %@)", [NSString stringForFileSize:
185                [self size]], [NSString stringForFileSize: [self uploadedTotal]],
186                [NSString stringForRatioWithDownload: [self downloadedTotal] upload: [self uploadedTotal]]];
187
188    switch (fStat->status)
189    {
190        NSString * tempString;
191   
192        case TR_STATUS_PAUSE:
193            if (fFinishedSeeding)
194                tempString = @"Seeding complete";
195            else if (fWaitToStart)
196                tempString = [@"Waiting to start" stringByAppendingEllipsis];
197            else
198                tempString = @"Paused";
199           
200            [fStatusString setString: tempString];
201            [fShortStatusString setString: tempString];
202           
203            break;
204
205        case TR_STATUS_CHECK:
206            tempString = [@"Checking existing files" stringByAppendingEllipsis];
207           
208            [fStatusString setString: tempString];
209            [fShortStatusString setString: tempString];
210            [fRemainingTimeString setString: tempString];
211           
212            break;
213
214        case TR_STATUS_DOWNLOAD:
215            [fStatusString setString: @""];
216            [fStatusString appendFormat:
217                @"Downloading from %d of %d peer%s", [self peersUploading], [self totalPeers],
218                [self totalPeers] == 1 ? "" : "s"];
219           
220            [fRemainingTimeString setString: @""];
221            int eta = [self eta];
222            if (eta < 0)
223            {
224                [fRemainingTimeString setString: @"Unknown"];
225                [fProgressString appendString: @" - remaining time unknown"];
226            }
227            else
228            {
229                if (eta < 60)
230                    [fRemainingTimeString appendFormat: @"%d sec", eta];
231                else if (eta < 3600) //60 * 60
232                    [fRemainingTimeString appendFormat: @"%d min %02d sec", eta / 60, eta % 60];
233                else if (eta < 86400) //24 * 60 * 60
234                    [fRemainingTimeString appendFormat: @"%d hr %02d min", eta / 3600, (eta / 60) % 60];
235                else
236                    [fRemainingTimeString appendFormat: @"%d day%s %d hr",
237                                                eta / 86400, eta / 86400 == 1 ? "" : "s", (eta / 3600) % 24];
238               
239                [fProgressString appendFormat: @" - %@ remaining", fRemainingTimeString];
240            }
241           
242            break;
243
244        case TR_STATUS_SEED:
245            [fStatusString setString: @""];
246            [fStatusString appendFormat:
247                @"Seeding to %d of %d peer%s",
248                [self peersDownloading], [self totalPeers], [self totalPeers] == 1 ? "" : "s"];
249           
250            break;
251
252        case TR_STATUS_STOPPING:
253            tempString = [@"Stopping" stringByAppendingEllipsis];
254       
255            [fStatusString setString: tempString];
256            [fShortStatusString setString: tempString];
257           
258            break;
259    }
260   
261    if( fStat->error & TR_ETRACKER )
262        [fStatusString setString: [@"Error: " stringByAppendingString:
263                        [NSString stringWithUTF8String: fStat->trackerError]]];
264
265    if ([self isActive])
266    {
267        NSString * stringToAppend = @"";
268        if ([self progress] < 1.0)
269        {
270            stringToAppend = [NSString stringWithFormat: @"DL: %@, ", [NSString stringForSpeed: [self downloadRate]]];
271            [fShortStatusString setString: @""];
272        }
273        else
274        {
275            NSString * ratioString = [NSString stringForRatioWithDownload: [self downloadedTotal]
276                                                upload: [self uploadedTotal]];
277       
278            [fShortStatusString setString: [NSString stringWithFormat: @"Ratio: %@, ", ratioString]];
279            [fRemainingTimeString setString: [@"Ratio: " stringByAppendingString: ratioString]];
280        }
281       
282        stringToAppend = [stringToAppend stringByAppendingString: [@"UL: " stringByAppendingString:
283                                                [NSString stringForSpeed: [self uploadRate]]]];
284
285        [fStatusString appendFormat: @" - %@", stringToAppend];
286        [fShortStatusString appendString: stringToAppend];
287    }
288}
289
290- (NSDictionary *) infoForCurrentView
291{
292    NSMutableDictionary * info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
293                                    [self name], @"Name",
294                                    [NSNumber numberWithBool: [self isSeeding]], @"Seeding",
295                                    [NSNumber numberWithFloat: [self progress]], @"Progress",
296                                    [NSNumber numberWithBool: [self isActive]], @"Active",
297                                    [NSNumber numberWithBool: [self isError]], @"Error", nil];
298   
299    if (![fDefaults boolForKey: @"SmallView"])
300    {
301        [info setObject: fIconFlipped forKey: @"Icon"];
302        [info setObject: [self progressString] forKey: @"ProgressString"];
303        [info setObject: [self statusString] forKey: @"StatusString"];
304    }
305    else
306    {
307        [info setObject: fIconSmall forKey: @"Icon"];
308        [info setObject: [self remainingTimeString] forKey: @"RemainingTimeString"];
309        [info setObject: [self shortStatusString] forKey: @"ShortStatusString"];
310    }
311   
312    if ([fDefaults boolForKey: @"UseAdvancedBar"])
313        [info setObject: [self advancedBar] forKey: @"AdvancedBar"];
314   
315    return info;
316}
317
318- (void) startTransfer
319{
320    if (![self isActive])
321    {
322        tr_torrentStart(fHandle);
323
324        fFinishedSeeding = NO;
325        fWaitToStart = NO;
326    }
327}
328
329- (void) stopTransfer
330{
331    if ([self isActive])
332    {
333        BOOL wasSeeding = [self isSeeding];
334   
335        tr_torrentStop(fHandle);
336
337        if (!wasSeeding)
338            [[NSNotificationCenter defaultCenter] postNotificationName: @"StoppedDownloading" object: self];
339    }
340}
341
342- (void) stopTransferForQuit
343{
344    if ([self isActive])
345        tr_torrentStop(fHandle);
346}
347
348- (void) removeForever
349{
350    if (fPrivateTorrent)
351        tr_torrentRemoveSaved(fHandle);
352}
353
354- (void) sleep
355{
356    if ((fResumeOnWake = [self isActive]))
357        tr_torrentStop(fHandle);
358}
359
360- (void) wakeUp
361{
362    if (fResumeOnWake)
363        tr_torrentStart(fHandle);
364}
365
366- (float) ratio
367{
368    float downloaded = [self downloadedTotal];
369    return downloaded > 0 ? (float)[self uploadedTotal] / downloaded : -1;
370}
371
372- (int) stopRatioSetting
373{
374        return fStopRatioSetting;
375}
376
377- (void) setStopRatioSetting: (int) setting
378{
379    fStopRatioSetting = setting;
380}
381
382- (float) ratioLimit
383{
384    return fRatioLimit;
385}
386
387- (void) setRatioLimit: (float) limit
388{
389    if (limit >= 0)
390        fRatioLimit = limit;
391}
392
393- (void) setWaitToStart: (BOOL) wait
394{
395    fWaitToStart = wait;
396}
397
398- (BOOL) waitingToStart
399{
400    return fWaitToStart;
401}
402
403- (void) revealData
404{
405    [[NSWorkspace sharedWorkspace] selectFile: [self dataLocation] inFileViewerRootedAtPath: nil];
406}
407
408- (void) trashData
409{
410    [self trashFile: [self dataLocation]];
411}
412
413- (void) trashTorrent
414{
415    if (fPublicTorrent)
416        [self trashFile: [self publicTorrentLocation]];
417}
418
419- (NSImage *) icon
420{
421    return fIcon;
422}
423
424- (NSImage *) iconFlipped
425{
426    return fIconFlipped;
427}
428
429- (NSImage *) iconSmall
430{
431    return fIconSmall;
432}
433
434- (NSString *) name
435{
436    return [NSString stringWithUTF8String: fInfo->name];
437}
438
439- (uint64_t) size
440{
441    return fInfo->totalSize;
442}
443
444- (NSString *) tracker
445{
446    return [NSString stringWithFormat: @"%s:%d", fInfo->trackerAddress, fInfo->trackerPort];
447}
448
449- (NSString *) announce
450{
451    return [NSString stringWithUTF8String: fInfo->trackerAnnounce];
452}
453
454- (int) pieceSize
455{
456    return fInfo->pieceSize;
457}
458
459- (int) pieceCount
460{
461    return fInfo->pieceCount;
462}
463
464- (NSString *) hashString
465{
466    return [NSString stringWithUTF8String: fInfo->hashString];
467}
468
469- (NSString *) torrentLocation
470{
471    return [NSString stringWithUTF8String: fInfo->torrent];
472}
473
474- (NSString *) publicTorrentLocation
475{
476    return fPublicTorrentLocation;
477}
478
479- (NSString *) torrentLocationString
480{
481    return fPrivateTorrent ? @"Transmission Support Folder" : [fPublicTorrentLocation stringByAbbreviatingWithTildeInPath];
482}
483
484- (NSString *) dataLocation
485{
486    return [[self downloadFolder] stringByAppendingPathComponent: [self name]];
487}
488
489- (BOOL) publicTorrent
490{
491    return fPublicTorrent;
492}
493
494- (BOOL) privateTorrent
495{
496    return fPrivateTorrent;
497}
498
499- (NSString *) stateString
500{
501    switch( fStat->status )
502    {
503        case TR_STATUS_PAUSE:
504            return @"Paused";
505            break;
506
507        case TR_STATUS_CHECK:
508            return [@"Checking existing files" stringByAppendingEllipsis];
509            break;
510
511        case TR_STATUS_DOWNLOAD:
512            return @"Downloading";
513            break;
514
515        case TR_STATUS_SEED:
516            return @"Seeding";
517            break;
518
519        case TR_STATUS_STOPPING:
520            return [@"Stopping" stringByAppendingEllipsis];
521            break;
522       
523        default:
524            return @"N/A";
525    }
526}
527
528- (float) progress
529{
530    return fStat->progress;
531}
532
533- (int) eta
534{
535    return fStat->eta;
536}
537
538- (BOOL) isActive
539{
540    return fStat->status & TR_STATUS_ACTIVE;
541}
542
543- (BOOL) isSeeding
544{
545    return fStat->status == TR_STATUS_SEED;
546}
547
548- (BOOL) isPaused
549{
550    return fStat->status == TR_STATUS_PAUSE;
551}
552
553- (BOOL) isError
554{
555    return fStat->error & TR_ETRACKER;
556}
557
558- (BOOL) justFinished
559{
560    return tr_getFinished(fHandle);
561}
562
563- (NSArray *) peers
564{
565    int totalPeers, i;
566    tr_peer_stat_t * peers = tr_torrentPeers(fHandle, & totalPeers);
567   
568    NSMutableArray * peerDics = [NSMutableArray arrayWithCapacity: totalPeers];
569    tr_peer_stat_t peer;
570    NSString * client;
571    for (i = 0; i < totalPeers; i++)
572    {
573        peer = peers[i];
574        [peerDics addObject: [NSDictionary dictionaryWithObjectsAndKeys:
575            [NSNumber numberWithBool: peer.isConnected], @"Connected",
576            [NSString stringWithCString: (char *) peer.addr encoding: NSUTF8StringEncoding], @"IP",
577            [NSString stringWithCString: (char *) peer.client encoding: NSUTF8StringEncoding], @"Client",
578            [NSNumber numberWithBool: peer.isDownloading], @"UL To",
579            [NSNumber numberWithBool: peer.isUploading], @"DL From", nil]];
580    }
581   
582    tr_torrentPeersFree(peers, totalPeers);
583   
584    return peerDics;
585}
586
587- (NSString *) progressString
588{
589    return fProgressString;
590}
591
592- (NSString *) statusString
593{
594    return fStatusString;
595}
596
597- (NSString *) shortStatusString
598{
599    return fShortStatusString;
600}
601
602- (NSString *) remainingTimeString
603{
604    return fRemainingTimeString;
605}
606
607- (int) seeders
608{
609    return fStat->seeders;
610}
611
612- (int) leechers
613{
614    return fStat->leechers;
615}
616
617- (int) totalPeers
618{
619    return fStat->peersTotal;
620}
621
622//peers uploading to you
623- (int) peersUploading
624{
625    return fStat->peersUploading;
626}
627
628//peers downloading from you
629- (int) peersDownloading
630{
631    return fStat->peersDownloading;
632}
633
634- (float) downloadRate
635{
636    return fStat->rateDownload;
637}
638
639- (float) uploadRate
640{
641    return fStat->rateUpload;
642}
643
644- (float) downloadedValid
645{
646    return [self progress] * [self size];
647}
648
649- (uint64_t) downloadedTotal
650{
651    return fStat->downloaded;
652}
653
654- (uint64_t) uploadedTotal
655{
656    return fStat->uploaded;
657}
658
659- (float) swarmSpeed
660{
661    return fStat->swarmspeed;
662}
663
664- (NSNumber *) orderValue
665{
666    return [NSNumber numberWithInt: fOrderValue];
667}
668
669- (void) setOrderValue: (int) orderValue
670{
671    fOrderValue = orderValue;
672}
673
674- (NSArray *) fileList
675{
676    int count = fInfo->fileCount, i;
677    tr_file_t file;
678    NSMutableArray * files = [NSMutableArray arrayWithCapacity: count];
679   
680    for (i = 0; i < count; i++)
681    {
682        file = fInfo->files[i];
683        [files addObject: [NSDictionary dictionaryWithObjectsAndKeys:
684            [[self downloadFolder] stringByAppendingPathComponent: [NSString stringWithUTF8String: file.name]], @"Name",
685            [NSNumber numberWithUnsignedLongLong: file.length], @"Size", nil]];
686    }
687   
688    return files;
689}
690
691- (NSDate *) date
692{
693    return fDate;
694}
695
696- (NSNumber *) stateSortKey
697{
698    if (![self isActive])
699        return [NSNumber numberWithInt: 0];
700    else if ([self isSeeding])
701        return [NSNumber numberWithInt: 1];
702    else
703        return [NSNumber numberWithInt: 2];
704}
705
706- (NSNumber *) progressSortKey
707{
708    //if finished downloading sort by ratio instead of progress
709    float progress = [self progress];
710    return [NSNumber numberWithFloat: progress < 1.0 ? progress : 2.0 + [self ratio]];
711}
712
713@end
714
715
716@implementation Torrent (Private)
717
718//if a hash is given, attempt to load that; otherwise, attempt to open file at path
719- (id) initWithHash: (NSString *) hashString path: (NSString *) path lib: (tr_handle_t *) lib
720        privateTorrent: (NSNumber *) privateTorrent publicTorrent: (NSNumber *) publicTorrent
721        date: (NSDate *) date stopRatioSetting: (NSNumber *) stopRatioSetting
722        ratioLimit: (NSNumber *) ratioLimit waitToStart: (NSNumber *) waitToStart
723        orderValue: (NSNumber *) orderValue
724{
725    if (!(self = [super init]))
726        return nil;
727
728    fLib = lib;
729    fDefaults = [NSUserDefaults standardUserDefaults];
730
731    fPrivateTorrent = privateTorrent ? [privateTorrent boolValue] : [fDefaults boolForKey: @"SavePrivateTorrent"];
732    fPublicTorrent = !fPrivateTorrent || (publicTorrent ? [publicTorrent boolValue]
733                                            : ![fDefaults boolForKey: @"DeleteOriginalTorrent"]);
734
735    int error;
736    if (fPrivateTorrent && hashString)
737        fHandle = tr_torrentInitSaved(fLib, [hashString UTF8String], TR_FSAVEPRIVATE, & error);
738   
739    if (!fHandle && path)
740        fHandle = tr_torrentInit(fLib, [path UTF8String], fPrivateTorrent ? TR_FSAVEPRIVATE : 0, & error);
741
742    if (!fHandle)
743    {
744        [self release];
745        return nil;
746    }
747   
748    fInfo = tr_torrentInfo( fHandle );
749
750    if (fPublicTorrent)
751        fPublicTorrentLocation = [path retain];
752
753    fDate = date ? [date retain] : [[NSDate alloc] init];
754   
755    fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
756    fRatioLimit = ratioLimit ? [ratioLimit floatValue] : [fDefaults floatForKey: @"RatioLimit"];
757    fFinishedSeeding = NO;
758   
759    fWaitToStart = waitToStart ? [waitToStart boolValue] : [fDefaults boolForKey: @"StartAtOpen"];
760    fOrderValue = orderValue ? [orderValue intValue] : tr_torrentCount(fLib) - 1;
761   
762    NSString * fileType = fInfo->multifile ? NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
763    fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
764    [fIcon retain];
765   
766    fIconFlipped = [fIcon copy];
767    [fIconFlipped setFlipped: YES];
768   
769    fIconSmall = [fIconFlipped copy];
770    [fIconSmall setScalesWhenResized: YES];
771    [fIconSmall setSize: NSMakeSize(16.0, 16.0)];
772
773    fProgressString = [[NSMutableString alloc] initWithCapacity: 50];
774    fStatusString = [[NSMutableString alloc] initWithCapacity: 75];
775    fShortStatusString = [[NSMutableString alloc] initWithCapacity: 30];
776    fRemainingTimeString = [[NSMutableString alloc] initWithCapacity: 30];
777
778    [self update];
779    return self;
780}
781
782- (NSImage *) advancedBar
783{
784    int width = 324; //integers for bars
785   
786    NSBitmapImageRep * bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil
787        pixelsWide: width pixelsHigh: BAR_HEIGHT bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES
788        isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bytesPerRow: 0 bitsPerPixel: 0];
789
790    int h, w;
791    uint32_t * p;
792    uint8_t * bitmapData = [bitmap bitmapData];
793    int bytesPerRow = [bitmap bytesPerRow];
794
795    int8_t * pieces = malloc(width);
796    [self getAvailability: pieces size: width];
797    int avail = 0;
798    for (w = 0; w < width; w++)
799        if (pieces[w] != 0)
800            avail++;
801
802    //first two lines: dark blue to show progression, green to show available
803    int end = lrintf(floor([self progress] * width));
804    p = (uint32_t *) bitmapData;
805
806    for (w = 0; w < end; w++)
807    {
808        p[w] = kBlue4;
809        p[w + bytesPerRow / 4] = kBlue4;
810    }
811    for (; w < avail; w++)
812    {
813        p[w] = kGreen;
814        p[w + bytesPerRow / 4] = kGreen;
815    }
816    for (; w < width; w++)
817    {
818        p[w] = kWhite;
819        p[w + bytesPerRow / 4] = kWhite;
820    }
821   
822    //lines 2 to 14: blue or grey depending on whether we have the piece or not
823    uint32_t color;
824    for( w = 0; w < width; w++ )
825    {
826        if (pieces[w] < 0)
827            color = kGreen;
828        else if (pieces[w] == 0)
829            color = kGray;
830        else if (pieces[w] == 1)
831            color = kBlue1;
832        else if (pieces[w] == 2)
833            color = kBlue2;
834        else
835            color = kBlue3;
836       
837        //point to pixel (w, 2) and draw "vertically"
838        p = (uint32_t *) ( bitmapData + 2 * bytesPerRow ) + w;
839        for( h = 2; h < BAR_HEIGHT; h++ )
840        {
841            p[0] = color;
842            p = (uint32_t *) ( (uint8_t *) p + bytesPerRow );
843        }
844    }
845
846    free(pieces);
847   
848    //actually draw image
849    NSImage * bar = [[NSImage alloc] initWithSize: [bitmap size]];
850    [bar addRepresentation: bitmap];
851    [bitmap release];
852   
853    [bar setScalesWhenResized: YES];
854   
855    return [bar autorelease];
856}
857
858- (void) trashFile: (NSString *) path
859{
860    //attempt to move to trash
861    if (![[NSWorkspace sharedWorkspace] performFileOperation: NSWorkspaceRecycleOperation
862            source: [path stringByDeletingLastPathComponent] destination: @""
863            files: [NSArray arrayWithObject: [path lastPathComponent]] tag: nil])
864    {
865        //if cannot trash, just delete it (will work if it is on a remote volume)
866        if (![[NSFileManager defaultManager] removeFileAtPath: path handler: nil])
867            NSLog([@"Could not trash " stringByAppendingString: path]);
868    }
869}
870
871@end
Note: See TracBrowser for help on using the repository browser.