Make browser and preferences window load lazily.
[pithos-macos] / pithos-macos / PithosPreferencesController.m
1 //
2 //  PithosPreferencesController.m
3 //  pithos-macos
4 //
5 // Copyright 2011-2012 GRNET S.A. All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
9 // conditions are met:
10 // 
11 //   1. Redistributions of source code must retain the above
12 //      copyright notice, this list of conditions and the following
13 //      disclaimer.
14 // 
15 //   2. Redistributions in binary form must reproduce the above
16 //      copyright notice, this list of conditions and the following
17 //      disclaimer in the documentation and/or other materials
18 //      provided with the distribution.
19 // 
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 // 
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
37
38 #import "PithosPreferencesController.h"
39 #import "PithosBrowserController.h"
40 #import "PithosAccountNode.h"
41 #import "PithosAccount.h"
42 #import "pithos_macosAppDelegate.h"
43
44 @implementation PithosPreferencesController
45 @synthesize selectedPithosAccount;
46 @synthesize accountsArrayController;
47 @synthesize accountRemoveEnable;
48 @synthesize serverURL, authUser, authToken, manual, loginEnable, loginCancelEnable;
49 @synthesize groupsDictionaryController, selectedGroupMembersDictionaryController;
50 @synthesize syncActive, syncDirectoryPath, syncApplyEnable, syncCancelEnable;
51
52 #pragma mark -
53 #pragma mark Object Lifecycle
54
55 - (id)init {
56     return [super initWithWindowNibName:@"PithosPreferencesController"];
57 }
58
59 - (void)windowDidLoad {
60     [super windowDidLoad];
61     
62     NSWindow *window = [self window];
63     [window setHidesOnDeactivate:NO];
64     [window setExcludedFromWindowsMenu:YES];
65     
66 //      // Select the first tab when the window is loaded for the first time.
67 //      [[window valueForKeyPath:@"toolbar"] setSelectedItemIdentifier:@"0"];
68
69     [groupsDictionaryController setInitialKey:@"group"];
70     [groupsDictionaryController setInitialValue:@"user"];
71     [selectedGroupMembersDictionaryController setInitialKey:@"user"];
72     [selectedGroupMembersDictionaryController setInitialValue:@""];
73
74     [window setDelegate:self];
75     
76     self.selectedPithosAccount = [[accountsArrayController selectedObjects] objectAtIndex:0];
77     [accountsArrayController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:NULL];
78 }
79
80 - (BOOL)windowShouldClose:(id)sender {
81     return [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] activated];
82 }
83
84 //- (void)windowWillClose:(NSNotification *)notification {
85 //}
86
87 //- (IBAction)toolbarItemSelected:(id)sender {
88 //}
89
90 #pragma mark -
91 #pragma Observers
92
93 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
94     if ([object isEqualTo:accountsArrayController] && 
95         [keyPath isEqualToString:@"selection"] && 
96         [[accountsArrayController selectedObjects] count]) {
97         self.selectedPithosAccount = [[accountsArrayController selectedObjects] objectAtIndex:0];
98     }
99 }
100
101 #pragma mark -
102 #pragma Update
103
104 - (void)updateAccounts {
105     pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
106     self.accountRemoveEnable = (delegate.activated && ([delegate.pithosAccounts count] > 1));
107 }
108
109 - (void)updateLogin {
110     self.loginEnable = ([selectedPithosAccount urlIsValid:serverURL] && (!manual || ([authUser length] && [authToken length])));
111     self.loginCancelEnable = (![selectedPithosAccount.serverURL isEqualToString:serverURL] || 
112                               (selectedPithosAccount.authUser && ![selectedPithosAccount.authUser isEqualToString:authUser]) || 
113                               (selectedPithosAccount.authToken && ![selectedPithosAccount.authToken isEqualToString:authToken]));
114 }
115
116 - (void)updateSync {
117     BOOL isDirectory;
118     self.syncApplyEnable = (selectedPithosAccount.active && 
119                             ((selectedPithosAccount.syncActive != syncActive) || 
120                              (![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath] && 
121                               (![[NSFileManager defaultManager] fileExistsAtPath:syncDirectoryPath isDirectory:&isDirectory] || 
122                                isDirectory))));
123     self.syncCancelEnable = (selectedPithosAccount.active && 
124                              ((selectedPithosAccount.syncActive != syncActive) || 
125                               ![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath]));
126 }
127
128 #pragma mark -
129 #pragma Properties
130
131 - (void)setSelectedPithosAccount:(PithosAccount *)aSelectedPithosAccount {
132     if (aSelectedPithosAccount && ![aSelectedPithosAccount isEqualTo:selectedPithosAccount]) {
133         [selectedPithosAccount release];
134         selectedPithosAccount = [aSelectedPithosAccount retain];
135         
136         [self updateAccounts];
137         [self loginCancel:self];
138         [self syncCancel:self];
139         [self groupsRevert:self];
140     }
141 }
142
143 #pragma Login Properties
144
145 - (void)setServerURL:(NSString *)aServerURL {
146     [serverURL release];
147     serverURL = [aServerURL copy];
148     [self updateLogin];
149 }
150
151 - (void)setAuthUser:(NSString *)anAuthUser {
152     [authUser release];
153     authUser = [anAuthUser copy];
154     [self updateLogin];
155 }
156
157 - (void)setAuthToken:(NSString *)anAuthToken {
158     [authToken release];
159     authToken = [anAuthToken copy];
160     [self updateLogin];
161 }
162
163 - (void)setManual:(BOOL)aManual {
164     manual = aManual;
165     [self updateLogin];
166     if (!manual) {
167         self.authUser = [[selectedPithosAccount.authUser copy] autorelease];
168         self.authToken = [[selectedPithosAccount.authToken copy] autorelease];
169     }
170 }
171
172 #pragma Sync Properties
173
174 - (void)setSyncActive:(BOOL)aSyncActive {
175     syncActive = aSyncActive;
176     [self updateSync];
177 }
178
179 - (void)setSyncDirectoryPath:(NSString *)aSyncDirectoryPath {
180     [syncDirectoryPath release];
181     syncDirectoryPath = [aSyncDirectoryPath copy];
182     [self updateSync];
183 }
184
185 #pragma mark -
186 #pragma Actions
187
188 - (IBAction)addAccount:(id)sender {
189     [accountsArrayController addObject:[PithosAccount pithosAccount]];
190     [self updateAccounts];
191     pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
192     [delegate.pithosAccountsDictionary setObject:selectedPithosAccount forKey:selectedPithosAccount.name];
193     [delegate savePithosAccounts:self];
194 }
195
196 - (IBAction)removeAccount:(id)sender {
197     [self updateAccounts];
198     if (!accountRemoveEnable)
199         return;
200     PithosAccount *removedPithosAccount = [selectedPithosAccount retain];
201     pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
202     if ([delegate.currentPithosAccount isEqualTo:removedPithosAccount] && [delegate.pithosBrowserController operationsPending]) {
203         NSAlert *alert = [[[NSAlert alloc] init] autorelease];
204         [alert setMessageText:@"Operations Pending"];
205         [alert setInformativeText:@"There are pending operations in the browser, do you want to remove the account and cancel them?"];
206         [alert addButtonWithTitle:@"OK"];
207         [alert addButtonWithTitle:@"Cancel"];
208         NSInteger choice = [alert runModal];
209         if (choice == NSAlertSecondButtonReturn) {
210             [removedPithosAccount release];
211             return;
212         }
213     }
214     [accountsArrayController removeObject:selectedPithosAccount];
215     [delegate.pithosAccountsDictionary removeObjectForKey:removedPithosAccount.name];
216     [delegate removedPithosAccount:removedPithosAccount];
217     [delegate savePithosAccounts:self];
218     [removedPithosAccount release];
219     [self updateAccounts];
220 }
221
222 #pragma Login Actions
223
224 - (IBAction)login:(id)sender {
225     if (!manual) {
226         [selectedPithosAccount loginWithServerURL:serverURL];
227     } else {
228         [selectedPithosAccount authenticateWithServerURL:serverURL authUser:authUser authToken:authToken];
229         self.manual = NO;
230         pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
231         [delegate savePithosAccounts:self];
232         if (!delegate.activated) {
233             delegate.activated = YES;
234             [delegate showPithosBrowser:self];
235         }
236         if ([selectedPithosAccount isEqualTo:delegate.currentPithosAccount])
237             delegate.pithosBrowserController.pithos = selectedPithosAccount.pithos;
238     }
239 }
240
241 - (IBAction)loginCancel:(id)server {
242     self.serverURL = [[selectedPithosAccount.serverURL copy] autorelease];
243     self.authUser = [[selectedPithosAccount.authUser copy] autorelease];
244     self.authToken = [[selectedPithosAccount.authToken copy] autorelease];
245 }
246
247 #pragma Sync Actions
248
249 - (IBAction)syncApply:(id)sender {
250     [selectedPithosAccount updateSyncWithSyncActive:syncActive syncDirectoryPath:syncDirectoryPath];
251     [self updateSync];
252     pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
253     [delegate savePithosAccounts:self];
254 }
255
256 - (IBAction)syncCancel:(id)sender {
257     self.syncActive = selectedPithosAccount.syncActive;
258     self.syncDirectoryPath = [[selectedPithosAccount.syncDirectoryPath copy] autorelease];
259 }
260
261 #pragma mark Groups Actions
262
263 - (IBAction)groupsApply:(id)sender {
264     [[self window] makeFirstResponder:nil];
265     if (selectedPithosAccount.active)
266         [selectedPithosAccount.accountNode applyInfo];
267 }
268
269 - (IBAction)groupsRevert:(id)sender {
270     if (selectedPithosAccount.active && selectedPithosAccount.accountNode)
271         [selectedPithosAccount.accountNode refreshInfo];
272 }
273
274 @end