Merged [13632]: Patch from Gayle Laakmann to not append @gmail.com if @googlemail...
[adiumx.git] / Source / AIEditAccountWindowController.m
blob34a87e44a9be8757c72c8ffa7c98cea83f43da76
1 /*
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  *
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import "AIAccountController.h"
18 #import "AIAccountProxySettings.h"
19 #import "AIContactController.h"
20 #import "AIPreferenceController.h"
21 #import "AIEditAccountWindowController.h"
22 #import <AIUtilities/AIStringAdditions.h>
23 #import <AIUtilities/AITabViewAdditions.h>
24 #import <AIUtilities/AIViewAdditions.h>
25 #import <AIUtilities/ESImageAdditions.h>
26 #import <AIUtilities/ESImageViewWithImagePicker.h>
27 #import <Adium/AIAccount.h>
28 #import <Adium/AIAccountViewController.h>
29 #import <Adium/AIService.h>
30 #import <Adium/AIService.h>
31 #import <Adium/AIServiceIcons.h>
33 @interface AIEditAccountWindowController (PRIVATE)
34 - (id)initWithWindowNibName:(NSString *)windowNibName account:(AIAccount *)inAccount isNewAccount:(BOOL)inIsNewAccount;
35 - (void)_addCustomViewAndTabsForAccount:(AIAccount *)inAccount;
36 - (int)_addCustomView:(NSView *)customView toView:(NSView *)setupView tabViewItemIdentifier:(NSString *)identifier;
37 - (void)_configureResponderChain:(NSTimer *)inTimer;
38 - (void)_removeCustomViewAndTabs;
39 - (void)_localizeTabViewItemLabels;
40 - (void)saveConfiguration;
41 @end
43 /*!
44  * @class AIEditAccountWindowController
45  * @brief Window controller for configuring an <tt>AIAccount</tt>
46  */
47 @implementation AIEditAccountWindowController
49 /*!
50  * @brief Begin editing
51  *
52  * @param inAccount The account to edit
53  * @param parentWindow A window on which to show the edit account window as a sheet.  If nil, account editing takes place in an independent window.
54  * @param inIsNewAccount If YES and the user presses cancel, inAccount is deleted. This should be passed as YES when the method is called as a result of creating a new account.
55  */
56 + (void)editAccount:(AIAccount *)inAccount onWindow:(id)parentWindow isNewAccount:(BOOL)inIsNewAccount
58         AIEditAccountWindowController   *controller;
60         controller = [[self alloc] initWithWindowNibName:@"EditAccountSheet"
61                                                                                          account:inAccount
62                                                                         isNewAccount:inIsNewAccount];
64         if(parentWindow){
65                 [NSApp beginSheet:[controller window]
66                    modalForWindow:parentWindow
67                         modalDelegate:controller
68                    didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
69                           contextInfo:nil];
70         }else{
71                 [controller showWindow:nil];
72         }
75 /*!
76  * @brief Init the window controller
77  */
78 - (id)initWithWindowNibName:(NSString *)windowNibName account:(AIAccount *)inAccount isNewAccount:(BOOL)inIsNewAccount
80         if((self = [super initWithWindowNibName:windowNibName])) {
81                 account = [inAccount retain];
82                 isNewAccount = inIsNewAccount;
83                 userIconData = nil;
84                 didDeleteUserIcon = NO;
85         }
86         return self;
89 /*!
90  * @brief Deallocate
91  */
92 - (void)dealloc
94         [account release];
95         [userIconData release]; userIconData = nil;
97         [super dealloc];
101  * @brief Setup the window before it is displayed
102  */
103 - (void)windowDidLoad
105         //Center our window if we're not a sheet (or opening a sheet failed)
106         [[self window] center];
108         //Account Overview
109         /*
110         [image_serviceIcon setImage:[AIServiceIcons serviceIconForService:[account service]
111                                                                                                                                  type:AIServiceIconLarge
112                                                                                                                         direction:AIIconNormal]];
113          */
114         [textField_serviceName setStringValue:[[account service] longDescription]];
115         [textField_accountDescription setStringValue:[account UID]];
116         [checkBox_autoConnect setState:[[account preferenceForKey:@"AutoConnect" group:GROUP_ACCOUNT_STATUS] boolValue]];
117         [checkBox_autoConnect setLocalizedString:AILocalizedString(@"Automatically connect on launch","Accounts preferences: When Adium loads, connect this account immediately.")];
118         [button_chooseIcon setLocalizedString:[AILocalizedString(@"Choose Icon",nil) stringByAppendingEllipsis]];
119         [button_OK setLocalizedString:AILocalizedString(@"OK",nil)];
120         [button_cancel setLocalizedString:AILocalizedString(@"Cancel",nil)];
122         //User icon
123         [imageView_userIcon setImage:[account userIcon]];
125         //Insert the custom controls for this account
126         [self _removeCustomViewAndTabs];
127         [self _addCustomViewAndTabsForAccount:account];
128         [self _localizeTabViewItemLabels];
132  * @brief Window is closing
133  */
134 - (void)windowWillClose:(id)sender
136         [super windowWillClose:sender];
137         [self autorelease];
141  * @brief Called as the user list edit sheet closes, dismisses the sheet
142  */
143 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
145     [sheet orderOut:nil];
149  * @brief Cancel
151  * Close without saving changes. If isNewAccount is YES, delete the account at this time.
152  * isNewAccount should only be YES if we were called to edit a newly created account. Canceling the process should
153  * delete the account which we were passed.
154  */
155 - (IBAction)cancel:(id)sender
157         if(isNewAccount){
158                 [[adium accountController] deleteAccount:account save:YES];
159         }
161         [self closeWindow:nil];
165  * @brief Okay.
167  * Save changes and close.
168  */
169 - (IBAction)okay:(id)sender
171         [self saveConfiguration];
172         [accountViewController saveConfiguration];
173         [accountProxyController saveConfiguration];
174         [self closeWindow:nil];
176         //Put new accounts online by default
177         if(isNewAccount){
178                 [account setPreference:[NSNumber numberWithBool:YES] forKey:@"Online" group:GROUP_ACCOUNT_STATUS];
179         }
180         
184  * @brief Save any configuration managed by the window controller
186  * Most configuration is handled by the custom view controllers.  Save any other configuration, such as the user icon.
187  */
188 - (void)saveConfiguration
190         /* User icon - save if we have data or we deleted
191          * (so if we don't have data that's the desired thing to set as the pref) */
192         if(userIconData || didDeleteUserIcon){
193                 [account setPreference:userIconData
194                                                 forKey:KEY_USER_ICON
195                                                  group:GROUP_ACCOUNT_STATUS];
196         }
197         
198         //Auto connect
199         [account setPreference:[NSNumber numberWithBool:[checkBox_autoConnect state]]
200                                         forKey:@"AutoConnect"
201                                          group:GROUP_ACCOUNT_STATUS];
205  * @brief Add the custom views for an account
206  */
207 - (void)_addCustomViewAndTabsForAccount:(AIAccount *)inAccount
209         NSRect  windowFrame;
210         int             heightChange = 0;
211         int             heightDifference;
213         windowFrame = [[self window] frame];
215         //Configure our account and proxy view controllers
216         accountViewController = [[[inAccount service] accountViewController] retain];
217         [accountViewController configureForAccount:inAccount];
219         accountProxyController = ([[inAccount service] supportsProxySettings] ?
220                                                           [[AIAccountProxySettings alloc] init] :
221                                                           nil);
222         [accountProxyController configureForAccount:inAccount];
224         //Account setup view
225         heightDifference = [self _addCustomView:[accountViewController setupView]
226                                                                          toView:view_accountSetup
227                                           tabViewItemIdentifier:@"account"];
228         if(heightDifference > heightChange) heightChange = heightDifference;
230         //Account Profile View
231         heightDifference = [self _addCustomView:[accountViewController profileView]
232                                                                          toView:view_accountProfile
233                                           tabViewItemIdentifier:@"profile"];
234         if(heightDifference > heightChange) heightChange = heightDifference;
236         //Account Options view
237         heightDifference = [self _addCustomView:[accountViewController optionsView]
238                                                                          toView:view_accountOptions
239                                           tabViewItemIdentifier:@"options"];
240         if(heightDifference > heightChange) heightChange = heightDifference;
242         //Account Privacy view
243         heightDifference = [self _addCustomView:[accountViewController privacyView]
244                                                                          toView:view_accountPrivacy
245                                           tabViewItemIdentifier:@"privacy"];
246         if(heightDifference > heightChange) heightChange = heightDifference;
248         //Add proxy view
249         heightDifference = [self _addCustomView:[accountProxyController view]
250                                                                          toView:view_accountProxy
251                                           tabViewItemIdentifier:@"proxy"];
252         if(heightDifference > heightChange) heightChange = heightDifference;
254         windowFrame.size.height += heightChange;
255         [[self window] setFrame:windowFrame display:YES];
257         //Responder chains are a pain in 10.3.  The tab view will set them up correctly when we switch tabs, but doesn't
258         //get a chance to setup the responder chain for our default tab.  A quick hack to get the tab view to set things
259         //up correctly is to switch tabs away and then back to our default.  This causes little harm, since our window
260         //isn't visible at this point anyway.
261         //XXX - I believe we're getting a method that will avoid the need for this hack in 10.4 -ai
262         [tabView_auxiliary selectLastTabViewItem:nil];
263         [tabView_auxiliary selectFirstTabViewItem:nil];
267  * @brief Used when configuring to add custom views and remove tabs as necessary
269  * Add customView to setupView and return the height difference between the two if customView is taller than setupView.
270  * Remove the tabViewItem with the passed identifier if no customView exists, avoiding empty tabs.
272  * @param customView The view to add
273  * @param setupView The view within our nib which will be filled by customView
274  * @param identifier Identifier of the <tt>NSTabViewItem</tt> which will be removed from tabView_auxiliary if customView == nil
275  * @result The positive height difference betwen customView and setupView, indicating how much taller the window needs to be to fit customView.
276  */
277 - (int)_addCustomView:(NSView *)customView toView:(NSView *)setupView tabViewItemIdentifier:(NSString *)identifier
279         NSSize  customViewFrameSize;
280         NSRect  ourViewFrame;
281         int             heightDifference;
283         if(customView){
284                 customViewFrameSize = [customView frame].size;
285                 ourViewFrame = [setupView frame];
287                 heightDifference = (customViewFrameSize.height - ourViewFrame.size.height);
288                 if(heightDifference > 0){
289                         //Modify our frame to make room
290                         ourViewFrame.size.height += heightDifference;
291                         ourViewFrame.origin.y -= heightDifference;
292                         [setupView setFrame:ourViewFrame];
293                 }
295                 [customView setFrameSize:ourViewFrame.size];
296                 [setupView addSubview:customView];
297         }else{
298                 //If no options are available, remove the options tab
299                 [tabView_auxiliary removeTabViewItem:[tabView_auxiliary tabViewItemWithIdentifier:identifier]];
301                 heightDifference = 0;
302         }
304         return(heightDifference > 0 ? heightDifference : 0);
308  * @brief Remove any existing custom views
309  */
310 - (void)_removeCustomViewAndTabs
312     //Close any currently open controllers
313     [view_accountSetup removeAllSubviews];
314     [accountViewController release]; accountViewController = nil;
318  * @brief Localization
319  */
320 - (void)_localizeTabViewItemLabels
322         [[tabView_auxiliary tabViewItemWithIdentifier:@"account"] setLabel:AILocalizedString(@"Account",nil)];
323         [[tabView_auxiliary tabViewItemWithIdentifier:@"profile"] setLabel:AILocalizedString(@"Personal",nil)];
324         [[tabView_auxiliary tabViewItemWithIdentifier:@"options"] setLabel:AILocalizedString(@"Options",nil)];
325         [[tabView_auxiliary tabViewItemWithIdentifier:@"privacy"] setLabel:AILocalizedString(@"Privacy",nil)];
326         [[tabView_auxiliary tabViewItemWithIdentifier:@"proxy"] setLabel:AILocalizedString(@"Proxy",nil)];
329 // ESImageViewWithImagePicker Delegate ---------------------------------------------------------------------
330 - (void)imageViewWithImagePicker:(ESImageViewWithImagePicker *)sender didChangeToImageData:(NSData *)imageData
332         [userIconData release];
333         userIconData = [imageData retain];
336 - (void)deleteInImageViewWithImagePicker:(ESImageViewWithImagePicker *)sender
338         [userIconData release]; userIconData = nil;
339         didDeleteUserIcon = YES;
341         //User icon - restore to the default icon
342         [imageView_userIcon setImage:[account userIcon]];
345 @end