Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / pithos_macosAppDelegate.m @ 544b6f52

History | View | Annotate | Download (18.2 kB)

1 d8d08dc1 Miltiadis Vasilakis
//
2 d8d08dc1 Miltiadis Vasilakis
//  pithos_macosAppDelegate.m
3 d8d08dc1 Miltiadis Vasilakis
//  pithos-macos
4 d8d08dc1 Miltiadis Vasilakis
//
5 919cb043 Miltiadis Vasilakis
// Copyright 2011-2012 GRNET S.A. All rights reserved.
6 d8d08dc1 Miltiadis Vasilakis
//
7 d8d08dc1 Miltiadis Vasilakis
// Redistribution and use in source and binary forms, with or
8 d8d08dc1 Miltiadis Vasilakis
// without modification, are permitted provided that the following
9 d8d08dc1 Miltiadis Vasilakis
// conditions are met:
10 d8d08dc1 Miltiadis Vasilakis
// 
11 d8d08dc1 Miltiadis Vasilakis
//   1. Redistributions of source code must retain the above
12 d8d08dc1 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
13 d8d08dc1 Miltiadis Vasilakis
//      disclaimer.
14 d8d08dc1 Miltiadis Vasilakis
// 
15 d8d08dc1 Miltiadis Vasilakis
//   2. Redistributions in binary form must reproduce the above
16 d8d08dc1 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
17 d8d08dc1 Miltiadis Vasilakis
//      disclaimer in the documentation and/or other materials
18 d8d08dc1 Miltiadis Vasilakis
//      provided with the distribution.
19 d8d08dc1 Miltiadis Vasilakis
// 
20 d8d08dc1 Miltiadis Vasilakis
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 d8d08dc1 Miltiadis Vasilakis
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 d8d08dc1 Miltiadis Vasilakis
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 d8d08dc1 Miltiadis Vasilakis
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 d8d08dc1 Miltiadis Vasilakis
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 d8d08dc1 Miltiadis Vasilakis
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 d8d08dc1 Miltiadis Vasilakis
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 d8d08dc1 Miltiadis Vasilakis
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 d8d08dc1 Miltiadis Vasilakis
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 d8d08dc1 Miltiadis Vasilakis
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 d8d08dc1 Miltiadis Vasilakis
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 d8d08dc1 Miltiadis Vasilakis
// POSSIBILITY OF SUCH DAMAGE.
32 d8d08dc1 Miltiadis Vasilakis
// 
33 d8d08dc1 Miltiadis Vasilakis
// The views and conclusions contained in the software and
34 d8d08dc1 Miltiadis Vasilakis
// documentation are those of the authors and should not be
35 d8d08dc1 Miltiadis Vasilakis
// interpreted as representing official policies, either expressed
36 d8d08dc1 Miltiadis Vasilakis
// or implied, of GRNET S.A.
37 d8d08dc1 Miltiadis Vasilakis
38 d8d08dc1 Miltiadis Vasilakis
#import "pithos_macosAppDelegate.h"
39 d8426ffb Miltiadis Vasilakis
#import "PithosAccount.h"
40 d8d08dc1 Miltiadis Vasilakis
#import "PithosBrowserController.h"
41 589a14ca Miltiadis Vasilakis
#import "PithosPreferencesController.h"
42 0224a49f Miltiadis Vasilakis
#import "PithosSyncDaemon.h"
43 589a14ca Miltiadis Vasilakis
#import "ASIPithosRequest.h"
44 919cb043 Miltiadis Vasilakis
#import "ASIPithos.h"
45 af3b9f06 Miltiadis Vasilakis
#import "ASIDownloadCache.h"
46 d8426ffb Miltiadis Vasilakis
#import "LastCompletedSyncTransformer.h"
47 d8d08dc1 Miltiadis Vasilakis
48 d8d08dc1 Miltiadis Vasilakis
@implementation pithos_macosAppDelegate
49 544b6f52 Miltiadis Vasilakis
@synthesize pithosBrowserController, alwaysNo, activated, currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccount, activityFacilityTimeInterval;
50 d8d08dc1 Miltiadis Vasilakis
51 d8d08dc1 Miltiadis Vasilakis
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
52 d8426ffb Miltiadis Vasilakis
    [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self 
53 d8426ffb Miltiadis Vasilakis
                                                       andSelector:@selector(handleAppleEvent:withReplyEvent:) 
54 d8426ffb Miltiadis Vasilakis
                                                     forEventClass:kInternetEventClass 
55 d8426ffb Miltiadis Vasilakis
                                                        andEventID:kAEGetURL];
56 efbe8f14 Miltiadis Vasilakis
    
57 d8426ffb Miltiadis Vasilakis
    userDefaults = [[NSUserDefaults standardUserDefaults] retain];
58 c6f07a3c Miltiadis Vasilakis
    
59 d8426ffb Miltiadis Vasilakis
    syncTimeInterval = [userDefaults doubleForKey:@"syncTimeInterval"];
60 d8426ffb Miltiadis Vasilakis
    if (syncTimeInterval <= 0.0) {
61 d8426ffb Miltiadis Vasilakis
        syncTimeInterval = 180.0;
62 d8426ffb Miltiadis Vasilakis
        [userDefaults setDouble:syncTimeInterval forKey:@"syncTimeInterval"];
63 d8426ffb Miltiadis Vasilakis
        [userDefaults synchronize];
64 0224a49f Miltiadis Vasilakis
    }
65 544b6f52 Miltiadis Vasilakis
66 544b6f52 Miltiadis Vasilakis
    activityFacilityTimeInterval = [userDefaults doubleForKey:@"activityFacilityTimeInterval"];
67 544b6f52 Miltiadis Vasilakis
    if (activityFacilityTimeInterval <= 0.0) {
68 544b6f52 Miltiadis Vasilakis
        activityFacilityTimeInterval = 0.05;
69 544b6f52 Miltiadis Vasilakis
        [userDefaults setDouble:activityFacilityTimeInterval forKey:@"activityFacilityTimeInterval"];
70 544b6f52 Miltiadis Vasilakis
        [userDefaults synchronize];
71 544b6f52 Miltiadis Vasilakis
    }
72 544b6f52 Miltiadis Vasilakis
73 d8426ffb Miltiadis Vasilakis
    NSData *tmpData = [userDefaults objectForKey:@"pithosAccounts"];
74 d8426ffb Miltiadis Vasilakis
    NSArray *tmpArray;
75 d8426ffb Miltiadis Vasilakis
    if (tmpData && (tmpArray = [NSKeyedUnarchiver unarchiveObjectWithData:tmpData]))
76 d8426ffb Miltiadis Vasilakis
        self.pithosAccounts = [NSMutableArray arrayWithArray:tmpArray];
77 d8426ffb Miltiadis Vasilakis
    else
78 d8426ffb Miltiadis Vasilakis
        self.pithosAccounts = [NSMutableArray array];
79 222199ae Miltiadis Vasilakis
    
80 d8426ffb Miltiadis Vasilakis
    if (![pithosAccounts count]) {
81 d8426ffb Miltiadis Vasilakis
        [pithosAccounts addObject:[PithosAccount pithosAccount]];
82 d8426ffb Miltiadis Vasilakis
        self.pithosAccounts = self.pithosAccounts;
83 d8426ffb Miltiadis Vasilakis
    } else {
84 d8426ffb Miltiadis Vasilakis
        self.activated = YES;
85 d8426ffb Miltiadis Vasilakis
    }
86 0224a49f Miltiadis Vasilakis
    
87 d8426ffb Miltiadis Vasilakis
    pithosAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[pithosAccounts count]];
88 d8426ffb Miltiadis Vasilakis
    for (PithosAccount *pithosAccount in pithosAccounts) {
89 d8426ffb Miltiadis Vasilakis
        [pithosAccountsDictionary setObject:pithosAccount forKey:pithosAccount.name];
90 d8426ffb Miltiadis Vasilakis
        if (!currentPithosAccount && pithosAccount.active)
91 d8426ffb Miltiadis Vasilakis
            currentPithosAccount = [pithosAccount retain];
92 d8426ffb Miltiadis Vasilakis
    }
93 d8426ffb Miltiadis Vasilakis
    if (!currentPithosAccount)
94 d8426ffb Miltiadis Vasilakis
        self.currentPithosAccount = [pithosAccounts objectAtIndex:0];
95 589a14ca Miltiadis Vasilakis
    
96 d8426ffb Miltiadis Vasilakis
    if (currentPithosAccount.active) {
97 d8426ffb Miltiadis Vasilakis
        [self savePithosAccounts:self];
98 d8426ffb Miltiadis Vasilakis
        [self showPithosBrowser:self];
99 d8426ffb Miltiadis Vasilakis
        pithosBrowserController.pithos = currentPithosAccount.pithos;
100 d8426ffb Miltiadis Vasilakis
    } else {
101 d8426ffb Miltiadis Vasilakis
        // XXX maybe call specifically to go to new account tab
102 d8426ffb Miltiadis Vasilakis
        [self showPithosPreferences:self];
103 d8426ffb Miltiadis Vasilakis
    }
104 d8426ffb Miltiadis Vasilakis
105 d8426ffb Miltiadis Vasilakis
    syncTimer = [[NSTimer scheduledTimerWithTimeInterval:syncTimeInterval 
106 d8426ffb Miltiadis Vasilakis
                                                  target:self 
107 d8426ffb Miltiadis Vasilakis
                                                selector:@selector(sync) 
108 d8426ffb Miltiadis Vasilakis
                                                userInfo:nil 
109 d8426ffb Miltiadis Vasilakis
                                                 repeats:YES] retain];
110 d8426ffb Miltiadis Vasilakis
    [syncTimer fire];
111 589a14ca Miltiadis Vasilakis
}
112 589a14ca Miltiadis Vasilakis
113 589a14ca Miltiadis Vasilakis
// Based on: http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/
114 589a14ca Miltiadis Vasilakis
// and: http://www.cocoadev.com/index.pl?ThumbnailImages
115 589a14ca Miltiadis Vasilakis
- (void)awakeFromNib {
116 72c9d681 Miltiadis Vasilakis
    NSImage *sourceImage = [NSImage imageNamed:@"pithos-large.png"];
117 589a14ca Miltiadis Vasilakis
    
118 589a14ca Miltiadis Vasilakis
    NSImage *smallImage = [[[NSImage alloc] initWithSize:NSMakeSize(18, 18)] autorelease];
119 589a14ca Miltiadis Vasilakis
    [smallImage lockFocus];
120 589a14ca Miltiadis Vasilakis
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
121 589a14ca Miltiadis Vasilakis
    [sourceImage setSize:NSMakeSize(18, 18)];
122 589a14ca Miltiadis Vasilakis
    [sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy];
123 589a14ca Miltiadis Vasilakis
    [smallImage unlockFocus];
124 589a14ca Miltiadis Vasilakis
    
125 589a14ca Miltiadis Vasilakis
    statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
126 589a14ca Miltiadis Vasilakis
    [statusItem setMenu:statusMenu];
127 589a14ca Miltiadis Vasilakis
    [statusItem setImage:sourceImage];
128 589a14ca Miltiadis Vasilakis
    [statusItem setHighlightMode:YES];
129 3812626f Miltiadis Vasilakis
    
130 3812626f Miltiadis Vasilakis
    self.alwaysNo = NO;
131 d8d08dc1 Miltiadis Vasilakis
}
132 d8d08dc1 Miltiadis Vasilakis
133 9f3a92de Miltiadis Vasilakis
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent {
134 9f3a92de Miltiadis Vasilakis
    NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
135 9f3a92de Miltiadis Vasilakis
    NSString *host = [url host];
136 9f3a92de Miltiadis Vasilakis
	NSString *query = [url query];
137 d8426ffb Miltiadis Vasilakis
    PithosAccount *pithosAccount = [pithosAccountsDictionary objectForKey:[url lastPathComponent]];
138 9f3a92de Miltiadis Vasilakis
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
139 d8426ffb Miltiadis Vasilakis
    if ([host isEqualToString:[NSString stringWithFormat:@"%@_%d", [processInfo processName], [processInfo processIdentifier]]] && 
140 d8426ffb Miltiadis Vasilakis
        pithosAccount && query) {
141 9f3a92de Miltiadis Vasilakis
        // user=
142 9f3a92de Miltiadis Vasilakis
        NSString *authUser;
143 9f3a92de Miltiadis Vasilakis
        NSRange userRange = [query rangeOfString:@"user=" options:NSCaseInsensitiveSearch];
144 9f3a92de Miltiadis Vasilakis
        if (userRange.length == 0)
145 9f3a92de Miltiadis Vasilakis
            // XXX maybe show an error message?
146 9f3a92de Miltiadis Vasilakis
            return;
147 9f3a92de Miltiadis Vasilakis
        NSUInteger authUserStartLocation = userRange.location + userRange.length;
148 9f3a92de Miltiadis Vasilakis
        NSRange userEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch 
149 9f3a92de Miltiadis Vasilakis
                                              range:NSMakeRange(authUserStartLocation, [query length] - authUserStartLocation)];
150 9f3a92de Miltiadis Vasilakis
        if (userEndRange.length) {
151 155f0dfd Miltiadis Vasilakis
            authUser = [[query substringWithRange:NSMakeRange(authUserStartLocation, userEndRange.location - authUserStartLocation)]
152 155f0dfd Miltiadis Vasilakis
                        stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
153 9f3a92de Miltiadis Vasilakis
        } else {
154 155f0dfd Miltiadis Vasilakis
            authUser = [[query substringFromIndex:authUserStartLocation]
155 155f0dfd Miltiadis Vasilakis
                        stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
156 9f3a92de Miltiadis Vasilakis
        }
157 9f3a92de Miltiadis Vasilakis
        // token=
158 9f3a92de Miltiadis Vasilakis
        NSString *authToken;
159 9f3a92de Miltiadis Vasilakis
        NSRange tokenRange = [query rangeOfString:@"token=" options:NSCaseInsensitiveSearch];
160 9f3a92de Miltiadis Vasilakis
        if (tokenRange.length == 0)
161 9f3a92de Miltiadis Vasilakis
            // XXX maybe show an error message?
162 9f3a92de Miltiadis Vasilakis
            return;
163 9f3a92de Miltiadis Vasilakis
        NSUInteger authTokenStartLocation = tokenRange.location + tokenRange.length;
164 9f3a92de Miltiadis Vasilakis
        NSRange tokenEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch 
165 9f3a92de Miltiadis Vasilakis
                                              range:NSMakeRange(authTokenStartLocation, [query length] - authTokenStartLocation)];
166 9f3a92de Miltiadis Vasilakis
        if (tokenEndRange.length) {
167 155f0dfd Miltiadis Vasilakis
            authToken = [[query substringWithRange:NSMakeRange(authTokenStartLocation, tokenEndRange.location - authTokenStartLocation)]
168 155f0dfd Miltiadis Vasilakis
                         stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
169 9f3a92de Miltiadis Vasilakis
        } else {
170 155f0dfd Miltiadis Vasilakis
            authToken = [[query substringFromIndex:authTokenStartLocation]
171 155f0dfd Miltiadis Vasilakis
                         stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
172 9f3a92de Miltiadis Vasilakis
        }
173 589a14ca Miltiadis Vasilakis
        
174 9f3a92de Miltiadis Vasilakis
        NSLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken);
175 589a14ca Miltiadis Vasilakis
        if ([authUser length] && [authToken length]) {
176 d8426ffb Miltiadis Vasilakis
            [pithosAccount authenticateWithServerURL:nil authUser:authUser authToken:authToken];
177 d8426ffb Miltiadis Vasilakis
            [self savePithosAccounts:self];
178 d8426ffb Miltiadis Vasilakis
            if (pithosPreferencesController && [pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount]) {
179 d8426ffb Miltiadis Vasilakis
                pithosPreferencesController.authUser = pithosAccount.authUser;
180 d8426ffb Miltiadis Vasilakis
                pithosPreferencesController.authToken = pithosAccount.authToken;
181 d8426ffb Miltiadis Vasilakis
            }
182 d8426ffb Miltiadis Vasilakis
            self.activated = YES;
183 d8426ffb Miltiadis Vasilakis
            if ([pithosAccount isEqualTo:currentPithosAccount]) {
184 d8426ffb Miltiadis Vasilakis
                [self showPithosBrowser:self];
185 d8426ffb Miltiadis Vasilakis
                pithosBrowserController.pithos = pithosAccount.pithos;
186 d8426ffb Miltiadis Vasilakis
            }
187 589a14ca Miltiadis Vasilakis
        }
188 589a14ca Miltiadis Vasilakis
        // XXX else maybe show an error message?
189 9f3a92de Miltiadis Vasilakis
    }
190 9f3a92de Miltiadis Vasilakis
    // XXX else maybe show an error message?
191 9f3a92de Miltiadis Vasilakis
}
192 9f3a92de Miltiadis Vasilakis
193 d8426ffb Miltiadis Vasilakis
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
194 d8426ffb Miltiadis Vasilakis
    [self savePithosAccounts:self];
195 d8426ffb Miltiadis Vasilakis
    if ([self.pithosBrowserController operationsPending]) {
196 d8426ffb Miltiadis Vasilakis
        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
197 d8426ffb Miltiadis Vasilakis
        [alert setMessageText:@"Pending Operations"];
198 d8426ffb Miltiadis Vasilakis
        [alert setInformativeText:@"There are pending operations in the browser, do you want to quit and cancel them?"];
199 d8426ffb Miltiadis Vasilakis
        [alert addButtonWithTitle:@"OK"];
200 d8426ffb Miltiadis Vasilakis
        [alert addButtonWithTitle:@"Cancel"];
201 d8426ffb Miltiadis Vasilakis
        NSInteger choice = [alert runModal];
202 d8426ffb Miltiadis Vasilakis
        if (choice == NSAlertSecondButtonReturn) 
203 d8426ffb Miltiadis Vasilakis
            return NSTerminateCancel;
204 d0d3b184 Miltiadis Vasilakis
    }
205 d8426ffb Miltiadis Vasilakis
    return NSTerminateNow;
206 d0d3b184 Miltiadis Vasilakis
}
207 d0d3b184 Miltiadis Vasilakis
208 d0d3b184 Miltiadis Vasilakis
#pragma mark -
209 d8426ffb Miltiadis Vasilakis
#pragma mark NSMenuDelegate
210 d8426ffb Miltiadis Vasilakis
211 d8426ffb Miltiadis Vasilakis
- (void)menuNeedsUpdate:(NSMenu *)menu {
212 d8426ffb Miltiadis Vasilakis
    NSMenuItem *menuItem;
213 d8426ffb Miltiadis Vasilakis
    [menu removeAllItems];
214 d8426ffb Miltiadis Vasilakis
    if ([menu isEqualTo:accountsMenu]) {
215 d8426ffb Miltiadis Vasilakis
        [menu setAutoenablesItems:NO];
216 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
217 d8426ffb Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:pithosAccount.name 
218 d8426ffb Miltiadis Vasilakis
                                                   action:@selector(menuChangePithosAccount:) 
219 d8426ffb Miltiadis Vasilakis
                                            keyEquivalent:@""] autorelease];
220 d8426ffb Miltiadis Vasilakis
            [menuItem setRepresentedObject:pithosAccount];
221 d8426ffb Miltiadis Vasilakis
            [menuItem setEnabled:pithosAccount.active];
222 d8426ffb Miltiadis Vasilakis
            [menuItem setState:((pithosAccount.active && [currentPithosAccount isEqualTo:pithosAccount]) ? NSOnState : NSOffState)];
223 d8426ffb Miltiadis Vasilakis
            [menu addItem:menuItem];
224 d8426ffb Miltiadis Vasilakis
        }
225 d8426ffb Miltiadis Vasilakis
    } else if ([menu isEqualTo:lastSyncMenu]) {
226 d8426ffb Miltiadis Vasilakis
        NSString *menuItemTitle;
227 d8426ffb Miltiadis Vasilakis
        [menu setAutoenablesItems:NO];
228 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
229 d8426ffb Miltiadis Vasilakis
            menuItemTitle = [NSString stringWithFormat:@"%@: %@", 
230 d8426ffb Miltiadis Vasilakis
                             pithosAccount.name, 
231 d8426ffb Miltiadis Vasilakis
                             [[[[LastCompletedSyncTransformer alloc] init] autorelease] transformedValue:pithosAccount.syncLastCompleted]];
232 d8426ffb Miltiadis Vasilakis
            if ([pithosAccount isEqualTo:syncPithosAccount] && [pithosAccount.syncDaemon isSyncing])
233 d8426ffb Miltiadis Vasilakis
                menuItemTitle = [menuItemTitle stringByAppendingString:@" (syncing)"];
234 544b6f52 Miltiadis Vasilakis
//            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle 
235 544b6f52 Miltiadis Vasilakis
//                                                   action:@selector(menuChangeSyncActive:) 
236 544b6f52 Miltiadis Vasilakis
//                                            keyEquivalent:@""] autorelease];
237 544b6f52 Miltiadis Vasilakis
//            [menuItem setRepresentedObject:pithosAccount];
238 544b6f52 Miltiadis Vasilakis
//            [menuItem setEnabled:pithosAccount.active];
239 544b6f52 Miltiadis Vasilakis
//            [menuItem setState:((pithosAccount.active && pithosAccount.syncActive) ? NSOnState : NSOffState)];
240 544b6f52 Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:nil keyEquivalent:@""] autorelease];
241 544b6f52 Miltiadis Vasilakis
            [menuItem setEnabled:NO];
242 544b6f52 Miltiadis Vasilakis
            [menuItem setState:NO];
243 d8426ffb Miltiadis Vasilakis
            [menu addItem:menuItem];
244 d8426ffb Miltiadis Vasilakis
        }
245 d8426ffb Miltiadis Vasilakis
        [menu addItem:[NSMenuItem separatorItem]];
246 d8426ffb Miltiadis Vasilakis
        [menu addItem:[[[NSMenuItem alloc] initWithTitle:@"Next Sync" 
247 d8426ffb Miltiadis Vasilakis
                                                  action:@selector(sync) 
248 d8426ffb Miltiadis Vasilakis
                                           keyEquivalent:@""] autorelease]];
249 d8426ffb Miltiadis Vasilakis
    }
250 d8426ffb Miltiadis Vasilakis
}
251 d8426ffb Miltiadis Vasilakis
252 d8426ffb Miltiadis Vasilakis
#pragma mark -
253 d8426ffb Miltiadis Vasilakis
#pragma mark Actions
254 589a14ca Miltiadis Vasilakis
255 589a14ca Miltiadis Vasilakis
- (IBAction)showPithosBrowser:(id)sender {
256 d8426ffb Miltiadis Vasilakis
    if (!activated)
257 d8426ffb Miltiadis Vasilakis
        return;
258 589a14ca Miltiadis Vasilakis
    [pithosBrowserController showWindow:sender];
259 589a14ca Miltiadis Vasilakis
    [[pithosBrowserController window] makeKeyAndOrderFront:sender];
260 589a14ca Miltiadis Vasilakis
    [NSApp activateIgnoringOtherApps:YES];
261 589a14ca Miltiadis Vasilakis
}
262 589a14ca Miltiadis Vasilakis
263 589a14ca Miltiadis Vasilakis
- (IBAction)showPithosPreferences:(id)sender {
264 589a14ca Miltiadis Vasilakis
    [pithosPreferencesController showWindow:sender];
265 589a14ca Miltiadis Vasilakis
    [[pithosPreferencesController window] makeKeyAndOrderFront:sender];
266 589a14ca Miltiadis Vasilakis
    [NSApp activateIgnoringOtherApps:YES];
267 589a14ca Miltiadis Vasilakis
}
268 589a14ca Miltiadis Vasilakis
269 d8426ffb Miltiadis Vasilakis
- (void)sync {
270 d8426ffb Miltiadis Vasilakis
    if (!activated || ![pithosAccounts count])
271 d8426ffb Miltiadis Vasilakis
        return;
272 d8426ffb Miltiadis Vasilakis
    NSUInteger syncIndex;
273 d8426ffb Miltiadis Vasilakis
    BOOL syncPithosAccountFound = [pithosAccounts containsObject:syncPithosAccount];
274 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccountFound)
275 d8426ffb Miltiadis Vasilakis
         syncIndex = [pithosAccounts indexOfObject:syncPithosAccount];
276 d8426ffb Miltiadis Vasilakis
    
277 d8426ffb Miltiadis Vasilakis
    PithosAccount *singleSyncPithosAccount = nil;
278 d8426ffb Miltiadis Vasilakis
    for (PithosAccount *pithosAccount in pithosAccounts) {
279 d8426ffb Miltiadis Vasilakis
        if (!singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
280 d8426ffb Miltiadis Vasilakis
            singleSyncPithosAccount = pithosAccount;
281 d8426ffb Miltiadis Vasilakis
        } else if (singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
282 d8426ffb Miltiadis Vasilakis
            singleSyncPithosAccount = nil;
283 d8426ffb Miltiadis Vasilakis
            break;
284 d8426ffb Miltiadis Vasilakis
        }
285 d8426ffb Miltiadis Vasilakis
    }
286 d8426ffb Miltiadis Vasilakis
    
287 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
288 d8426ffb Miltiadis Vasilakis
        // An active syncDaemon was previously syncing
289 d8426ffb Miltiadis Vasilakis
        if (singleSyncPithosAccount && [singleSyncPithosAccount isEqualTo:syncPithosAccount]) {
290 d8426ffb Miltiadis Vasilakis
            // It's the only one, sync again
291 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon startDaemon];
292 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon sync];
293 d8426ffb Miltiadis Vasilakis
            return;
294 d8426ffb Miltiadis Vasilakis
        } else if ([syncPithosAccount.syncDaemon isSyncing]) {
295 d8426ffb Miltiadis Vasilakis
            // It's still syncing, mark it as late and return
296 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon syncLate];
297 d8426ffb Miltiadis Vasilakis
            return;
298 d8426ffb Miltiadis Vasilakis
        }
299 d8426ffb Miltiadis Vasilakis
    }
300 d8426ffb Miltiadis Vasilakis
    PithosAccount *newSyncPithosAccount = nil;
301 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccountFound) {
302 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(syncIndex + 1, [pithosAccounts count] - syncIndex - 1)]]) {
303 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
304 d8426ffb Miltiadis Vasilakis
                newSyncPithosAccount = pithosAccount;
305 d8426ffb Miltiadis Vasilakis
                break;
306 d8426ffb Miltiadis Vasilakis
            }
307 d8426ffb Miltiadis Vasilakis
        }
308 d8426ffb Miltiadis Vasilakis
        if (!newSyncPithosAccount) {
309 d8426ffb Miltiadis Vasilakis
            for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, syncIndex)]]) {
310 d8426ffb Miltiadis Vasilakis
                if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
311 d8426ffb Miltiadis Vasilakis
                    newSyncPithosAccount = pithosAccount;
312 d8426ffb Miltiadis Vasilakis
                    break;
313 d8426ffb Miltiadis Vasilakis
                }
314 d8426ffb Miltiadis Vasilakis
            }
315 d8426ffb Miltiadis Vasilakis
        }
316 d8426ffb Miltiadis Vasilakis
    } else {
317 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
318 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
319 d8426ffb Miltiadis Vasilakis
                newSyncPithosAccount = pithosAccount;
320 d8426ffb Miltiadis Vasilakis
                break;
321 d8426ffb Miltiadis Vasilakis
            }
322 d8426ffb Miltiadis Vasilakis
        }
323 d8426ffb Miltiadis Vasilakis
    }        
324 d8426ffb Miltiadis Vasilakis
    if (newSyncPithosAccount) {
325 d8426ffb Miltiadis Vasilakis
        // A different syncDaemon is found, sync it
326 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = newSyncPithosAccount;
327 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon startDaemon];
328 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon sync];
329 d8426ffb Miltiadis Vasilakis
    } else if (syncPithosAccountFound && syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
330 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon startDaemon];
331 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon sync];
332 d8426ffb Miltiadis Vasilakis
    } else {
333 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = nil;
334 d8426ffb Miltiadis Vasilakis
    }
335 0224a49f Miltiadis Vasilakis
}
336 0224a49f Miltiadis Vasilakis
337 d8426ffb Miltiadis Vasilakis
- (void)savePithosAccounts:(id)sender {
338 d8426ffb Miltiadis Vasilakis
    [userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:pithosAccounts] forKey:@"pithosAccounts"];
339 d8426ffb Miltiadis Vasilakis
    [userDefaults synchronize];
340 d8426ffb Miltiadis Vasilakis
}
341 589a14ca Miltiadis Vasilakis
342 d8426ffb Miltiadis Vasilakis
- (void)removedPithosAccount:(PithosAccount *)removedPithosAccount {
343 d8426ffb Miltiadis Vasilakis
    if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
344 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
345 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active) {
346 d8426ffb Miltiadis Vasilakis
                self.currentPithosAccount = pithosAccount;
347 d8426ffb Miltiadis Vasilakis
                pithosBrowserController.pithos = currentPithosAccount.pithos;
348 d8426ffb Miltiadis Vasilakis
                break;
349 d8426ffb Miltiadis Vasilakis
            }
350 d8426ffb Miltiadis Vasilakis
        }
351 d8426ffb Miltiadis Vasilakis
        if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
352 d8426ffb Miltiadis Vasilakis
            self.activated = NO;
353 d8426ffb Miltiadis Vasilakis
            [pithosBrowserController.window close];
354 d8426ffb Miltiadis Vasilakis
            [pithosBrowserController resetBrowser];
355 d8426ffb Miltiadis Vasilakis
            self.currentPithosAccount = [pithosAccounts objectAtIndex:0];
356 d8426ffb Miltiadis Vasilakis
        }
357 d8426ffb Miltiadis Vasilakis
    }
358 d8426ffb Miltiadis Vasilakis
    if ([self.syncPithosAccount isEqualTo:removedPithosAccount])
359 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = nil;
360 dbfd951b Miltiadis Vasilakis
}
361 dbfd951b Miltiadis Vasilakis
362 d8426ffb Miltiadis Vasilakis
#pragma mark -
363 d8426ffb Miltiadis Vasilakis
#pragma mark Menu Actions
364 d8426ffb Miltiadis Vasilakis
365 d8426ffb Miltiadis Vasilakis
- (void)menuChangePithosAccount:(NSMenuItem *)sender {
366 d8426ffb Miltiadis Vasilakis
    PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
367 d8426ffb Miltiadis Vasilakis
    if (!pithosAccount.active)
368 d8426ffb Miltiadis Vasilakis
        return;
369 d8426ffb Miltiadis Vasilakis
    if (![currentPithosAccount isEqualTo:pithosAccount] && [pithosAccounts containsObject:pithosAccount]) {
370 d8426ffb Miltiadis Vasilakis
        if ([self.pithosBrowserController operationsPending]) {
371 d8426ffb Miltiadis Vasilakis
            NSAlert *alert = [[[NSAlert alloc] init] autorelease];
372 d8426ffb Miltiadis Vasilakis
            [alert setMessageText:@"Pending Operations"];
373 d8426ffb Miltiadis Vasilakis
            [alert setInformativeText:@"There are pending operations in the browser, do you want to change accounts and cancel them?"];
374 d8426ffb Miltiadis Vasilakis
            [alert addButtonWithTitle:@"OK"];
375 d8426ffb Miltiadis Vasilakis
            [alert addButtonWithTitle:@"Cancel"];
376 d8426ffb Miltiadis Vasilakis
            NSInteger choice = [alert runModal];
377 d8426ffb Miltiadis Vasilakis
            if (choice == NSAlertSecondButtonReturn) 
378 d8426ffb Miltiadis Vasilakis
                return;
379 d8426ffb Miltiadis Vasilakis
        }
380 d8426ffb Miltiadis Vasilakis
        self.currentPithosAccount = pithosAccount;
381 d8426ffb Miltiadis Vasilakis
        [self showPithosBrowser:self];
382 d8426ffb Miltiadis Vasilakis
        pithosBrowserController.pithos = currentPithosAccount.pithos;
383 74314fd6 Miltiadis Vasilakis
    }
384 0224a49f Miltiadis Vasilakis
}
385 0224a49f Miltiadis Vasilakis
386 544b6f52 Miltiadis Vasilakis
//- (void)menuChangeSyncActive:(NSMenuItem *)sender {
387 544b6f52 Miltiadis Vasilakis
//    PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
388 544b6f52 Miltiadis Vasilakis
//    if (!pithosAccount.active)
389 544b6f52 Miltiadis Vasilakis
//        return;
390 544b6f52 Miltiadis Vasilakis
//    pithosAccount.syncActive = !pithosAccount.syncActive;
391 544b6f52 Miltiadis Vasilakis
//    if (pithosPreferencesController && [pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount])
392 544b6f52 Miltiadis Vasilakis
//        pithosPreferencesController.syncActive = pithosAccount.syncActive;
393 544b6f52 Miltiadis Vasilakis
//    [self savePithosAccounts:self];
394 544b6f52 Miltiadis Vasilakis
//}
395 d8426ffb Miltiadis Vasilakis
396 d8d08dc1 Miltiadis Vasilakis
@end