source: trunk/macosx/CreatorWindowController.m @ 2149

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

Merge file selection and torrent creation into the main branch.

The new code for these features is under a new license.

File size: 13.5 KB
Line 
1/******************************************************************************
2 * $Id$
3 *
4 * Copyright (c) 2007 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 "StringAdditions.h"
27
28#define DEFAULT_SAVE_LOCATION @"~/Desktop/"
29
30@interface CreatorWindowController (Private)
31
32+ (NSString *) chooseFile;
33- (void) locationSheetClosed: (NSSavePanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
34- (void) checkProgress;
35- (void) failureSheetClosed: (NSAlert *) alert returnCode: (int) code contextInfo: (void *) info;
36
37@end
38
39@implementation CreatorWindowController
40
41+ (void) createTorrentFile: (tr_handle_t *) handle
42{
43    //get file/folder for torrent
44    NSString * path;
45    if (!(path = [CreatorWindowController chooseFile]))
46        return;
47   
48    CreatorWindowController * creator = [[self alloc] initWithWindowNibName: @"Creator" handle: handle path: path];
49    [creator showWindow: nil];
50}
51
52+ (void) createTorrentFile: (tr_handle_t *) handle forFile: (NSString *) file
53{
54    CreatorWindowController * creator = [[self alloc] initWithWindowNibName: @"Creator" handle: handle path: file];
55    [creator showWindow: nil];
56}
57
58- (id) initWithWindowNibName: (NSString *) name handle: (tr_handle_t *) handle path: (NSString *) path
59{
60    if ((self = [super initWithWindowNibName: name]))
61    {
62        fStarted = NO;
63       
64        fPath = [path retain];
65        fInfo = tr_metaInfoBuilderCreate(handle, [fPath UTF8String]);
66        if (fInfo->fileCount == 0)
67        {
68            NSAlert * alert = [[[NSAlert alloc] init] autorelease];
69            [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> no files -> button")];
70            [alert setMessageText: NSLocalizedString(@"This folder contains no files.",
71                                                    "Create torrent -> no files -> title")];
72            [alert setInformativeText: NSLocalizedString(@"There must be at least one file in a folder to create a torrent file.",
73                                                        "Create torrent -> no files -> warning")];
74            [alert setAlertStyle: NSWarningAlertStyle];
75           
76            [alert runModal];
77           
78            [self release];
79            return nil;
80        }
81    }
82    return self;
83}
84
85- (void) awakeFromNib
86{
87    NSString * name = [fPath lastPathComponent];
88   
89    [[self window] setTitle: name];
90   
91    [fNameField setStringValue: name];
92    [fNameField setToolTip: fPath];
93   
94    BOOL multifile = !fInfo->isSingleFile;
95   
96    #warning fix when resizing window
97    [fIcon setImage: [[NSWorkspace sharedWorkspace] iconForFileType: multifile
98                        ? NSFileTypeForHFSTypeCode('fldr') : [fPath pathExtension]]];
99   
100    NSString * statusString = [NSString stringForFileSize: fInfo->totalSize];
101    if (multifile)
102    {
103        NSString * fileString;
104        int count = fInfo->fileCount;
105        if (count != 1)
106            fileString = [NSString stringWithFormat: NSLocalizedString(@"%d Files, ", "Create torrent -> info"), count];
107        else
108            fileString = NSLocalizedString(@"1 File, ", "Create torrent -> info");
109        statusString = [fileString stringByAppendingString: statusString];
110    }
111    [fStatusField setStringValue: statusString];
112   
113    NSString * piecesCountString;
114    int piecesCount = fInfo->pieceCount;
115    if (piecesCount == 1)
116        piecesCountString = NSLocalizedString(@"1 piece", "Create torrent -> info");
117    else
118        piecesCountString = [NSString stringWithFormat: NSLocalizedString(@"%d pieces", "Create torrent -> info"),
119                                                                piecesCount];
120    [fPiecesField setStringValue: [NSString stringWithFormat: NSLocalizedString(@"%@, %@ each", "Create torrent -> info"),
121                                        piecesCountString, [NSString stringForFileSize: fInfo->pieceSize]]];
122   
123    fLocation = [[[DEFAULT_SAVE_LOCATION stringByAppendingPathComponent: [name stringByAppendingPathExtension: @"torrent"]]
124                                            stringByExpandingTildeInPath] retain];
125    [fLocationField setStringValue: [fLocation stringByAbbreviatingWithTildeInPath]];
126    [fLocationField setToolTip: fLocation];
127}
128
129- (void) dealloc
130{
131    [fPath release];
132    if (fLocation)
133        [fLocation release];
134   
135    if (fInfo)
136        tr_metaInfoBuilderFree(fInfo);
137   
138    if (fTimer)
139        [fTimer invalidate];
140   
141    [super dealloc];
142}
143
144- (void) setLocation: (id) sender
145{
146    NSSavePanel * panel = [NSSavePanel savePanel];
147
148    [panel setPrompt: @"Select"];
149    [panel setRequiredFileType: @"torrent"];
150    [panel setCanSelectHiddenExtension: YES];
151
152    [panel beginSheetForDirectory: nil file: [fLocation lastPathComponent] modalForWindow: [self window] modalDelegate: self
153            didEndSelector: @selector(locationSheetClosed:returnCode:contextInfo:) contextInfo: nil];
154}
155
156- (void) create: (id) sender
157{
158    //parse tracker string
159    NSString * trackerString = [fTrackerField stringValue];
160    if ([trackerString rangeOfString: @"://"].location != NSNotFound)
161    {
162        if (![trackerString hasPrefix: @"http://"])
163        {
164            NSAlert * alert = [[[NSAlert alloc] init] autorelease];
165            [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> http warning -> button")];
166            [alert setMessageText: NSLocalizedString(@"The tracker address must begin with \"http://\".",
167                                                    "Create torrent -> http warning -> title")];
168            [alert setInformativeText: NSLocalizedString(@"Change the tracker address to create the torrent.",
169                                                        "Create torrent -> http warning -> warning")];
170            [alert setAlertStyle: NSWarningAlertStyle];
171           
172            [alert beginSheetModalForWindow: [self window] modalDelegate: self didEndSelector: nil contextInfo: nil];
173            return;
174        }
175    }
176    else
177        trackerString = [@"http://" stringByAppendingString: trackerString];
178   
179    //don't allow blank addresses
180    if ([trackerString length] <= 7)
181    {
182        NSAlert * alert = [[[NSAlert alloc] init] autorelease];
183        [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> no url warning -> button")];
184        [alert setMessageText: NSLocalizedString(@"The tracker address cannot be blank.",
185                                                "Create torrent -> no url warning -> title")];
186        [alert setInformativeText: NSLocalizedString(@"Change the tracker address to create the torrent.",
187                                                    "Create torrent -> no url warning -> warning")];
188        [alert setAlertStyle: NSWarningAlertStyle];
189       
190        [alert beginSheetModalForWindow: [self window] modalDelegate: self didEndSelector: nil contextInfo: nil];
191        return;
192    }
193   
194    //check if a file with the same name and location already exists
195    if ([[NSFileManager defaultManager] fileExistsAtPath: fLocation])
196    {
197        NSArray * pathComponents = [fLocation pathComponents];
198        int count = [pathComponents count];
199       
200        NSAlert * alert = [[[NSAlert alloc] init] autorelease];
201        [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> file already exists warning -> button")];
202        [alert setMessageText: NSLocalizedString(@"A torrent file with this name and directory cannot be created.",
203                                                "Create torrent -> file already exists warning -> title")];
204        [alert setInformativeText: [NSString stringWithFormat:
205                NSLocalizedString(@"A file with the name \"%@\" already exists in the directory \"%@\". "
206                    "Choose a new name or directory to create the torrent.",
207                    "Create torrent -> file already exists warning -> warning"),
208                    [pathComponents objectAtIndex: count-1], [pathComponents objectAtIndex: count-2]]];
209        [alert setAlertStyle: NSWarningAlertStyle];
210       
211        [alert beginSheetModalForWindow: [self window] modalDelegate: self didEndSelector: nil contextInfo: nil];
212        return;
213    }
214   
215    fOpenTorrent = [fOpenCheck state] == NSOnState;
216    tr_makeMetaInfo(fInfo, [fLocation UTF8String], [trackerString UTF8String], [[fCommentView string] UTF8String],
217                    [fPrivateCheck state] == NSOnState);
218   
219    fTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector(checkProgress)
220                        userInfo: nil repeats: YES];
221}
222
223- (void) cancelCreateWindow: (id) sender
224{
225    [[self window] close];
226}
227
228- (void) windowWillClose: (NSNotification *) notification
229{
230    [self release];
231}
232
233- (void) cancelCreateProgress: (id) sender
234{
235    fInfo->abortFlag = 1;
236    [fTimer fire];
237}
238
239@end
240
241@implementation CreatorWindowController (Private)
242
243+ (NSString *) chooseFile
244{
245    NSOpenPanel * panel = [NSOpenPanel openPanel];
246   
247    [panel setPrompt: NSLocalizedString(@"Select", "Create torrent -> select file")];
248    [panel setAllowsMultipleSelection: NO];
249    [panel setCanChooseFiles: YES];
250    [panel setCanChooseDirectories: YES];
251    [panel setCanCreateDirectories: NO];
252
253    [panel setMessage: NSLocalizedString(@"Select a file or folder for the torrent file.", "Create torrent -> select file")];
254   
255    BOOL success = [panel runModal] == NSOKButton;
256    return success ? [[panel filenames] objectAtIndex: 0] : nil;
257}
258
259- (void) locationSheetClosed: (NSSavePanel *) panel returnCode: (int) code contextInfo: (void *) info
260{
261    if (code == NSOKButton)
262    {
263        [fLocation release];
264        fLocation = [[panel filename] retain];
265       
266        [fLocationField setStringValue: [fLocation stringByAbbreviatingWithTildeInPath]];
267        [fLocationField setToolTip: fLocation];
268    }
269}
270
271- (void) checkProgress
272{
273    if (fInfo->isDone)
274    {
275        [fTimer invalidate];
276        fTimer = nil;
277       
278        if (fInfo->failed)
279        {
280            if (!fInfo->abortFlag)
281            {
282                NSAlert * alert = [[[NSAlert alloc] init] autorelease];
283                [alert addButtonWithTitle: NSLocalizedString(@"OK", "Create torrent -> failed -> button")];
284                [alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"Creation of \"%@\" failed.",
285                                                "Create torrent -> failed -> title"), [fLocation lastPathComponent]]];
286                [alert setInformativeText: NSLocalizedString(@"There was an error parsing the data file. "
287                                            "The torrent file was not created.", "Create torrent -> failed -> warning")];
288                [alert setAlertStyle: NSWarningAlertStyle];
289               
290                [alert beginSheetModalForWindow: [self window] modalDelegate: self
291                        didEndSelector: @selector(failureSheetClosed:returnCode:contextInfo:) contextInfo: nil];
292                return;
293            }
294        }
295        else
296        {
297            if (fOpenTorrent)
298            {
299                NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys: fLocation, @"File",
300                                        [fPath stringByDeletingLastPathComponent], @"Path", nil];
301                [[NSNotificationCenter defaultCenter] postNotificationName: @"OpenCreatedTorrentFile" object: self userInfo: dict];
302            }
303        }
304       
305        [[self window] close];
306    }
307    else
308    {
309        [fProgressIndicator setDoubleValue: (double)fInfo->pieceIndex / fInfo->pieceCount];
310       
311        if (!fStarted)
312        {
313            NSWindow * window = [self window];
314           
315            NSRect windowRect = [window frame];
316            float difference = [fProgressView frame].size.height - [[window contentView] frame].size.height;
317            windowRect.origin.y -= difference;
318            windowRect.size.height += difference;
319           
320            //don't allow vertical resizing
321            float height = windowRect.size.height;
322            [window setMinSize: NSMakeSize([window minSize].width, height)];
323            [window setMaxSize: NSMakeSize([window maxSize].width, height)];
324           
325            [window setContentView: fProgressView];
326            [window setFrame: windowRect display: YES animate: YES];
327            [fProgressView setHidden: NO];
328           
329            fStarted = YES;
330        }
331    }
332}
333
334- (void) failureSheetClosed: (NSAlert *) alert returnCode: (int) code contextInfo: (void *) info
335{
336    [[alert window] orderOut: nil];
337    [[self window] close];
338}
339
340@end
Note: See TracBrowser for help on using the repository browser.