source: trunk/macosx/PrefsController.m @ 920

Last change on this file since 920 was 920, checked in by joshe, 15 years ago

Merge nat-traversal branch to trunk.

  • Property svn:keywords set to Date Rev Author Id
File size: 30.2 KB
Line 
1/******************************************************************************
2 * $Id: PrefsController.m 920 2006-09-25 18:37:45Z 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 "UKKQueue.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_BANDWIDTH   @"Bandwidth"
43#define TOOLBAR_NETWORK     @"Network"
44
45@interface PrefsController (Private)
46
47- (void) showGeneralPref: (id) sender;
48- (void) showTransfersPref: (id) sender;
49- (void) showBandwidthPref: (id) sender;
50- (void) showNetworkPref: (id) sender;
51
52- (void) setPrefView: (NSView *) view;
53
54- (void) folderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
55- (void) updatePopUp;
56
57- (void) importFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
58- (void) updateImportPopUp;
59
60@end
61
62@implementation PrefsController
63
64- (id) initWithWindowNibName: (NSString *) name handle: (tr_handle_t *) handle
65{
66    if ((self = [self initWithWindowNibName: name]))
67    {
68        fDefaults = [NSUserDefaults standardUserDefaults];
69        fHandle = handle;
70       
71        [[self window] update]; //make sure nib is loaded right away
72    }
73    return self;
74}
75
76- (void) dealloc
77{
78    [fNatStatusTimer invalidate];
79
80    [fDownloadFolder release];
81    [fImportFolder release];
82    [super dealloc];
83}
84
85- (void) awakeFromNib
86{
87    fToolbar = [[NSToolbar alloc] initWithIdentifier: @"Preferences Toolbar"];
88    [fToolbar setDelegate: self];
89    [fToolbar setAllowsUserCustomization: NO];
90    [[self window] setToolbar: fToolbar];
91    [fToolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
92    [fToolbar setSizeMode: NSToolbarSizeModeRegular];
93
94    [fToolbar setSelectedItemIdentifier: TOOLBAR_GENERAL];
95    [self showGeneralPref: nil];
96   
97    //set download folder
98    NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
99    fDownloadFolder = [[[fDefaults stringForKey: @"DownloadFolder"] stringByExpandingTildeInPath] retain];
100    if ([downloadChoice isEqualToString: @"Constant"])
101        [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
102    else if ([downloadChoice isEqualToString: @"Torrent"])
103        [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
104    else
105        [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
106    [self updatePopUp];
107   
108    //set auto import
109    fImportFolder = [[[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath] retain];
110    [self updateImportPopUp];
111 
112    BOOL autoImport = [fDefaults boolForKey: @"AutoImport"];
113    [fAutoImportCheck setState: autoImport];
114    [fImportFolderPopUp setEnabled: autoImport];
115   
116    if (autoImport)
117        [[UKKQueue sharedFileWatcher] addPath: fImportFolder];
118   
119    //set auto size
120    [fAutoSizeCheck setState: [fDefaults boolForKey: @"AutoSize"]];
121   
122    //set bind port
123    int bindPort = [fDefaults integerForKey: @"BindPort"];
124    [fPortField setIntValue: bindPort];
125    tr_setBindPort(fHandle, bindPort);
126   
127    //set NAT
128    BOOL natShouldEnable = [fDefaults boolForKey: @"NatTraversal"];
129    if (natShouldEnable)
130        tr_natTraversalEnable(fHandle);
131    [fNatCheck setState: natShouldEnable];
132   
133    fNatStatus = -1;
134    [self updateNatStatus];
135    fNatStatusTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0 target: self
136                        selector: @selector(updateNatStatus) userInfo: nil repeats: YES];
137   
138    //checks for old version upload speed of -1
139    if ([fDefaults integerForKey: @"UploadLimit"] < 0)
140    {
141        [fDefaults setInteger: 20 forKey: @"UploadLimit"];
142        [fDefaults setBool: NO forKey: @"CheckUpload"];
143    }
144   
145    //set upload limit
146    BOOL checkUpload = [fDefaults boolForKey: @"CheckUpload"];
147    int uploadLimit = [fDefaults integerForKey: @"UploadLimit"];
148   
149    [fUploadCheck setState: checkUpload];
150    [fUploadField setIntValue: uploadLimit];
151    [fUploadField setEnabled: checkUpload];
152
153        //set download limit
154    BOOL checkDownload = [fDefaults boolForKey: @"CheckDownload"];
155    int downloadLimit = [fDefaults integerForKey: @"DownloadLimit"];
156   
157    [fDownloadCheck setState: checkDownload];
158    [fDownloadField setIntValue: downloadLimit];
159    [fDownloadField setEnabled: checkDownload];
160   
161    //set speed limit
162    int speedLimitUploadLimit = [fDefaults integerForKey: @"SpeedLimitUploadLimit"];
163    [fSpeedLimitUploadField setIntValue: speedLimitUploadLimit];
164   
165    int speedLimitDownloadLimit = [fDefaults integerForKey: @"SpeedLimitDownloadLimit"];
166    [fSpeedLimitDownloadField setIntValue: speedLimitDownloadLimit];
167   
168    //actually set bandwidth limits
169    if ([fDefaults boolForKey: @"SpeedLimit"])
170    {
171        tr_setUploadLimit(fHandle, speedLimitUploadLimit);
172        tr_setDownloadLimit(fHandle, speedLimitDownloadLimit);
173    }
174    else
175    {
176        tr_setUploadLimit(fHandle, checkUpload ? uploadLimit : -1);
177        tr_setDownloadLimit(fHandle, checkDownload ? downloadLimit : -1);
178    }
179   
180    //set auto speed limit
181    BOOL speedLimitAuto = [fDefaults boolForKey: @"SpeedLimitAuto"];
182    [fSpeedLimitAutoCheck setState: speedLimitAuto];
183   
184    int speedLimitAutoOnHour = [fDefaults integerForKey: @"SpeedLimitAutoOnHour"];
185    [fSpeedLimitAutoOnField setStringValue: [NSString stringWithFormat: @"%02d", speedLimitAutoOnHour]];
186    [fSpeedLimitAutoOnField setEnabled: speedLimitAuto];
187   
188    int speedLimitAutoOffHour = [fDefaults integerForKey: @"SpeedLimitAutoOffHour"];
189    [fSpeedLimitAutoOffField setStringValue: [NSString stringWithFormat: @"%02d", speedLimitAutoOffHour]];
190    [fSpeedLimitAutoOffField setEnabled: speedLimitAuto];
191   
192    //set ratio limit
193    BOOL ratioCheck = [fDefaults boolForKey: @"RatioCheck"];
194    [fRatioCheck setState: ratioCheck];
195    [fRatioField setEnabled: ratioCheck];
196    [fRatioField setFloatValue: [fDefaults floatForKey: @"RatioLimit"]];
197   
198    //set remove and quit prompts
199    BOOL isQuitCheck = [fDefaults boolForKey: @"CheckQuit"],
200        isRemoveCheck = [fDefaults boolForKey: @"CheckRemove"];
201   
202    [fQuitCheck setState: isQuitCheck];
203    [fRemoveCheck setState: isRemoveCheck];
204   
205    [fQuitDownloadingCheck setState: [fDefaults boolForKey: @"CheckQuitDownloading"]];
206    [fQuitDownloadingCheck setEnabled: isQuitCheck];
207    [fRemoveDownloadingCheck setState: [fDefaults boolForKey: @"CheckRemoveDownloading"]];
208    [fRemoveDownloadingCheck setEnabled: isRemoveCheck];
209
210    //set dock badging
211    [fBadgeDownloadRateCheck setState: [fDefaults boolForKey: @"BadgeDownloadRate"]];
212    [fBadgeUploadRateCheck setState: [fDefaults boolForKey: @"BadgeUploadRate"]];
213   
214    //set play sound
215    NSMutableArray * sounds = [NSMutableArray array];
216    NSEnumerator * soundEnumerator,
217                * soundDirectoriesEnumerator = [[NSArray arrayWithObjects: @"System/Library/Sounds",
218                        [NSHomeDirectory() stringByAppendingPathComponent: @"Library/Sounds"], nil] objectEnumerator];
219    NSString * soundPath, * sound;
220   
221    //get list of all sounds and sort alphabetically
222    while ((soundPath = [soundDirectoriesEnumerator nextObject]))
223        if (soundEnumerator = [[NSFileManager defaultManager] enumeratorAtPath: soundPath])
224            while ((sound = [soundEnumerator nextObject]))
225            {
226                sound = [sound stringByDeletingPathExtension];
227                if ([NSSound soundNamed: sound])
228                    [sounds addObject: sound];
229            }
230   
231    [sounds sortUsingSelector: @selector(caseInsensitiveCompare:)];
232   
233    //set download sound
234    [fDownloadSoundPopUp removeAllItems];
235    [fDownloadSoundPopUp addItemsWithTitles: sounds];
236   
237    BOOL playDownloadSound = [fDefaults boolForKey: @"PlayDownloadSound"];
238    [fPlayDownloadSoundCheck setState: playDownloadSound];
239    [fDownloadSoundPopUp setEnabled: playDownloadSound];
240   
241    int downloadSoundIndex = [fDownloadSoundPopUp indexOfItemWithTitle: [fDefaults stringForKey: @"DownloadSound"]];
242    if (downloadSoundIndex >= 0)
243        [fDownloadSoundPopUp selectItemAtIndex: downloadSoundIndex];
244    else
245        [fDefaults setObject: [fDownloadSoundPopUp titleOfSelectedItem] forKey: @"DownloadSound"];
246   
247    //set seeding sound
248    [fSeedingSoundPopUp removeAllItems];
249    [fSeedingSoundPopUp addItemsWithTitles: sounds];
250   
251    BOOL playSeedingSound = [fDefaults boolForKey: @"PlaySeedingSound"];
252    [fPlaySeedingSoundCheck setState: playSeedingSound];
253    [fSeedingSoundPopUp setEnabled: playSeedingSound];
254   
255    int seedingSoundIndex = [fDownloadSoundPopUp indexOfItemWithTitle: [fDefaults stringForKey: @"SeedingSound"]];
256    if (seedingSoundIndex >= 0)
257        [fSeedingSoundPopUp selectItemAtIndex: seedingSoundIndex];
258    else
259        [fDefaults setObject: [fSeedingSoundPopUp titleOfSelectedItem] forKey: @"SeedingSound"];
260   
261    //set start settings
262    BOOL useQueue = [fDefaults boolForKey: @"Queue"];
263    [fQueueCheck setState: useQueue];
264    [fQueueNumberField setEnabled: useQueue];
265    [fQueueNumberField setIntValue: [fDefaults integerForKey: @"QueueDownloadNumber"]];
266   
267    [fStartAtOpenCheck setState: [fDefaults boolForKey: @"StartAtOpen"]];
268   
269    //set private torrents
270    BOOL copyTorrents = [fDefaults boolForKey: @"SavePrivateTorrent"];
271    [fCopyTorrentCheck setState: copyTorrents];
272   
273    [fDeleteOriginalTorrentCheck setEnabled: copyTorrents];
274    [fDeleteOriginalTorrentCheck setState: [fDefaults boolForKey: @"DeleteOriginalTorrent"]];
275
276    //set update check
277    NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
278    if ([updateCheck isEqualToString: @"Weekly"])
279        [fUpdatePopUp selectItemAtIndex: UPDATE_WEEKLY];
280    else if ([updateCheck isEqualToString: @"Never"])
281        [fUpdatePopUp selectItemAtIndex: UPDATE_NEVER];
282    else
283        [fUpdatePopUp selectItemAtIndex: UPDATE_DAILY];
284}
285
286- (NSToolbarItem *) toolbar: (NSToolbar *) t itemForItemIdentifier:
287    (NSString *) ident willBeInsertedIntoToolbar: (BOOL) flag
288{
289    NSToolbarItem * item;
290    item = [[NSToolbarItem alloc] initWithItemIdentifier: ident];
291
292    if ([ident isEqualToString: TOOLBAR_GENERAL])
293    {
294        [item setLabel: TOOLBAR_GENERAL];
295        [item setImage: [NSImage imageNamed: @"Preferences.png"]];
296        [item setTarget: self];
297        [item setAction: @selector(showGeneralPref:)];
298    }
299    else if ([ident isEqualToString: TOOLBAR_TRANSFERS])
300    {
301        [item setLabel: TOOLBAR_TRANSFERS];
302        [item setImage: [NSImage imageNamed: @"Transfers.png"]];
303        [item setTarget: self];
304        [item setAction: @selector(showTransfersPref:)];
305    }
306    else if ([ident isEqualToString: TOOLBAR_BANDWIDTH])
307    {
308        [item setLabel: TOOLBAR_BANDWIDTH];
309        [item setImage: [NSImage imageNamed: @"Bandwidth.png"]];
310        [item setTarget: self];
311        [item setAction: @selector(showBandwidthPref:)];
312    }
313    else if ([ident isEqualToString: TOOLBAR_NETWORK])
314    {
315        [item setLabel: TOOLBAR_NETWORK];
316        [item setImage: [NSImage imageNamed: @"Network.png"]];
317        [item setTarget: self];
318        [item setAction: @selector(showNetworkPref:)];
319    }
320    else
321    {
322        [item release];
323        return nil;
324    }
325
326    return item;
327}
328
329- (NSArray *) toolbarSelectableItemIdentifiers: (NSToolbar *) toolbar
330{
331    return [self toolbarDefaultItemIdentifiers: toolbar];
332}
333
334- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
335{
336    return [self toolbarAllowedItemIdentifiers: toolbar];
337}
338
339- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
340{
341    return [NSArray arrayWithObjects:
342            TOOLBAR_GENERAL, TOOLBAR_TRANSFERS,
343            TOOLBAR_BANDWIDTH, TOOLBAR_NETWORK, nil];
344}
345
346- (void) setPort: (id) sender
347{
348    int bindPort = [sender intValue];
349    if (![[NSString stringWithInt: bindPort] isEqualToString: [sender stringValue]]
350            || bindPort < MIN_PORT || bindPort > MAX_PORT)
351    {
352        NSBeep();
353        bindPort = [fDefaults integerForKey: @"BindPort"];
354        [sender setIntValue: bindPort];
355    }
356    else
357    {
358        tr_setBindPort(fHandle, bindPort);
359        [fDefaults setInteger: bindPort forKey: @"BindPort"];
360       
361        [self updateNatStatus];
362    }
363}
364
365- (void) setNat: (id) sender
366{
367    BOOL enable = [sender state] == NSOnState;
368    enable ? tr_natTraversalEnable(fHandle) : tr_natTraversalDisable(fHandle);
369    [fDefaults setBool: enable forKey: @"NatTraversal"];
370   
371    [self updateNatStatus];
372}
373
374- (void) updateNatStatus
375{
376    int status = tr_natTraversalStatus(fHandle);
377    if (fNatStatus == status)
378        return;
379    fNatStatus = status;
380   
381    if (status == 2)
382    {
383        [fNatStatusField setStringValue: @"Ports successfully mapped"];
384        [fNatStatusImage setImage: [NSImage imageNamed: @"Check.png"]];
385    }
386    else if (status == 3 || status == 4)
387    {
388        [fNatStatusField setStringValue: @"Error mapping ports"];
389        [fNatStatusImage setImage: [NSImage imageNamed: @"Error.tiff"]];
390    }
391    else
392    {
393        [fNatStatusField setStringValue: @""];
394        [fNatStatusImage setImage: nil];
395    }
396}
397
398- (void) setLimit: (id) sender
399{
400    NSString * key;
401    NSButton * check;
402    NSString * type;
403    if (sender == fUploadField)
404    {
405        key = @"UploadLimit";
406        check = fUploadCheck;
407        type = @"Upload";
408    }
409    else
410    {
411        key = @"DownloadLimit";
412        check = fDownloadCheck;
413        type = @"Download";
414    }
415
416    int limit = [sender intValue];
417    if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%d", limit]] || limit < 0)
418    {
419        NSBeep();
420        limit = [fDefaults integerForKey: key];
421        [sender setIntValue: limit];
422    }
423    else
424    {
425        if (![fDefaults boolForKey: @"SpeedLimit"])
426        {
427            int realLimit = [check state] ? limit : -1;
428            if (sender == fUploadField)
429                tr_setUploadLimit(fHandle, realLimit);
430            else
431                tr_setDownloadLimit(fHandle, realLimit);
432        }
433       
434        [fDefaults setInteger: limit forKey: key];
435    }
436   
437    NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
438                                    [NSNumber numberWithBool: [check state]], @"Enable",
439                                    [NSNumber numberWithInt: limit], @"Limit",
440                                    type, @"Type", nil];
441    [[NSNotificationCenter defaultCenter] postNotificationName: @"LimitGlobalChange" object: dict];
442}
443
444- (void) setLimitCheck: (id) sender
445{
446    NSString * key;
447    NSTextField * field;
448    if (sender == fUploadCheck)
449    {
450        key = @"CheckUpload";
451        field = fUploadField;
452    }
453    else
454    {
455        key = @"CheckDownload";
456        field = fDownloadField;
457    }
458   
459    BOOL check = [sender state] == NSOnState;
460    [self setLimit: field];
461    [field setEnabled: check];
462   
463    [fDefaults setBool: check forKey: key];
464}
465
466- (void) setLimitEnabled: (BOOL) enable type: (NSString *) type
467{
468    NSButton * check = [type isEqualToString: @"Upload"] ? fUploadCheck : fDownloadCheck;
469    [check setState: enable ? NSOnState : NSOffState];
470    [self setLimitCheck: check];
471}
472
473- (void) setQuickLimit: (int) limit type: (NSString *) type
474{
475    NSButton * check;
476    if ([type isEqualToString: @"Upload"])
477    {
478        [fUploadField setIntValue: limit];
479        check = fUploadCheck;
480    }
481    else
482    {
483        [fDownloadField setIntValue: limit];
484        check = fDownloadCheck;
485    }
486    [check setState: NSOnState];
487    [self setLimitCheck: check];
488}
489
490- (void) enableSpeedLimit: (BOOL) enable
491{
492    if ([fDefaults boolForKey: @"SpeedLimit"] != enable)
493    {
494        [fDefaults setBool: enable forKey: @"SpeedLimit"];
495       
496        if (enable)
497        {
498            tr_setUploadLimit(fHandle, [fDefaults integerForKey: @"SpeedLimitUploadLimit"]);
499            tr_setDownloadLimit(fHandle, [fDefaults integerForKey: @"SpeedLimitDownloadLimit"]);
500        }
501        else
502        {
503            tr_setUploadLimit(fHandle, [fUploadCheck state] ? [fDefaults integerForKey: @"UploadLimit"] : -1);
504            tr_setDownloadLimit(fHandle, [fDownloadCheck state] ? [fDefaults integerForKey: @"DownloadLimit"] : -1);
505        }
506    }
507}
508
509- (void) setSpeedLimit: (id) sender
510{
511    NSString * key = sender == fSpeedLimitUploadField ? @"SpeedLimitUploadLimit" : @"SpeedLimitDownloadLimit";
512
513    int limit = [sender intValue];
514    if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%d", limit]] || limit < 0)
515    {
516        NSBeep();
517        limit = [fDefaults integerForKey: key];
518        [sender setIntValue: limit];
519    }
520    else
521    {
522        if ([fDefaults boolForKey: @"SpeedLimit"])
523        {
524            if (sender == fSpeedLimitUploadField)
525                tr_setUploadLimit(fHandle, limit);
526            else
527                tr_setDownloadLimit(fHandle, limit);
528        }
529       
530        [fDefaults setInteger: limit forKey: key];
531    }
532}
533
534- (void) setAutoSpeedLimitCheck: (id) sender
535{
536    BOOL check = [sender state] == NSOnState;
537   
538    [fDefaults setBool: check forKey: @"SpeedLimitAuto"];
539
540    [self setAutoSpeedLimitHour: fSpeedLimitAutoOnField];
541    [fSpeedLimitAutoOnField setEnabled: check];
542   
543    [self setAutoSpeedLimitHour: fSpeedLimitAutoOffField];
544    [fSpeedLimitAutoOffField setEnabled: check];
545}
546
547- (void) setAutoSpeedLimitHour: (id) sender
548{
549    NSString * key = (sender == fSpeedLimitAutoOnField) ? @"SpeedLimitAutoOnHour" : @"SpeedLimitAutoOffHour";
550
551    int hour = [sender intValue];
552   
553    //allow numbers under ten in the format 0x
554    if (!([[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%d", hour]]
555        || [[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%02d", hour]]) || hour < 0 || hour > 23
556        || [fSpeedLimitAutoOnField intValue] == [fSpeedLimitAutoOffField intValue])
557    {
558        NSBeep();
559        hour = [fDefaults integerForKey: key];
560        [sender setStringValue: [NSString stringWithFormat: @"%02d", hour]];
561    }
562    else
563        [fDefaults setInteger: hour forKey: key];
564   
565    [sender setStringValue: [NSString stringWithFormat: @"%02d", hour]]; //ensure number has 2 digits
566   
567    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoSpeedLimitChange" object: self];
568}
569
570- (void) setRatio: (id) sender
571{
572    float ratioLimit = [sender floatValue];
573    if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%.2f", ratioLimit]]
574            || ratioLimit < 0)
575    {
576        NSBeep();
577        ratioLimit = [fDefaults floatForKey: @"RatioLimit"];
578        [sender setFloatValue: ratioLimit];
579    }
580    else
581        [fDefaults setFloat: ratioLimit forKey: @"RatioLimit"];
582   
583    NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:
584                                [NSNumber numberWithBool: [fRatioCheck state]], @"Enable",
585                                [NSNumber numberWithFloat: ratioLimit], @"Ratio", nil];
586    [[NSNotificationCenter defaultCenter] postNotificationName: @"RatioGlobalChange" object: dict];
587}
588
589- (void) setRatioCheck: (id) sender
590{
591    BOOL check = [sender state] == NSOnState;
592    [self setRatio: fRatioField];
593    [fRatioField setEnabled: check];
594   
595    [fDefaults setBool: check forKey: @"RatioCheck"];
596}
597
598- (void) setRatioEnabled: (BOOL) enable
599{
600    int state = enable ? NSOnState : NSOffState;
601   
602    [fRatioCheck setState: state];
603    [self setRatioCheck: fRatioCheck];
604}
605
606- (void) setQuickRatio: (float) ratioLimit
607{
608    [fRatioField setFloatValue: ratioLimit];
609   
610    [fRatioCheck setState: NSOnState];
611    [self setRatioCheck: fRatioCheck];
612}
613
614- (void) setShowMessage: (id) sender
615{
616    BOOL state = [sender state];
617
618    if (sender == fQuitCheck)
619    {
620        [fDefaults setBool: state forKey: @"CheckQuit"];
621        [fQuitDownloadingCheck setEnabled: state];
622    }
623    else if (sender == fRemoveCheck)
624    {
625        [fDefaults setBool: state forKey: @"CheckRemove"];
626        [fRemoveDownloadingCheck setEnabled: state];
627    }
628    if (sender == fQuitDownloadingCheck)
629        [fDefaults setBool: state forKey: @"CheckQuitDownloading"];
630    else if (sender == fRemoveDownloadingCheck)
631        [fDefaults setBool: state forKey: @"CheckRemoveDownloading"];
632    else;
633}
634
635- (void) setBadge: (id) sender
636{   
637    if (sender == fBadgeDownloadRateCheck)
638        [fDefaults setBool: [sender state] forKey: @"BadgeDownloadRate"];
639    else if (sender == fBadgeUploadRateCheck)
640        [fDefaults setBool: [sender state] forKey: @"BadgeUploadRate"];
641    else;
642   
643    [[NSNotificationCenter defaultCenter] postNotificationName: @"DockBadgeChange" object: self];
644}
645
646- (void) setPlaySound: (id) sender
647{
648    BOOL state = [sender state];
649
650    if (sender == fPlayDownloadSoundCheck)
651    {
652        [fDownloadSoundPopUp setEnabled: state];
653        [fDefaults setBool: state forKey: @"PlayDownloadSound"];
654    }
655    else if (sender == fPlaySeedingSoundCheck)
656    {
657        [fSeedingSoundPopUp setEnabled: state];
658        [fDefaults setBool: state forKey: @"PlaySeedingSound"];
659    }
660    else;
661}
662
663- (void) setSound: (id) sender
664{
665    //play sound when selecting
666    NSString * soundName = [sender titleOfSelectedItem];
667    NSSound * sound;
668    if ((sound = [NSSound soundNamed: soundName]))
669        [sound play];
670
671    if (sender == fDownloadSoundPopUp)
672        [fDefaults setObject: soundName forKey: @"DownloadSound"];
673    else if (sender == fSeedingSoundPopUp)
674        [fDefaults setObject: soundName forKey: @"SeedingSound"];
675    else;
676}
677
678- (void) setUpdate: (id) sender
679{
680    int index = [fUpdatePopUp indexOfSelectedItem];
681    NSTimeInterval seconds;
682    if (index == UPDATE_DAILY)
683    {
684        [fDefaults setObject: @"Daily" forKey: @"UpdateCheck"];
685        seconds = 86400;
686    }
687    else if (index == UPDATE_WEEKLY)
688    {
689        [fDefaults setObject: @"Weekly" forKey: @"UpdateCheck"];
690        seconds = 604800;
691    }
692    else
693    {
694        [fDefaults setObject: @"Never" forKey: @"UpdateCheck"];
695        seconds = 0;
696    }
697
698    [fDefaults setInteger: seconds forKey: @"SUScheduledCheckInterval"];
699    [fUpdater scheduleCheckWithInterval: seconds];
700}
701
702- (void) setStartAtOpen: (id) sender
703{
704    [fDefaults setBool: [sender state] == NSOnState forKey: @"StartAtOpen"];
705}
706
707- (void) setUseQueue: (id) sender
708{
709    BOOL useQueue = [sender state] == NSOnState;
710   
711    [fDefaults setBool: useQueue forKey: @"Queue"];
712    [self setQueueNumber: fQueueNumberField];
713    [fQueueNumberField setEnabled: useQueue];
714}
715
716- (void) setQueueNumber: (id) sender
717{
718    int queueNumber = [sender intValue];
719    if (![[sender stringValue] isEqualToString: [NSString stringWithInt: queueNumber]] || queueNumber < 1)
720    {
721        NSBeep();
722        queueNumber = [fDefaults integerForKey: @"QueueDownloadNumber"];
723        [sender setIntValue: queueNumber];
724    }
725    else
726        [fDefaults setInteger: queueNumber forKey: @"QueueDownloadNumber"];
727   
728    [[NSNotificationCenter defaultCenter] postNotificationName: @"GlobalStartSettingChange" object: self];
729}
730
731- (void) setMoveTorrent: (id) sender
732{
733    int state = [sender state];
734    if (sender == fCopyTorrentCheck)
735    {
736        [fDefaults setBool: state forKey: @"SavePrivateTorrent"];
737       
738        [fDeleteOriginalTorrentCheck setEnabled: state];
739        if (state == NSOffState)
740        {
741            [fDeleteOriginalTorrentCheck setState: NSOffState];
742            [fDefaults setBool: NO forKey: @"DeleteOriginalTorrent"];
743        }
744    }
745    else
746        [fDefaults setBool: state forKey: @"DeleteOriginalTorrent"];
747}
748
749- (void) setDownloadLocation: (id) sender
750{
751    //Download folder
752    switch ([fFolderPopUp indexOfSelectedItem])
753    {
754        case DOWNLOAD_FOLDER:
755            [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
756            break;
757        case DOWNLOAD_TORRENT:
758            [fDefaults setObject: @"Torrent" forKey: @"DownloadChoice"];
759            break;
760        case DOWNLOAD_ASK:
761            [fDefaults setObject: @"Ask" forKey: @"DownloadChoice"];
762            break;
763    }
764}
765
766- (void) checkUpdate
767{
768    [fUpdater checkForUpdates: nil];
769}
770
771- (void) folderSheetShow: (id) sender
772{
773    NSOpenPanel * panel = [NSOpenPanel openPanel];
774
775    [panel setPrompt: @"Select"];
776    [panel setAllowsMultipleSelection: NO];
777    [panel setCanChooseFiles: NO];
778    [panel setCanChooseDirectories: YES];
779    [panel setCanCreateDirectories: YES];
780
781    [panel beginSheetForDirectory: nil file: nil types: nil
782        modalForWindow: [self window] modalDelegate: self didEndSelector:
783        @selector(folderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
784}
785
786- (void) setAutoImport: (id) sender
787{
788    int state = [fAutoImportCheck state];
789    [fDefaults setBool: state forKey: @"AutoImport"];
790    [fImportFolderPopUp setEnabled: state];
791   
792    if (state == NSOnState)
793        [[UKKQueue sharedFileWatcher] addPath: fImportFolder];
794    else
795        [[UKKQueue sharedFileWatcher] removePathFromQueue: fImportFolder];
796   
797    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoImportSettingChange" object: self];
798}
799
800- (void) importFolderSheetShow: (id) sender
801{
802    NSOpenPanel * panel = [NSOpenPanel openPanel];
803
804    [panel setPrompt: @"Select"];
805    [panel setAllowsMultipleSelection: NO];
806    [panel setCanChooseFiles: NO];
807    [panel setCanChooseDirectories: YES];
808    [panel setCanCreateDirectories: YES];
809
810    [panel beginSheetForDirectory: nil file: nil types: nil
811        modalForWindow: [self window] modalDelegate: self didEndSelector:
812        @selector(importFolderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
813}
814
815- (void) setAutoSize: (id) sender
816{
817    [fDefaults setBool: [sender state] forKey: @"AutoSize"];
818   
819    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoSizeSettingChange" object: self];
820}
821
822- (void) helpForNetwork: (id) sender
823{
824    [[NSHelpManager sharedHelpManager] openHelpAnchor: @"PortForwarding"
825        inBook: [[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleHelpBookName"]];
826}
827
828@end
829
830@implementation PrefsController (Private)
831
832- (void) showGeneralPref: (id) sender
833{
834    [self setPrefView: fGeneralView];
835}
836
837- (void) showTransfersPref: (id) sender
838{
839    [self setPrefView: fTransfersView];
840}
841
842- (void) showBandwidthPref: (id) sender
843{
844    [self setPrefView: fBandwidthView];
845}
846
847- (void) showNetworkPref: (id) sender
848{
849    [self setPrefView: fNetworkView];
850}
851
852- (void) setPrefView: (NSView *) view
853{
854    NSWindow * window = [self window];
855   
856    if ([window contentView] == view)
857        return;
858   
859    NSRect windowRect = [window frame];
860    int difference = [view frame].size.height - [[window contentView] frame].size.height;
861    windowRect.origin.y -= difference;
862    windowRect.size.height += difference;
863
864    [window setTitle: [fToolbar selectedItemIdentifier]];
865   
866    [view setHidden: YES];
867    [window setContentView: view];
868    [window setFrame: windowRect display: YES animate: YES];
869    [view setHidden: NO];
870}
871
872- (void) folderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info
873{
874    if (code == NSOKButton)
875    {
876        [fDownloadFolder release];
877        fDownloadFolder = [[[openPanel filenames] objectAtIndex: 0] retain];
878       
879        [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
880        [fDefaults setObject: fDownloadFolder forKey: @"DownloadFolder"];
881        [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
882       
883        [self updatePopUp];
884    }
885    else
886    {
887        //reset if cancelled
888        NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
889        if ([downloadChoice isEqualToString: @"Constant"])
890            [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
891        else if ([downloadChoice isEqualToString: @"Torrent"])
892            [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
893        else
894            [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
895    }
896}
897
898- (void) updatePopUp
899{
900    //get and resize the icon
901    NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile: fDownloadFolder];
902    [icon setScalesWhenResized: YES];
903    [icon setSize: NSMakeSize(16.0, 16.0)];
904
905    //update menu item
906    NSMenuItem * menuItem = (NSMenuItem *) [fFolderPopUp itemAtIndex: 0];
907    [menuItem setTitle: [fDownloadFolder lastPathComponent]];
908    [menuItem setImage: icon];
909}
910
911- (void) importFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info
912{
913    if (code == NSOKButton)
914    {
915        UKKQueue * sharedQueue = [UKKQueue sharedFileWatcher];
916        [sharedQueue removePathFromQueue: fImportFolder];
917       
918        [fImportFolder release];
919        fImportFolder = [[[openPanel filenames] objectAtIndex: 0] retain];
920       
921        [fDefaults setObject: fImportFolder forKey: @"AutoImportDirectory"];
922       
923        [self updateImportPopUp];
924       
925        [sharedQueue addPath: fImportFolder];
926       
927        [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoImportSettingChange" object: self];
928    }
929    [fImportFolderPopUp selectItemAtIndex: 0];
930}
931
932- (void) updateImportPopUp
933{
934    //get and resize the icon
935    NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile: fImportFolder];
936    [icon setScalesWhenResized: YES];
937    [icon setSize: NSMakeSize(16.0, 16.0)];
938
939    //update menu item
940    NSMenuItem * menuItem = (NSMenuItem *) [fImportFolderPopUp itemAtIndex: 0];
941    [menuItem setTitle: [fImportFolder lastPathComponent]];
942    [menuItem setImage: icon];
943}
944
945@end
Note: See TracBrowser for help on using the repository browser.