source: trunk/macosx/PrefsController.m @ 310

Last change on this file since 310 was 310, checked in by joshe, 16 years ago

Add support to libtransmission and the MacOS X GUI for saving private copies of

torrent files.

  • Property svn:keywords set to Date Rev Author Id
File size: 17.1 KB
Line 
1/******************************************************************************
2 * $Id: PrefsController.m 310 2006-06-09 19:53:35Z joshe $
3 *
4 * Copyright (c) 2005-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 "PrefsController.h"
26#import "StringAdditions.h"
27#import "Utils.h"
28
29#define MIN_PORT            1
30#define MAX_PORT            65535
31
32#define DOWNLOAD_FOLDER     0
33#define DOWNLOAD_TORRENT    2
34#define DOWNLOAD_ASK        3
35
36#define UPDATE_DAILY        0
37#define UPDATE_WEEKLY       1
38#define UPDATE_NEVER        2
39
40#define TOOLBAR_GENERAL     @"General"
41#define TOOLBAR_TRANSFERS   @"Transfers"
42#define TOOLBAR_NETWORK     @"Network"
43
44@interface PrefsController (Private)
45
46- (void) showGeneralPref: (id) sender;
47- (void) showTransfersPref: (id) sender;
48- (void) showNetworkPref: (id) sender;
49
50- (void) setPrefView: (NSView *) view;
51
52- (void) folderSheetClosed: (NSOpenPanel *) s returnCode: (int) code
53                                contextInfo: (void *) info;
54- (void) updatePopUp;
55
56@end
57
58@implementation PrefsController
59
60+ (void) initialize
61{
62    [[NSUserDefaults standardUserDefaults] registerDefaults:
63        [NSDictionary dictionaryWithContentsOfFile:
64            [[NSBundle mainBundle] pathForResource: @"Defaults"
65                ofType: @"plist"]]];
66}
67
68- (void) dealloc
69{
70    [fDownloadFolder release];
71    [super dealloc];
72}
73
74- (void) setPrefsWindow: (tr_handle_t *) handle
75{
76    fToolbar = [[NSToolbar alloc] initWithIdentifier: @"Preferences Toolbar"];
77    [fToolbar setDelegate: self];
78    [fToolbar setAllowsUserCustomization: NO];
79    [[self window] setToolbar: fToolbar];
80    [fToolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
81    [fToolbar setSizeMode: NSToolbarSizeModeRegular];
82
83    [fToolbar setSelectedItemIdentifier: TOOLBAR_GENERAL];
84    [self showGeneralPref: nil];
85
86    fDefaults = [NSUserDefaults standardUserDefaults];
87    fHandle = handle;
88   
89    //set download folder
90    NSString * downloadChoice  = [fDefaults stringForKey: @"DownloadChoice"];
91    fDownloadFolder = [[fDefaults stringForKey: @"DownloadFolder"] stringByExpandingTildeInPath];
92    [fDownloadFolder retain];
93
94    if ([downloadChoice isEqualToString: @"Constant"])
95        [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
96    else if ([downloadChoice isEqualToString: @"Torrent"])
97        [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
98    else
99        [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
100    [self updatePopUp];
101
102    //set bind port
103    int bindPort = [fDefaults integerForKey: @"BindPort"];
104    [fPortField setIntValue: bindPort];
105    fHandle = handle;
106    tr_setBindPort( fHandle, bindPort );
107   
108    //checks for old version upload speed of -1
109    if ([fDefaults integerForKey: @"UploadLimit"] < 0)
110    {
111        [fDefaults setInteger: 20 forKey: @"UploadLimit"];
112        [fDefaults setBool: NO forKey: @"CheckUpload"];
113    }
114   
115    //set upload limit
116    BOOL checkUpload = [fDefaults boolForKey: @"CheckUpload"];
117    int uploadLimit = [fDefaults integerForKey: @"UploadLimit"];
118   
119    [fUploadCheck setState: checkUpload];
120    [fUploadField setIntValue: uploadLimit];
121    [fUploadField setEnabled: checkUpload];
122   
123    tr_setUploadLimit( fHandle, checkUpload ? uploadLimit : -1 );
124
125        //set download limit
126    BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
127    int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
128   
129    [fDownloadCheck setState: checkDownload];
130    [fDownloadField setIntValue: downloadLimit];
131    [fDownloadField setEnabled: checkDownload];
132   
133    tr_setDownloadLimit( fHandle, checkDownload ? downloadLimit : -1 );
134   
135    //set ratio limit
136    BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
137    [fRatioCheck setState: ratioCheck];
138    [fRatioField setEnabled: ratioCheck];
139    [fRatioField setFloatValue: [fDefaults floatForKey: @"RatioLimit"]];
140   
141    //set remove and quit prompts
142    [fQuitCheck setState: [fDefaults boolForKey: @"CheckQuit"]];
143    [fRemoveCheck setState: [fDefaults boolForKey: @"CheckRemove"]];
144
145    //set dock badging
146    [fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
147    [fBadgeUploadRateCheck setState: [fDefaults boolForKey: @"BadgeUploadRate"]];
148   
149    //set auto start
150    [fAutoStartCheck setState: [fDefaults boolForKey: @"AutoStartDownload"]];
151   
152    //set private torrents
153    BOOL copyTorrents = [fDefaults boolForKey: @"SavePrivateTorrent"];
154    [fCopyTorrentCheck setState: copyTorrents];
155   
156    [fDeleteOriginalTorrentCheck setEnabled: copyTorrents];
157    [fDeleteOriginalTorrentCheck setState: [fDefaults boolForKey: @"DeleteOriginalTorrent"]];
158
159    //set update check
160    NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
161    if ([updateCheck isEqualToString: @"Weekly"])
162        [fUpdatePopUp selectItemAtIndex: UPDATE_WEEKLY];
163    else if ([updateCheck isEqualToString: @"Never"])
164        [fUpdatePopUp selectItemAtIndex: UPDATE_NEVER];
165    else
166        [fUpdatePopUp selectItemAtIndex: UPDATE_DAILY];
167}
168
169- (NSToolbarItem *) toolbar: (NSToolbar *) t itemForItemIdentifier:
170    (NSString *) ident willBeInsertedIntoToolbar: (BOOL) flag
171{
172    NSToolbarItem * item;
173    item = [[NSToolbarItem alloc] initWithItemIdentifier: ident];
174
175    if ([ident isEqualToString: TOOLBAR_GENERAL])
176    {
177        [item setLabel: TOOLBAR_GENERAL];
178        [item setImage: [NSImage imageNamed: @"Preferences.png"]];
179        [item setTarget: self];
180        [item setAction: @selector( showGeneralPref: )];
181    }
182    else if ([ident isEqualToString: TOOLBAR_TRANSFERS])
183    {
184        [item setLabel: TOOLBAR_TRANSFERS];
185        [item setImage: [NSImage imageNamed: @"Transfers.png"]];
186        [item setTarget: self];
187        [item setAction: @selector( showTransfersPref: )];
188    }
189    else if ([ident isEqualToString: TOOLBAR_NETWORK])
190    {
191        [item setLabel: TOOLBAR_NETWORK];
192        [item setImage: [NSImage imageNamed: @"Network.png"]];
193        [item setTarget: self];
194        [item setAction: @selector( showNetworkPref: )];
195    }
196    else
197    {
198        [item release];
199        return nil;
200    }
201
202    return item;
203}
204
205- (NSArray *) toolbarSelectableItemIdentifiers: (NSToolbar *) toolbar
206{
207    return [self toolbarDefaultItemIdentifiers: nil];
208}
209
210- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
211{
212    return [self toolbarAllowedItemIdentifiers: nil];
213}
214
215- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
216{
217    return [NSArray arrayWithObjects:
218            TOOLBAR_GENERAL, TOOLBAR_TRANSFERS,
219            TOOLBAR_NETWORK, nil];
220}
221
222- (void) setPort: (id) sender
223{
224    int bindPort = [sender intValue];
225    if (![[NSString stringWithInt: bindPort] isEqualToString: [sender stringValue]]
226            || bindPort < MIN_PORT || bindPort > MAX_PORT)
227    {
228        NSBeep();
229        bindPort = [fDefaults integerForKey: @"BindPort"];
230        [sender setIntValue: bindPort];
231    }
232    else
233    {
234        tr_setBindPort( fHandle, bindPort );
235        [fDefaults setInteger: bindPort forKey: @"BindPort"];
236    }
237}
238
239- (void) setLimit: (id) sender
240{
241    NSString * key;
242    NSButton * check;
243    NSString * type;
244    if (sender == fUploadField)
245    {
246        key = @"UploadLimit";
247        check = fUploadCheck;
248        type = @"Upload";
249    }
250    else
251    {
252        key = @"DownloadLimit";
253        check = fDownloadCheck;
254        type = @"Download";
255    }
256
257    int limit = [sender intValue];
258    if (![[sender stringValue] isEqualToString:
259            [NSString stringWithFormat: @"%d", limit]]
260            || limit < 0)
261    {
262        NSBeep();
263        limit = [fDefaults integerForKey: key];
264        [sender setIntValue: limit];
265    }
266    else
267    {
268        if( sender == fUploadField )
269            tr_setUploadLimit( fHandle,
270                ( [fUploadCheck state] == NSOffState ) ? -1 : limit );
271        else
272            tr_setDownloadLimit( fHandle,
273                ( [fDownloadCheck state] == NSOffState ) ? -1 : limit );
274       
275        [fDefaults setInteger: limit forKey: key];
276    }
277   
278    NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
279                                    [NSNumber numberWithBool: [check state]], @"Enable",
280                                    [NSNumber numberWithInt: limit], @"Limit",
281                                    type, @"Type", nil];
282    [[NSNotificationCenter defaultCenter] postNotificationName:
283                            @"LimitGlobalChange" object: dict];
284}
285
286- (void) setLimitCheck: (id) sender
287{
288    NSString * key;
289    NSTextField * field;
290    if (sender == fUploadCheck)
291    {
292        key = @"CheckUpload";
293        field = fUploadField;
294    }
295    else
296    {
297        key = @"CheckDownload";
298        field = fDownloadField;
299    }
300   
301    BOOL check = [sender state] == NSOnState;
302    [self setLimit: field];
303    [field setEnabled: check];
304   
305    [fDefaults setBool: check forKey: key];
306}
307
308- (void) setLimitEnabled: (BOOL) enable type: (NSString *) type
309{
310    NSButton * check = [type isEqualToString: @"Upload"]
311                        ? fUploadCheck : fDownloadCheck;
312    [check setState: enable ? NSOnState : NSOffState];
313    [self setLimitCheck: check];
314}
315
316- (void) setQuickLimit: (int) limit type: (NSString *) type
317{
318    NSButton * check;
319    if ([type isEqualToString: @"Upload"])
320    {
321        [fUploadField setIntValue: limit];
322        check = fUploadCheck;
323    }
324    else
325    {
326        [fDownloadField setIntValue: limit];
327        check = fDownloadCheck;
328    }
329    [check setState: NSOnState];
330    [self setLimitCheck: check];
331}
332
333- (void) setRatio: (id) sender
334{
335    float ratioLimit = [sender floatValue];
336    if (![[sender stringValue] isEqualToString:
337            [NSString stringWithFormat: @"%.2f", ratioLimit]]
338            || ratioLimit < 0)
339    {
340        NSBeep();
341        ratioLimit = [fDefaults floatForKey: @"RatioLimit"];
342        [sender setFloatValue: ratioLimit];
343    }
344    else
345        [fDefaults setFloat: ratioLimit forKey: @"RatioLimit"];
346   
347    NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
348                                    [NSNumber numberWithBool: [fRatioCheck state]], @"Enable",
349                                    [NSNumber numberWithFloat: ratioLimit], @"Ratio", nil];
350    [[NSNotificationCenter defaultCenter] postNotificationName:
351                                @"RatioGlobalChange" object: dict];
352}
353
354- (void) setRatioCheck: (id) sender
355{
356    BOOL check = [sender state] == NSOnState;
357    [self setRatio: fRatioField];
358    [fRatioField setEnabled: check];
359   
360    [fDefaults setBool: check forKey: @"RatioCheck"];
361}
362
363- (void) setRatioEnabled: (BOOL) enable
364{
365    int state = enable ? NSOnState : NSOffState;
366   
367    [fRatioCheck setState: state];
368    [self setRatioCheck: fRatioCheck];
369}
370
371- (void) setQuickRatio: (float) ratioLimit
372{
373    [fRatioField setFloatValue: ratioLimit];
374   
375    [fRatioCheck setState: NSOnState];
376    [self setRatioCheck: fRatioCheck];
377}
378
379- (void) setShowMessage: (id) sender
380{
381    if (sender == fQuitCheck)
382        [fDefaults setBool: [sender state] forKey: @"CheckQuit"];
383    else if (sender == fRemoveCheck)
384        [fDefaults setBool: [fRemoveCheck state] forKey: @"CheckRemove"];
385    else;
386}
387
388- (void) setBadge: (id) sender
389{   
390    if (sender == fBadgeDownloadRateCheck)
391        [fDefaults setBool: [sender state] forKey: @"BadgeDownloadRate"];
392    else if (sender == fBadgeUploadRateCheck)
393        [fDefaults setBool: [sender state] forKey: @"BadgeUploadRate"];
394    else;
395}
396
397- (void) setUpdate: (id) sender
398{
399    NSString * schedule;
400    int index = [fUpdatePopUp indexOfSelectedItem];
401    NSTimeInterval seconds;
402    if (index == UPDATE_DAILY)
403    {
404        [fDefaults setObject: @"Daily" forKey: @"UpdateCheck"];
405        seconds = 86400;
406    }
407    else if (index == UPDATE_WEEKLY)
408    {
409        [fDefaults setObject: @"Weekly" forKey: @"UpdateCheck"];
410        seconds = 604800;
411    }
412    else
413    {
414        [fDefaults setObject: @"Never" forKey: @"UpdateCheck"];
415        seconds = 0;
416    }
417
418    [fDefaults setInteger: seconds forKey: @"SUScheduledCheckInterval"];
419    [fUpdater scheduleCheckWithInterval: seconds];
420}
421
422- (void) setAutoStart: (id) sender
423{
424    [fDefaults setBool: [sender state] forKey: @"AutoStartDownload"];
425}
426
427- (void) setMoveTorrent: (id) sender
428{
429    int state = [sender state];
430    if (sender == fCopyTorrentCheck)
431    {
432        [fDefaults setBool: state forKey: @"SavePrivateTorrent"];
433       
434        [fDeleteOriginalTorrentCheck setEnabled: state];
435        if (state == NSOffState)
436        {
437            [fDeleteOriginalTorrentCheck setState: NSOffState];
438            [fDefaults setBool: NO forKey: @"DeleteOriginalTorrent"];
439        }
440    }
441    else
442        [fDefaults setBool: state forKey: @"DeleteOriginalTorrent"];
443}
444
445- (void) setDownloadLocation: (id) sender
446{
447    //Download folder
448    switch( [fFolderPopUp indexOfSelectedItem] )
449    {
450        case DOWNLOAD_FOLDER:
451            [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
452            break;
453        case DOWNLOAD_TORRENT:
454            [fDefaults setObject: @"Torrent" forKey: @"DownloadChoice"];
455            break;
456        case DOWNLOAD_ASK:
457            [fDefaults setObject: @"Ask" forKey: @"DownloadChoice"];
458            break;
459    }
460}
461
462- (void) checkUpdate
463{
464    [fUpdater checkForUpdates: nil];
465}
466
467- (void) folderSheetShow: (id) sender
468{
469    NSOpenPanel * panel = [NSOpenPanel openPanel];
470
471    [panel setPrompt:                  @"Select"];
472    [panel setAllowsMultipleSelection:        NO];
473    [panel setCanChooseFiles:                 NO];
474    [panel setCanChooseDirectories:          YES];
475
476    [panel beginSheetForDirectory: NULL file: NULL types: NULL
477        modalForWindow: [self window] modalDelegate: self didEndSelector:
478        @selector( folderSheetClosed:returnCode:contextInfo: )
479        contextInfo: NULL];
480}
481
482@end
483
484@implementation PrefsController (Private)
485
486- (void) showGeneralPref: (id) sender
487{
488    [self setPrefView: fGeneralView];
489}
490
491- (void) showTransfersPref: (id) sender
492{
493    [self setPrefView: fTransfersView];
494}
495
496- (void) showNetworkPref: (id) sender
497{
498    [self setPrefView: fNetworkView];
499}
500
501- (void) setPrefView: (NSView *) view
502{
503    NSWindow * window = [self window];
504   
505    NSRect windowRect = [window frame];
506    int difference = [view frame].size.height - [[window contentView] frame].size.height;
507    windowRect.origin.y -= difference;
508    windowRect.size.height += difference;
509
510    [window setTitle: [fToolbar selectedItemIdentifier]];
511   
512    [window setContentView: view];
513    [view setHidden: YES];
514    [window setFrame: windowRect display: YES animate: YES];
515    [view setHidden: NO];
516}
517
518- (void) folderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code
519    contextInfo: (void *) info
520{
521   if (code == NSOKButton)
522   {
523       [fDownloadFolder release];
524       fDownloadFolder = [[openPanel filenames] objectAtIndex: 0];
525       [fDownloadFolder retain];
526
527       [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
528       [fDefaults setObject: fDownloadFolder forKey: @"DownloadFolder"];
529       [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
530
531       [self updatePopUp];
532   }
533   else
534   {
535       //reset if cancelled
536       NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
537       if( [downloadChoice isEqualToString: @"Constant"] )
538       {
539           [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
540       }
541       else if( [downloadChoice isEqualToString: @"Torrent"] )
542       {
543           [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
544       }
545       else
546       {
547           [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
548       }
549   }
550}
551
552- (void) updatePopUp
553{
554    // Get the icon for the folder
555    NSImage * image32 = [[NSWorkspace sharedWorkspace] iconForFile:
556                fDownloadFolder];
557    NSImage * image16 = [[NSImage alloc] initWithSize: NSMakeSize(16,16)];
558
559    // 32x32 -> 16x16 scaling
560    [image16 lockFocus];
561    [[NSGraphicsContext currentContext]
562        setImageInterpolation: NSImageInterpolationHigh];
563    [image32 drawInRect: NSMakeRect(0,0,16,16)
564        fromRect: NSMakeRect(0,0,32,32) operation: NSCompositeCopy
565        fraction: 1.0];
566    [image16 unlockFocus];
567
568    // Update the menu item
569    NSMenuItem * menuItem = (NSMenuItem *) [fFolderPopUp itemAtIndex: 0];
570    [menuItem setTitle: [fDownloadFolder lastPathComponent]];
571    [menuItem setImage: image16];
572
573    [image16 release];
574}
575
576@end
Note: See TracBrowser for help on using the repository browser.