source: trunk/macosx/PrefsController.m @ 1058

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

don't autovalidate toolbar items that never change

  • Property svn:keywords set to Date Rev Author Id
File size: 19.1 KB
Line 
1/******************************************************************************
2 * $Id: PrefsController.m 1058 2006-11-06 02:05:32Z livings124 $
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 DOWNLOAD_FOLDER     0
30#define DOWNLOAD_TORRENT    2
31#define DOWNLOAD_ASK        3
32
33#define UPDATE_DAILY    0
34#define UPDATE_WEEKLY   1
35#define UPDATE_NEVER    2
36
37#define TOOLBAR_GENERAL     @"TOOLBAR_GENERAL"
38#define TOOLBAR_TRANSFERS   @"TOOLBAR_TRANSFERS"
39#define TOOLBAR_BANDWIDTH   @"TOOLBAR_BANDWIDTH"
40#define TOOLBAR_NETWORK     @"TOOLBAR_NETWORK"
41
42@interface PrefsController (Private)
43
44- (void) setPrefView: (id) sender;
45
46- (void) folderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
47- (void) incompleteFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
48- (void) importFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info;
49
50@end
51
52@implementation PrefsController
53
54- (id) initWithWindowNibName: (NSString *) name handle: (tr_handle_t *) handle
55{
56    if ((self = [self initWithWindowNibName: name]))
57    {
58        fDefaults = [NSUserDefaults standardUserDefaults];
59        fHandle = handle;
60       
61        //checks for old version upload speed of -1
62        if ([fDefaults integerForKey: @"UploadLimit"] < 0)
63        {
64            [fDefaults setInteger: 20 forKey: @"UploadLimit"];
65            [fDefaults setBool: NO forKey: @"CheckUpload"];
66        }
67       
68        //set auto import
69        if ([fDefaults boolForKey: @"AutoImport"])
70            [[UKKQueue sharedFileWatcher] addPath:
71                [[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath]];
72       
73        //set bind port
74        int bindPort = [fDefaults integerForKey: @"BindPort"];
75        tr_setBindPort(fHandle, bindPort);
76       
77        //set NAT
78        if ([fDefaults boolForKey: @"NatTraversal"])
79            tr_natTraversalEnable(fHandle);
80       
81        //actually set bandwidth limits
82        [self applySpeedSettings: nil];
83       
84        //set play sound
85        NSMutableArray * sounds = [NSMutableArray array];
86        NSEnumerator * soundEnumerator,
87                    * soundDirectoriesEnumerator = [[NSArray arrayWithObjects: @"System/Library/Sounds",
88                            [NSHomeDirectory() stringByAppendingPathComponent: @"Library/Sounds"], nil] objectEnumerator];
89        NSString * soundPath, * sound;
90       
91        //get list of all sounds and sort alphabetically
92        while ((soundPath = [soundDirectoriesEnumerator nextObject]))
93            if (soundEnumerator = [[NSFileManager defaultManager] enumeratorAtPath: soundPath])
94                while ((sound = [soundEnumerator nextObject]))
95                {
96                    sound = [sound stringByDeletingPathExtension];
97                    if ([NSSound soundNamed: sound])
98                        [sounds addObject: sound];
99                }
100       
101        fSounds = [[sounds sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)] retain];
102    }
103    return self;
104}
105
106- (void) dealloc
107{
108    if (fNatStatusTimer)
109        [fNatStatusTimer invalidate];
110    [fSounds release];
111   
112    [super dealloc];
113}
114
115- (void) awakeFromNib
116{
117    fToolbar = [[NSToolbar alloc] initWithIdentifier: @"Preferences Toolbar"];
118    [fToolbar setDelegate: self];
119    [fToolbar setAllowsUserCustomization: NO];
120    [[self window] setToolbar: fToolbar];
121    [fToolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
122    [fToolbar setSizeMode: NSToolbarSizeModeRegular];
123
124    [fToolbar setSelectedItemIdentifier: TOOLBAR_GENERAL];
125    [self setPrefView: nil];
126   
127    //set download folder
128    NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
129    if ([downloadChoice isEqualToString: @"Constant"])
130        [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
131    else if ([downloadChoice isEqualToString: @"Torrent"])
132        [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
133    else
134        [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
135   
136    [self updatePortStatus];
137   
138    fNatStatus = -1;
139    [self updateNatStatus];
140    fNatStatusTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0 target: self
141                        selector: @selector(updateNatStatus) userInfo: nil repeats: YES];
142
143    //set update check
144    NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"];
145    if ([updateCheck isEqualToString: @"Weekly"])
146        [fUpdatePopUp selectItemAtIndex: UPDATE_WEEKLY];
147    else if ([updateCheck isEqualToString: @"Never"])
148        [fUpdatePopUp selectItemAtIndex: UPDATE_NEVER];
149    else
150        [fUpdatePopUp selectItemAtIndex: UPDATE_DAILY];
151}
152
153- (void) setUpdater: (SUUpdater *) updater
154{
155    fUpdater = updater;
156}
157
158- (NSToolbarItem *) toolbar: (NSToolbar *) toolbar itemForItemIdentifier: (NSString *) ident
159                    willBeInsertedIntoToolbar: (BOOL) flag
160{
161    NSToolbarItem * item;
162    item = [[NSToolbarItem alloc] initWithItemIdentifier: ident];
163
164    if ([ident isEqualToString: TOOLBAR_GENERAL])
165    {
166        [item setLabel: NSLocalizedString(@"General", "Preferences -> General toolbar item title")];
167        [item setImage: [NSImage imageNamed: @"Preferences.png"]];
168        [item setTarget: self];
169        [item setAction: @selector(setPrefView:)];
170        [item setAutovalidates: NO];
171    }
172    else if ([ident isEqualToString: TOOLBAR_TRANSFERS])
173    {
174        [item setLabel: NSLocalizedString(@"Transfers", "Preferences -> Transfers toolbar item title")];
175        [item setImage: [NSImage imageNamed: @"Transfers.png"]];
176        [item setTarget: self];
177        [item setAction: @selector(setPrefView:)];
178        [item setAutovalidates: NO];
179    }
180    else if ([ident isEqualToString: TOOLBAR_BANDWIDTH])
181    {
182        [item setLabel: NSLocalizedString(@"Bandwidth", "Preferences -> Bandwidth toolbar item title")];
183        [item setImage: [NSImage imageNamed: @"Bandwidth.png"]];
184        [item setTarget: self];
185        [item setAction: @selector(setPrefView:)];
186        [item setAutovalidates: NO];
187    }
188    else if ([ident isEqualToString: TOOLBAR_NETWORK])
189    {
190        [item setLabel: NSLocalizedString(@"Network", "Preferences -> Network toolbar item title")];
191        [item setImage: [NSImage imageNamed: @"Network.png"]];
192        [item setTarget: self];
193        [item setAction: @selector(setPrefView:)];
194        [item setAutovalidates: NO];
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: toolbar];
208}
209
210- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
211{
212    return [self toolbarAllowedItemIdentifiers: toolbar];
213}
214
215- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
216{
217    return [NSArray arrayWithObjects: TOOLBAR_GENERAL, TOOLBAR_TRANSFERS,
218                                        TOOLBAR_BANDWIDTH, TOOLBAR_NETWORK, nil];
219}
220
221- (void) setPort: (id) sender
222{
223    tr_setBindPort(fHandle, [fDefaults integerForKey: @"BindPort"]);
224    [self updateNatStatus];
225    [self updatePortStatus];
226}
227
228- (void) updatePortStatus
229{
230    PortChecker * portChecker = [[PortChecker alloc] initWithDelegate: self];
231
232    [fPortStatusField setStringValue: [NSLocalizedString(@"Checking port status",
233                                        "Preferences -> Network -> port status") stringByAppendingEllipsis]];
234    [fPortStatusImage setImage: nil];
235    [fPortStatusProgress startAnimation: self];
236       
237    [portChecker probePort: [fDefaults integerForKey: @"BindPort"]];
238}
239
240- (void) portCheckerDidFinishProbing: (PortChecker *) portChecker
241{
242    [fPortStatusProgress stopAnimation: self];
243    switch ([portChecker status])
244    {
245        case PORT_STATUS_OPEN:
246            [fPortStatusField setStringValue: NSLocalizedString(@"Port is open", "Preferences -> Network -> port status")];
247            [fPortStatusImage setImage: [NSImage imageNamed: @"GreenDot.tiff"]];
248            break;
249        case PORT_STATUS_STEALTH:
250            [fPortStatusField setStringValue: NSLocalizedString(@"Port is stealth", "Preferences -> Network -> port status")];
251            [fPortStatusImage setImage: [NSImage imageNamed: @"RedDot.tiff"]];
252            break;
253        case PORT_STATUS_CLOSED:
254            [fPortStatusField setStringValue: NSLocalizedString(@"Port is closed", "Preferences -> Network -> port status")];
255            [fPortStatusImage setImage: [NSImage imageNamed: @"RedDot.tiff"]];
256            break;
257        case PORT_STATUS_ERROR:
258            [fPortStatusField setStringValue: NSLocalizedString(@"Unable to check port status",
259                                                "Preferences -> Network -> port status")];
260            [fPortStatusImage setImage: [NSImage imageNamed: @"YellowDot.tiff"]];
261            break;
262    }
263    [portChecker release];
264}
265
266- (void) setNat: (id) sender
267{
268    [fDefaults boolForKey: @"NatTraversal"] ? tr_natTraversalEnable(fHandle) : tr_natTraversalDisable(fHandle);
269    [self updateNatStatus];
270}
271
272- (void) updateNatStatus
273{
274    int status = tr_natTraversalStatus(fHandle);
275    if (fNatStatus == status)
276        return;
277    fNatStatus = status;
278   
279    if (status == 2)
280    {
281        [fNatStatusField setStringValue: NSLocalizedString(@"Port successfully mapped",
282                                            "Preferences -> Network -> port map status")];
283        [fNatStatusImage setImage: [NSImage imageNamed: @"GreenDot.tiff"]];
284    }
285    else if (status == 3 || status == 4)
286    {
287        [fNatStatusField setStringValue: NSLocalizedString(@"Error mapping port",
288                                            "Preferences -> Network -> port map status")];
289        [fNatStatusImage setImage: [NSImage imageNamed: @"RedDot.tiff"]];
290    }
291    else
292    {
293        [fNatStatusField setStringValue: @""];
294        [fNatStatusImage setImage: nil];
295    }
296   
297    [self updatePortStatus];
298}
299
300- (void) applySpeedSettings: (id) sender
301{
302    if ([fDefaults boolForKey: @"SpeedLimit"])
303    {
304        tr_setUploadLimit(fHandle, [fDefaults integerForKey: @"SpeedLimitUploadLimit"]);
305        tr_setDownloadLimit(fHandle, [fDefaults integerForKey: @"SpeedLimitDownloadLimit"]);
306    }
307    else
308    {
309        tr_setUploadLimit(fHandle, [fDefaults boolForKey: @"CheckUpload"]
310                                        ? [fDefaults integerForKey: @"UploadLimit"] : -1);
311        tr_setDownloadLimit(fHandle, [fDefaults boolForKey: @"CheckDownload"]
312                                        ? [fDefaults integerForKey: @"DownloadLimit"] : -1);
313    }
314}
315
316- (void) setAutoSpeedLimit: (id) sender
317{
318    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoSpeedLimitChange" object: self];
319}
320
321- (void) setBadge: (id) sender
322{   
323    [[NSNotificationCenter defaultCenter] postNotificationName: @"DockBadgeChange" object: self];
324}
325
326- (void) setSound: (id) sender
327{
328    //play sound when selecting
329    NSString * soundName = [sender titleOfSelectedItem];
330    NSSound * sound;
331    if ((sound = [NSSound soundNamed: soundName]))
332        [sound play];
333}
334
335- (void) setUpdate: (id) sender
336{
337    int index = [fUpdatePopUp indexOfSelectedItem];
338    NSTimeInterval seconds;
339    if (index == UPDATE_DAILY)
340    {
341        [fDefaults setObject: @"Daily" forKey: @"UpdateCheck"];
342        seconds = 86400;
343    }
344    else if (index == UPDATE_WEEKLY)
345    {
346        [fDefaults setObject: @"Weekly" forKey: @"UpdateCheck"];
347        seconds = 604800;
348    }
349    else
350    {
351        [fDefaults setObject: @"Never" forKey: @"UpdateCheck"];
352        seconds = 0;
353    }
354
355    [fDefaults setInteger: seconds forKey: @"SUScheduledCheckInterval"];
356   
357    if (fUpdater)
358        [fUpdater scheduleCheckWithInterval: seconds];
359}
360
361- (void) setQueueNumber: (id) sender
362{
363    [[NSNotificationCenter defaultCenter] postNotificationName: @"GlobalStartSettingChange" object: self];
364}
365
366- (void) setDownloadLocation: (id) sender
367{
368    //download folder
369    switch ([fFolderPopUp indexOfSelectedItem])
370    {
371        case DOWNLOAD_FOLDER:
372            [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
373            break;
374        case DOWNLOAD_TORRENT:
375            [fDefaults setObject: @"Torrent" forKey: @"DownloadChoice"];
376            break;
377        case DOWNLOAD_ASK:
378            [fDefaults setObject: @"Ask" forKey: @"DownloadChoice"];
379            break;
380    }
381}
382
383- (void) folderSheetShow: (id) sender
384{
385    NSOpenPanel * panel = [NSOpenPanel openPanel];
386
387    [panel setPrompt: @"Select"];
388    [panel setAllowsMultipleSelection: NO];
389    [panel setCanChooseFiles: NO];
390    [panel setCanChooseDirectories: YES];
391    [panel setCanCreateDirectories: YES];
392
393    [panel beginSheetForDirectory: nil file: nil types: nil
394        modalForWindow: [self window] modalDelegate: self didEndSelector:
395        @selector(folderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
396}
397
398- (void) incompleteFolderSheetShow: (id) sender
399{
400    NSOpenPanel * panel = [NSOpenPanel openPanel];
401
402    [panel setPrompt: @"Select"];
403    [panel setAllowsMultipleSelection: NO];
404    [panel setCanChooseFiles: NO];
405    [panel setCanChooseDirectories: YES];
406    [panel setCanCreateDirectories: YES];
407
408    [panel beginSheetForDirectory: nil file: nil types: nil
409        modalForWindow: [self window] modalDelegate: self didEndSelector:
410        @selector(incompleteFolderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
411}
412
413- (void) setAutoImport: (id) sender
414{
415    if ([fDefaults boolForKey: @"AutoImport"])
416        [[UKKQueue sharedFileWatcher] addPath:
417            [[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath]];
418    else
419        [[UKKQueue sharedFileWatcher] removePathFromQueue:
420            [[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath]];
421   
422    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoImportSettingChange" object: self];
423}
424
425- (void) importFolderSheetShow: (id) sender
426{
427    NSOpenPanel * panel = [NSOpenPanel openPanel];
428
429    [panel setPrompt: @"Select"];
430    [panel setAllowsMultipleSelection: NO];
431    [panel setCanChooseFiles: NO];
432    [panel setCanChooseDirectories: YES];
433    [panel setCanCreateDirectories: YES];
434
435    [panel beginSheetForDirectory: nil file: nil types: nil
436        modalForWindow: [self window] modalDelegate: self didEndSelector:
437        @selector(importFolderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
438}
439
440- (void) setAutoSize: (id) sender
441{
442    [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoSizeSettingChange" object: self];
443}
444
445- (void) helpForNetwork: (id) sender
446{
447    [[NSHelpManager sharedHelpManager] openHelpAnchor: @"PortForwarding"
448        inBook: [[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleHelpBookName"]];
449}
450
451@end
452
453@implementation PrefsController (Private)
454
455- (void) setPrefView: (id) sender
456{
457    NSView * view = fGeneralView;
458    if (sender)
459    {
460        NSString * identifier = [sender itemIdentifier];
461        if ([identifier isEqualToString: TOOLBAR_TRANSFERS])
462            view = fTransfersView;
463        else if ([identifier isEqualToString: TOOLBAR_BANDWIDTH])
464            view = fBandwidthView;
465        else if ([identifier isEqualToString: TOOLBAR_NETWORK])
466            view = fNetworkView;
467        else;
468    }
469   
470    NSWindow * window = [self window];
471    if ([window contentView] == view)
472        return;
473   
474    NSRect windowRect = [window frame];
475    int difference = [view frame].size.height - [[window contentView] frame].size.height;
476    windowRect.origin.y -= difference;
477    windowRect.size.height += difference;
478   
479    [view setHidden: YES];
480    [window setContentView: view];
481    [window setFrame: windowRect display: YES animate: YES];
482    [view setHidden: NO];
483   
484    //set title label
485    if (sender)
486        [window setTitle: [sender label]];
487    else
488    {
489        NSToolbarItem * item;
490        NSEnumerator * enumerator = [[fToolbar items] objectEnumerator];
491        while ((item = [enumerator nextObject]))
492            if ([[item itemIdentifier] isEqualToString: [fToolbar selectedItemIdentifier]])
493            {
494                [window setTitle: [item label]];
495                break;
496            }
497    }
498   
499    //for network view make sure progress indicator hides itself
500    if (view == fNetworkView && [fPortStatusImage image])
501        [fPortStatusProgress setDisplayedWhenStopped: NO];
502}
503
504- (void) folderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info
505{
506    if (code == NSOKButton)
507    {
508        [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
509        [fDefaults setObject: [[openPanel filenames] objectAtIndex: 0] forKey: @"DownloadFolder"];
510        [fDefaults setObject: @"Constant" forKey: @"DownloadChoice"];
511    }
512    else
513    {
514        //reset if cancelled
515        NSString * downloadChoice = [fDefaults stringForKey: @"DownloadChoice"];
516        if ([downloadChoice isEqualToString: @"Constant"])
517            [fFolderPopUp selectItemAtIndex: DOWNLOAD_FOLDER];
518        else if ([downloadChoice isEqualToString: @"Torrent"])
519            [fFolderPopUp selectItemAtIndex: DOWNLOAD_TORRENT];
520        else
521            [fFolderPopUp selectItemAtIndex: DOWNLOAD_ASK];
522    }
523}
524
525- (void) incompleteFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info
526{
527    if (code == NSOKButton)
528        [fDefaults setObject: [[openPanel filenames] objectAtIndex: 0] forKey: @"IncompleteDownloadFolder"];
529    [fIncompleteFolderPopUp selectItemAtIndex: 0];
530}
531
532- (void) importFolderSheetClosed: (NSOpenPanel *) openPanel returnCode: (int) code contextInfo: (void *) info
533{
534    if (code == NSOKButton)
535    {
536        UKKQueue * sharedQueue = [UKKQueue sharedFileWatcher];
537        [sharedQueue removePathFromQueue: [[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath]];
538       
539        [fDefaults setObject: [[openPanel filenames] objectAtIndex: 0] forKey: @"AutoImportDirectory"];
540       
541        [sharedQueue addPath: [[fDefaults stringForKey: @"AutoImportDirectory"] stringByExpandingTildeInPath]];
542       
543        [[NSNotificationCenter defaultCenter] postNotificationName: @"AutoImportSettingChange" object: self];
544    }
545    [fImportFolderPopUp selectItemAtIndex: 0];
546}
547
548@end
Note: See TracBrowser for help on using the repository browser.