source: trunk/macosx/CreatorWindowController.m @ 13319

Last change on this file since 13319 was 13319, checked in by livings124, 9 years ago

#4921 On Lion, use window restoration on the torrent creation window

  • Property Id set to /Users/mitchell/Desktop/Transmission/macosx/ActionMenuRatioToDisplayRatioTransformer.h
  • Property svn:keywords set to Date Rev Author Id
File size: 26.1 KB
Line 
1/******************************************************************************
2 * $Id: CreatorWindowController.m 13319 2012-05-28 14:28:50Z livings124 $
3 *
4 * Copyright (c) 2007-2012 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 "CreatorWindowController.h"
26#import "Controller.h"
27#import "NSStringAdditions.h"
28
29#import "transmission.h" // required by utils.h
30#import "utils.h" // tr_urlIsValidTracker()
31
32#define TRACKER_ADD_TAG 0
33#define TRACKER_REMOVE_TAG 1
34
35@interface CreatorWindowController (Private)
36
37+ (NSURL *) chooseFile;
38
39- (void) createBlankAddressAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo;
40- (void) createReal;
41- (void) checkProgress;
42- (void) failureSheetClosed: (NSAlert *) alert returnCode: (NSInteger) code contextInfo: (void *) info;
43
44@end
45
46@implementation CreatorWindowController
47
48+ (CreatorWindowController *) createTorrentFile: (tr_session *) handle
49{
50    //get file/folder for torrent
51    NSURL * path;
52    if (!(path = [CreatorWindowController chooseFile]))
53        return nil;
54   
55    CreatorWindowController * creator = [[self alloc] initWithHandle: handle path: path];
56    [creator showWindow: nil];
57    return creator;
58}
59
60+ (CreatorWindowController *) createTorrentFile: (tr_session *) handle forFile: (NSURL *) file
61{
62    CreatorWindowController * creator = [[self alloc] initWithHandle: handle path: file];
63    [creator showWindow: nil];
64    return creator;
65}
66
67- (id) initWithHandle: (tr_session *) handle path: (NSURL *) path
68{
69    if ((self = [super initWithWindowNibName: @"Creator"]))
70    {
71        fStarted = NO;
72       
73        fPath = [path retain];
74        fInfo = tr_metaInfoBuilderCreate([[fPath path] UTF8String]);
75       
76        if (fInfo->fileCount == 0)
77        {
78            NSAlert * alert = [[NSAlert alloc] init];
79            [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> no files -> button")];
80            [alert setMessageText: NSLocalizedString(@"This folder contains no files.",
81                                                    "Create torrent -> no files -> title")];
82            [alert setInformativeText: NSLocalizedString(@"There must be at least one file in a folder to create a torrent file.",
83                                                        "Create torrent -> no files -> warning")];
84            [alert setAlertStyle: NSWarningAlertStyle];
85           
86            [alert runModal];
87            [alert release];
88           
89            [self release];
90            return nil;
91        }
92        if (fInfo->totalSize == 0)
93        {
94            NSAlert * alert = [[NSAlert alloc] init];
95            [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> zero size -> button")];
96            [alert setMessageText: NSLocalizedString(@"The total file size is zero bytes.",
97                                                    "Create torrent -> zero size -> title")];
98            [alert setInformativeText: NSLocalizedString(@"A torrent file cannot be created for files with no size.",
99                                                        "Create torrent -> zero size -> warning")];
100            [alert setAlertStyle: NSWarningAlertStyle];
101           
102            [alert runModal];
103            [alert release];
104           
105            [self release];
106            return nil;
107        }
108       
109        fDefaults = [NSUserDefaults standardUserDefaults];
110       
111        //get list of trackers
112        if (!(fTrackers = [[fDefaults arrayForKey: @"CreatorTrackers"] mutableCopy]))
113        {
114            fTrackers = [[NSMutableArray alloc] init];
115           
116            //check for single tracker from versions before 1.3
117            NSString * tracker;
118            if ((tracker = [fDefaults stringForKey: @"CreatorTracker"]))
119            {
120                [fDefaults removeObjectForKey: @"CreatorTracker"];
121                if (![tracker isEqualToString: @""])
122                {
123                    [fTrackers addObject: tracker];
124                    [fDefaults setObject: fTrackers forKey: @"CreatorTrackers"];
125                }
126            }
127        }
128       
129        //remove potentially invalid addresses
130        for (NSInteger i = [fTrackers count]-1; i >= 0; i--)
131        {
132            if (!tr_urlIsValidTracker([[fTrackers objectAtIndex: i] UTF8String]))
133                [fTrackers removeObjectAtIndex: i];
134        }
135    }
136    return self;
137}
138
139- (void) awakeFromNib
140{
141    [[self window] setRestorationClass: [self class]];
142   
143    NSString * name = [fPath lastPathComponent];
144   
145    [[self window] setTitle: name];
146   
147    [fNameField setStringValue: name];
148    [fNameField setToolTip: [fPath path]];
149   
150    const BOOL multifile = !fInfo->isSingleFile;
151   
152    NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFileType: multifile
153                        ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [fPath pathExtension]];
154    [icon setSize: [fIconView frame].size];
155    [fIconView setImage: icon];
156   
157    NSString * statusString = [NSString stringForFileSize: fInfo->totalSize];
158    if (multifile)
159    {
160        NSString * fileString;
161        NSInteger count = fInfo->fileCount;
162        if (count != 1)
163            fileString = [NSString stringWithFormat: NSLocalizedString(@"%@ files", "Create torrent -> info"),
164                            [NSString formattedUInteger: count]];
165        else
166            fileString = NSLocalizedString(@"1 file", "Create torrent -> info");
167        statusString = [NSString stringWithFormat: @"%@, %@", fileString, statusString];
168    }
169    [fStatusField setStringValue: statusString];
170   
171    if (fInfo->pieceCount == 1)
172        [fPiecesField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"1 piece, %@", "Create torrent -> info"),
173                                                            [NSString stringForFileSize: fInfo->pieceSize]]];
174    else
175        [fPiecesField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%d pieces, %@ each", "Create torrent -> info"),
176                                                            fInfo->pieceCount, [NSString stringForFileSize: fInfo->pieceSize]]];
177   
178    fLocation = [[[fDefaults URLForKey: @"CreatorLocationURL"] URLByAppendingPathComponent: [name stringByAppendingPathExtension: @"torrent"]] retain];
179    if (!fLocation)
180    {
181        //for 2.5 and earlier
182        #warning we still store "CreatorLocation" in Defaults.plist, and not "CreatorLocationURL"
183        NSString * location = [fDefaults stringForKey: @"CreatorLocation"];
184        fLocation = [[NSURL alloc] initFileURLWithPath: [[location stringByExpandingTildeInPath] stringByAppendingPathComponent: [name stringByAppendingPathExtension: @"torrent"]]];
185    }
186    NSString * pathString = [fLocation path];
187    [fLocationField setStringValue: [pathString stringByAbbreviatingWithTildeInPath]];
188    [fLocationField setToolTip: pathString];
189   
190    //set previously saved values
191    if ([fDefaults objectForKey: @"CreatorPrivate"])
192        [fPrivateCheck setState: [fDefaults boolForKey: @"CreatorPrivate"] ? NSOnState : NSOffState];
193   
194    [fOpenCheck setState: [fDefaults boolForKey: @"CreatorOpen"] ? NSOnState : NSOffState];
195}
196
197- (void) dealloc
198{
199    [fPath release];
200    [fLocation release];
201   
202    [fTrackers release];
203   
204    if (fInfo)
205        tr_metaInfoBuilderFree(fInfo);
206   
207    [fTimer invalidate];
208   
209    [super dealloc];
210}
211
212+ (void) restoreWindowWithIdentifier: (NSString *) identifier state: (NSCoder *) state completionHandler: (void (^)(NSWindow *, NSError *)) completionHandler
213{
214    NSURL * path = [state decodeObjectForKey: @"TRCreatorPath"];
215    if (!path || ![path checkResourceIsReachableAndReturnError: nil])
216    {
217        completionHandler(nil, [NSError errorWithDomain: NSURLErrorDomain code: NSURLErrorCannotOpenFile userInfo: nil]);
218        return;
219    }
220   
221    NSWindow * window = [[self createTorrentFile: [(Controller *)[NSApp delegate] sessionHandle] forFile: path] window];
222    completionHandler(window, nil);
223}
224
225- (void) window: (NSWindow *) window willEncodeRestorableState: (NSCoder *) state
226{
227    [state encodeObject: fPath forKey: @"TRCreatorPath"];
228    [state encodeObject: fLocation forKey: @"TRCreatorLocation"];
229    [state encodeObject: fTrackers forKey: @"TRCreatorTrackers"];
230    [state encodeInteger: [fOpenCheck state] forKey: @"TRCreatorOpenCheck"];
231    [state encodeInteger: [fPrivateCheck state] forKey: @"TRCreatorPrivateCheck"];
232    [state encodeObject: [fCommentView string] forKey: @"TRCreatorPrivateComment"];
233}
234
235- (void) window: (NSWindow *) window didDecodeRestorableState: (NSCoder *) coder
236{
237    #warning done in 3 places - make a separate method
238    [fLocation release];
239    fLocation = [[coder decodeObjectForKey: @"TRCreatorLocation"] retain];
240    NSString * pathString = [fLocation path];
241    [fLocationField setStringValue: [pathString stringByAbbreviatingWithTildeInPath]];
242    [fLocationField setToolTip: pathString];
243   
244    [fTrackers release];
245    fTrackers = [[coder decodeObjectForKey: @"TRCreatorTrackers"] retain];
246    [fTrackerTable reloadData];
247   
248    [fOpenCheck setState: [coder decodeIntegerForKey: @"TRCreatorOpenCheck"]];
249    [fPrivateCheck setState: [coder decodeIntegerForKey: @"TRCreatorPrivateCheck"]];
250    [fCommentView setString: [coder decodeObjectForKey: @"TRCreatorPrivateComment"]];
251}
252
253- (IBAction) setLocation: (id) sender
254{
255    NSSavePanel * panel = [NSSavePanel savePanel];
256
257    [panel setPrompt: NSLocalizedString(@"Select", "Create torrent -> location sheet -> button")];
258    [panel setMessage: NSLocalizedString(@"Select the name and location for the torrent file.",
259                                        "Create torrent -> location sheet -> message")];
260   
261    [panel setAllowedFileTypes: [NSArray arrayWithObjects: @"org.bittorrent.torrent", @"torrent", nil]];
262    [panel setCanSelectHiddenExtension: YES];
263   
264    [panel setDirectoryURL: [fLocation URLByDeletingLastPathComponent]];
265    [panel setNameFieldStringValue: [fLocation lastPathComponent]];
266   
267    [panel beginSheetModalForWindow: [self window] completionHandler: ^(NSInteger result) {
268        if (result == NSFileHandlingPanelOKButton)
269        {
270            [fLocation release];
271            fLocation = [[panel URL] retain];
272           
273            NSString * pathString = [fLocation path];
274            [fLocationField setStringValue: [pathString stringByAbbreviatingWithTildeInPath]];
275            [fLocationField setToolTip: pathString];
276        }
277    }];
278}
279
280- (IBAction) create: (id) sender
281{
282    //make sure the trackers are no longer being verified
283    if ([fTrackerTable editedRow] != -1)
284        [[self window] endEditingFor: fTrackerTable];
285   
286    const BOOL isPrivate = [fPrivateCheck state] == NSOnState;
287    if ([fTrackers count] == 0
288        && [fDefaults boolForKey: isPrivate ? @"WarningCreatorPrivateBlankAddress" : @"WarningCreatorBlankAddress"])
289    {
290        NSAlert * alert = [[NSAlert alloc] init];
291        [alert setMessageText: NSLocalizedString(@"There are no tracker addresses.", "Create torrent -> blank address -> title")];
292       
293        NSString * infoString = isPrivate
294                    ? NSLocalizedString(@"A transfer marked as private with no tracker addresses will be unable to connect to peers."
295                        " The torrent file will only be useful if you plan to upload the file to a tracker website"
296                        " that will add the addresses for you.", "Create torrent -> blank address -> message")
297                    : NSLocalizedString(@"The transfer will not contact trackers for peers, and will have to rely solely on"
298                        " non-tracker peer discovery methods such as PEX and DHT to download and seed.",
299                        "Create torrent -> blank address -> message");
300       
301        [alert setInformativeText: infoString];
302        [alert addButtonWithTitle: NSLocalizedString(@"Create", "Create torrent -> blank address -> button")];
303        [alert addButtonWithTitle: NSLocalizedString(@"Cancel", "Create torrent -> blank address -> button")];
304        [alert setShowsSuppressionButton: YES];
305
306        [alert beginSheetModalForWindow: [self window] modalDelegate: self
307            didEndSelector: @selector(createBlankAddressAlertDidEnd:returnCode:contextInfo:) contextInfo: nil];
308    }
309    else
310        [self createReal];
311}
312
313- (IBAction) cancelCreateWindow: (id) sender
314{
315    [[self window] close];
316}
317
318- (void) windowWillClose: (NSNotification *) notification
319{
320    [self autorelease];
321}
322
323- (IBAction) cancelCreateProgress: (id) sender
324{
325    fInfo->abortFlag = 1;
326    [fTimer fire];
327}
328
329- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableView
330{
331    return [fTrackers count];
332}
333
334- (id) tableView: (NSTableView *) tableView objectValueForTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row
335{
336    return [fTrackers objectAtIndex: row];
337}
338
339- (IBAction) addRemoveTracker: (id) sender
340{
341    //don't allow add/remove when currently adding - it leads to weird results
342    if ([fTrackerTable editedRow] != -1)
343        return;
344   
345    if ([[sender cell] tagForSegment: [sender selectedSegment]] == TRACKER_REMOVE_TAG)
346    {
347        [fTrackers removeObjectsAtIndexes: [fTrackerTable selectedRowIndexes]];
348       
349        [fTrackerTable deselectAll: self];
350        [fTrackerTable reloadData];
351    }
352    else
353    {
354        [fTrackers addObject: @""];
355        [fTrackerTable reloadData];
356       
357        const NSInteger row = [fTrackers count] - 1;
358        [fTrackerTable selectRowIndexes: [NSIndexSet indexSetWithIndex: row] byExtendingSelection: NO];
359        [fTrackerTable editColumn: 0 row: row withEvent: nil select: YES];
360    }
361}
362
363- (void) tableView: (NSTableView *) tableView setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn
364    row: (NSInteger) row
365{
366    NSString * tracker = (NSString *)object;
367   
368    tracker = [tracker stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
369   
370    if ([tracker rangeOfString: @"://"].location == NSNotFound)
371        tracker = [@"http://" stringByAppendingString: tracker];
372   
373    if (!tr_urlIsValidTracker([tracker UTF8String]))
374    {
375        NSBeep();
376        [fTrackers removeObjectAtIndex: row];
377    }
378    else
379        [fTrackers replaceObjectAtIndex: row withObject: tracker];
380   
381    [fTrackerTable deselectAll: self];
382    [fTrackerTable reloadData];
383}
384
385- (void) tableViewSelectionDidChange: (NSNotification *) notification
386{
387    [fTrackerAddRemoveControl setEnabled: [fTrackerTable numberOfSelectedRows] > 0 forSegment: TRACKER_REMOVE_TAG];
388}
389
390- (void) copy: (id) sender
391{
392    NSArray * addresses = [fTrackers objectsAtIndexes: [fTrackerTable selectedRowIndexes]];
393    NSString * text = [addresses componentsJoinedByString: @"\n"];
394   
395    NSPasteboard * pb = [NSPasteboard generalPasteboard];
396    [pb clearContents];
397    [pb writeObjects: [NSArray arrayWithObject: text]];
398}
399
400- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
401{
402    const SEL action = [menuItem action];
403   
404    if (action == @selector(copy:))
405        return [[self window] firstResponder] == fTrackerTable && [fTrackerTable numberOfSelectedRows] > 0;
406   
407    if (action == @selector(paste:))
408        return [[self window] firstResponder] == fTrackerTable
409            && [[NSPasteboard generalPasteboard] canReadObjectForClasses: [NSArray arrayWithObject: [NSString class]] options: nil];
410   
411    return YES;
412}
413
414- (void) paste: (id) sender
415{
416    NSMutableArray * tempTrackers = [NSMutableArray array];
417   
418    NSArray * items = [[NSPasteboard generalPasteboard] readObjectsForClasses: [NSArray arrayWithObject: [NSString class]] options: nil];
419    NSAssert(items != nil, @"no string items to paste; should not be able to call this method");
420   
421    for (NSString * pbItem in items)
422    {
423        for (NSString * tracker in [pbItem componentsSeparatedByString: @"\n"])
424            [tempTrackers addObject: tracker];
425    }
426   
427    BOOL added = NO;
428   
429    for (NSString * tracker in tempTrackers)
430    {
431        tracker = [tracker stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
432       
433        if ([tracker rangeOfString: @"://"].location == NSNotFound)
434            tracker = [@"http://" stringByAppendingString: tracker];
435       
436        if (tr_urlIsValidTracker([tracker UTF8String]))
437        {
438            [fTrackers addObject: tracker];
439            added = YES;
440        }
441    }
442   
443    if (added)
444    {
445        [fTrackerTable deselectAll: self];
446        [fTrackerTable reloadData];
447    }
448    else
449        NSBeep();
450}
451
452@end
453
454@implementation CreatorWindowController (Private)
455
456+ (NSURL *) chooseFile
457{
458    NSOpenPanel * panel = [NSOpenPanel openPanel];
459   
460    [panel setTitle: NSLocalizedString(@"Create Torrent File", "Create torrent -> select file")];
461    [panel setPrompt: NSLocalizedString(@"Select", "Create torrent -> select file")];
462    [panel setAllowsMultipleSelection: NO];
463    [panel setCanChooseFiles: YES];
464    [panel setCanChooseDirectories: YES];
465    [panel setCanCreateDirectories: NO];
466
467    [panel setMessage: NSLocalizedString(@"Select a file or folder for the torrent file.", "Create torrent -> select file")];
468   
469    BOOL success = [panel runModal] == NSOKButton;
470    return success ? [[panel URLs] objectAtIndex: 0] : nil;
471}
472
473- (void) createBlankAddressAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
474{
475    if ([[alert suppressionButton] state] == NSOnState)
476    {
477        [[NSUserDefaults standardUserDefaults] setBool: NO forKey: @"WarningCreatorBlankAddress"]; //set regardless of private/public
478        if ([fPrivateCheck state] == NSOnState)
479            [[NSUserDefaults standardUserDefaults] setBool: NO forKey: @"WarningCreatorPrivateBlankAddress"];
480    }
481   
482    [alert release];
483   
484    if (returnCode == NSAlertFirstButtonReturn)
485        [self performSelectorOnMainThread: @selector(createReal) withObject: nil waitUntilDone: NO];
486}
487
488- (void) createReal
489{
490    //check if the location currently exists
491    if (![[fLocation URLByDeletingLastPathComponent] checkResourceIsReachableAndReturnError: NULL])
492    {
493        NSAlert * alert = [[[NSAlert alloc] init] autorelease];
494        [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> directory doesn't exist warning -> button")];
495        [alert setMessageText: NSLocalizedString(@"The chosen torrent file location does not exist.",
496                                                "Create torrent -> directory doesn't exist warning -> title")];
497        [alert setInformativeText: [NSString stringWithFormat:
498                NSLocalizedString(@"The directory \"%@\" does not currently exist. "
499                    "Create this directory or choose a different one to create the torrent file.",
500                    "Create torrent -> directory doesn't exist warning -> warning"),
501                    [[fLocation URLByDeletingLastPathComponent] path]]];
502        [alert setAlertStyle: NSWarningAlertStyle];
503       
504        [alert beginSheetModalForWindow: [self window] modalDelegate: self didEndSelector: nil contextInfo: nil];
505        return;
506    }
507   
508    //check if a file with the same name and location already exists
509    if ([fLocation checkResourceIsReachableAndReturnError: NULL])
510    {
511        NSArray * pathComponents = [fLocation pathComponents];
512        NSInteger count = [pathComponents count];
513       
514        NSAlert * alert = [[[NSAlert alloc] init] autorelease];
515        [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> file already exists warning -> button")];
516        [alert setMessageText: NSLocalizedString(@"A torrent file with this name and directory cannot be created.",
517                                                "Create torrent -> file already exists warning -> title")];
518        [alert setInformativeText: [NSString stringWithFormat:
519                NSLocalizedString(@"A file with the name \"%@\" already exists in the directory \"%@\". "
520                    "Choose a new name or directory to create the torrent file.",
521                    "Create torrent -> file already exists warning -> warning"),
522                    [pathComponents objectAtIndex: count-1], [pathComponents objectAtIndex: count-2]]];
523        [alert setAlertStyle: NSWarningAlertStyle];
524       
525        [alert beginSheetModalForWindow: [self window] modalDelegate: self didEndSelector: nil contextInfo: nil];
526        return;
527    }
528   
529    //parse non-empty tracker strings
530    tr_tracker_info * trackerInfo = tr_new0(tr_tracker_info, [fTrackers count]);
531   
532    for (NSUInteger i = 0; i < [fTrackers count]; i++)
533    {
534        trackerInfo[i].announce = (char *)[[fTrackers objectAtIndex: i] UTF8String];
535        trackerInfo[i].tier = i;
536    }
537   
538    //store values
539    [fDefaults setObject: fTrackers forKey: @"CreatorTrackers"];
540    [fDefaults setBool: [fPrivateCheck state] == NSOnState forKey: @"CreatorPrivate"];
541    [fDefaults setBool: [fOpenCheck state] == NSOnState forKey: @"CreatorOpen"];
542    [fDefaults setURL: [fLocation URLByDeletingLastPathComponent] forKey: @"CreatorLocationURL"];
543   
544    [[NSNotificationCenter defaultCenter] postNotificationName: @"BeginCreateTorrentFile" object: fLocation userInfo: nil];
545    tr_makeMetaInfo(fInfo, [[fLocation path] UTF8String], trackerInfo, [fTrackers count], [[fCommentView string] UTF8String],
546                    [fPrivateCheck state] == NSOnState);
547    tr_free(trackerInfo);
548   
549    fTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector(checkProgress)
550                userInfo: nil repeats: YES];
551}
552
553- (void) checkProgress
554{
555    if (fInfo->isDone)
556    {
557        [fTimer invalidate];
558        fTimer = nil;
559       
560        NSAlert * alert;
561        switch (fInfo->result)
562        {
563            case TR_MAKEMETA_OK:
564                #warning this isn't safe - what if another window changes it after hitting the create button on this window?
565                if ([fDefaults boolForKey: @"CreatorOpen"])
566                {
567                    NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys: [fLocation path], @"File",
568                                            [[fPath URLByDeletingLastPathComponent] path], @"Path", nil];
569                    [[NSNotificationCenter defaultCenter] postNotificationName: @"OpenCreatedTorrentFile" object: self userInfo: dict];
570                }
571               
572                [[self window] close];
573                break;
574           
575            case TR_MAKEMETA_CANCELLED:
576                [[self window] close];
577                break;
578           
579            default:
580                alert = [[[NSAlert alloc] init] autorelease];
581                [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> failed -> button")];
582                [alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"Creation of \"%@\" failed.",
583                                                "Create torrent -> failed -> title"), [fLocation lastPathComponent]]];
584                [alert setAlertStyle: NSWarningAlertStyle];
585               
586                if (fInfo->result == TR_MAKEMETA_IO_READ)
587                    [alert setInformativeText: [NSString stringWithFormat: NSLocalizedString(@"Could not read \"%s\": %s.",
588                        "Create torrent -> failed -> warning"), fInfo->errfile, strerror(fInfo->my_errno)]];
589                else if (fInfo->result == TR_MAKEMETA_IO_WRITE)
590                    [alert setInformativeText: [NSString stringWithFormat: NSLocalizedString(@"Could not write \"%s\": %s.",
591                        "Create torrent -> failed -> warning"), fInfo->errfile, strerror(fInfo->my_errno)]];
592                else //invalid url should have been caught before creating
593                    [alert setInformativeText: [NSString stringWithFormat: @"%@ (%d)",
594                        NSLocalizedString(@"An unknown error has occurred.", "Create torrent -> failed -> warning"), fInfo->result]];
595               
596                [alert beginSheetModalForWindow: [self window] modalDelegate: self
597                    didEndSelector: @selector(failureSheetClosed:returnCode:contextInfo:) contextInfo: nil];
598        }
599    }
600    else
601    {
602        [fProgressIndicator setDoubleValue: (double)fInfo->pieceIndex / fInfo->pieceCount];
603       
604        if (!fStarted)
605        {
606            fStarted = YES;
607           
608            [fProgressView setHidden: YES];
609           
610            NSWindow * window = [self window];
611            [window setFrameAutosaveName: @""];
612           
613            NSRect windowRect = [window frame];
614            CGFloat difference = [fProgressView frame].size.height - [[window contentView] frame].size.height;
615            windowRect.origin.y -= difference;
616            windowRect.size.height += difference;
617           
618            //don't allow vertical resizing
619            CGFloat height = windowRect.size.height;
620            [window setMinSize: NSMakeSize([window minSize].width, height)];
621            [window setMaxSize: NSMakeSize([window maxSize].width, height)];
622           
623            [window setContentView: fProgressView];
624            [window setFrame: windowRect display: YES animate: YES];
625            [fProgressView setHidden: NO];
626           
627            [[window standardWindowButton: NSWindowCloseButton] setEnabled: NO];
628        }
629    }
630}
631
632- (void) failureSheetClosed: (NSAlert *) alert returnCode: (NSInteger) code contextInfo: (void *) info
633{
634    [[alert window] orderOut: nil];
635    [[self window] close];
636}
637
638@end
Note: See TracBrowser for help on using the repository browser.