Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / pithos_macosAppDelegate.m @ d8426ffb

History | View | Annotate | Download (18.5 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 d8426ffb Miltiadis Vasilakis
@synthesize pithosBrowserController, alwaysNo, aboutVersion, activated, currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccount;
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 222199ae Miltiadis Vasilakis
59 d8426ffb Miltiadis Vasilakis
    NSString *stringURL = [userDefaults stringForKey:@"aboutURL"];
60 d8426ffb Miltiadis Vasilakis
    NSURL *testURL = (stringURL) ? [NSURL URLWithString:stringURL] : nil;
61 d8426ffb Miltiadis Vasilakis
    if (!testURL || !testURL.scheme || !testURL.host) {
62 d8426ffb Miltiadis Vasilakis
        [userDefaults setObject:@"https://pithos.dev.grnet.gr/docs/pithos" forKey:@"aboutURL"];
63 d8426ffb Miltiadis Vasilakis
        [userDefaults synchronize];
64 d8426ffb Miltiadis Vasilakis
    }
65 c6f07a3c Miltiadis Vasilakis
    
66 d8426ffb Miltiadis Vasilakis
    syncTimeInterval = [userDefaults doubleForKey:@"syncTimeInterval"];
67 d8426ffb Miltiadis Vasilakis
    if (syncTimeInterval <= 0.0) {
68 d8426ffb Miltiadis Vasilakis
        syncTimeInterval = 180.0;
69 d8426ffb Miltiadis Vasilakis
        [userDefaults setDouble:syncTimeInterval forKey:@"syncTimeInterval"];
70 d8426ffb Miltiadis Vasilakis
        [userDefaults synchronize];
71 0224a49f Miltiadis Vasilakis
    }
72 0224a49f 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 Properties
210 5e5eeeaa Miltiadis Vasilakis
211 5e5eeeaa Miltiadis Vasilakis
- (NSString *)aboutVersion {
212 5e5eeeaa Miltiadis Vasilakis
    return [NSString stringWithFormat:@"About Pithos+ %@ (%@)", 
213 5e5eeeaa Miltiadis Vasilakis
            [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"], 
214 5e5eeeaa Miltiadis Vasilakis
            [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];
215 5e5eeeaa Miltiadis Vasilakis
}
216 5e5eeeaa Miltiadis Vasilakis
217 5e5eeeaa Miltiadis Vasilakis
#pragma mark -
218 d8426ffb Miltiadis Vasilakis
#pragma mark NSMenuDelegate
219 d8426ffb Miltiadis Vasilakis
220 d8426ffb Miltiadis Vasilakis
- (void)menuNeedsUpdate:(NSMenu *)menu {
221 d8426ffb Miltiadis Vasilakis
    NSMenuItem *menuItem;
222 d8426ffb Miltiadis Vasilakis
    [menu removeAllItems];
223 d8426ffb Miltiadis Vasilakis
    if ([menu isEqualTo:accountsMenu]) {
224 d8426ffb Miltiadis Vasilakis
        [menu setAutoenablesItems:NO];
225 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
226 d8426ffb Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:pithosAccount.name 
227 d8426ffb Miltiadis Vasilakis
                                                   action:@selector(menuChangePithosAccount:) 
228 d8426ffb Miltiadis Vasilakis
                                            keyEquivalent:@""] autorelease];
229 d8426ffb Miltiadis Vasilakis
            [menuItem setRepresentedObject:pithosAccount];
230 d8426ffb Miltiadis Vasilakis
            [menuItem setEnabled:pithosAccount.active];
231 d8426ffb Miltiadis Vasilakis
            [menuItem setState:((pithosAccount.active && [currentPithosAccount isEqualTo:pithosAccount]) ? NSOnState : NSOffState)];
232 d8426ffb Miltiadis Vasilakis
            [menu addItem:menuItem];
233 d8426ffb Miltiadis Vasilakis
        }
234 d8426ffb Miltiadis Vasilakis
    } else if ([menu isEqualTo:lastSyncMenu]) {
235 d8426ffb Miltiadis Vasilakis
        NSString *menuItemTitle;
236 d8426ffb Miltiadis Vasilakis
        [menu setAutoenablesItems:NO];
237 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
238 d8426ffb Miltiadis Vasilakis
            menuItemTitle = [NSString stringWithFormat:@"%@: %@", 
239 d8426ffb Miltiadis Vasilakis
                             pithosAccount.name, 
240 d8426ffb Miltiadis Vasilakis
                             [[[[LastCompletedSyncTransformer alloc] init] autorelease] transformedValue:pithosAccount.syncLastCompleted]];
241 d8426ffb Miltiadis Vasilakis
            if ([pithosAccount isEqualTo:syncPithosAccount] && [pithosAccount.syncDaemon isSyncing])
242 d8426ffb Miltiadis Vasilakis
                menuItemTitle = [menuItemTitle stringByAppendingString:@" (syncing)"];
243 d8426ffb Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle 
244 d8426ffb Miltiadis Vasilakis
                                                   action:@selector(menuChangeSyncActive:) 
245 d8426ffb Miltiadis Vasilakis
                                            keyEquivalent:@""] autorelease];
246 d8426ffb Miltiadis Vasilakis
            [menuItem setRepresentedObject:pithosAccount];
247 d8426ffb Miltiadis Vasilakis
            [menuItem setEnabled:pithosAccount.active];
248 d8426ffb Miltiadis Vasilakis
            [menuItem setState:((pithosAccount.active && pithosAccount.syncActive) ? NSOnState : NSOffState)];
249 d8426ffb Miltiadis Vasilakis
            [menu addItem:menuItem];
250 d8426ffb Miltiadis Vasilakis
        }
251 d8426ffb Miltiadis Vasilakis
        [menu addItem:[NSMenuItem separatorItem]];
252 d8426ffb Miltiadis Vasilakis
        [menu addItem:[[[NSMenuItem alloc] initWithTitle:@"Next Sync" 
253 d8426ffb Miltiadis Vasilakis
                                                  action:@selector(sync) 
254 d8426ffb Miltiadis Vasilakis
                                           keyEquivalent:@""] autorelease]];
255 d8426ffb Miltiadis Vasilakis
    }
256 d8426ffb Miltiadis Vasilakis
}
257 d8426ffb Miltiadis Vasilakis
258 d8426ffb Miltiadis Vasilakis
#pragma mark -
259 d8426ffb Miltiadis Vasilakis
#pragma mark Actions
260 589a14ca Miltiadis Vasilakis
261 589a14ca Miltiadis Vasilakis
- (IBAction)showPithosBrowser:(id)sender {
262 d8426ffb Miltiadis Vasilakis
    if (!activated)
263 d8426ffb Miltiadis Vasilakis
        return;
264 589a14ca Miltiadis Vasilakis
    [pithosBrowserController showWindow:sender];
265 589a14ca Miltiadis Vasilakis
    [[pithosBrowserController window] makeKeyAndOrderFront:sender];
266 589a14ca Miltiadis Vasilakis
    [NSApp activateIgnoringOtherApps:YES];
267 589a14ca Miltiadis Vasilakis
}
268 589a14ca Miltiadis Vasilakis
269 589a14ca Miltiadis Vasilakis
- (IBAction)showPithosPreferences:(id)sender {
270 589a14ca Miltiadis Vasilakis
    [pithosPreferencesController showWindow:sender];
271 589a14ca Miltiadis Vasilakis
    [[pithosPreferencesController window] makeKeyAndOrderFront:sender];
272 589a14ca Miltiadis Vasilakis
    [NSApp activateIgnoringOtherApps:YES];
273 589a14ca Miltiadis Vasilakis
}
274 589a14ca Miltiadis Vasilakis
275 589a14ca Miltiadis Vasilakis
- (IBAction)aboutPithos:(id)sender {
276 222199ae Miltiadis Vasilakis
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[userDefaults stringForKey:@"aboutURL"]]];
277 589a14ca Miltiadis Vasilakis
}
278 589a14ca Miltiadis Vasilakis
279 d8426ffb Miltiadis Vasilakis
- (void)sync {
280 d8426ffb Miltiadis Vasilakis
    if (!activated || ![pithosAccounts count])
281 d8426ffb Miltiadis Vasilakis
        return;
282 d8426ffb Miltiadis Vasilakis
    NSUInteger syncIndex;
283 d8426ffb Miltiadis Vasilakis
    BOOL syncPithosAccountFound = [pithosAccounts containsObject:syncPithosAccount];
284 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccountFound)
285 d8426ffb Miltiadis Vasilakis
         syncIndex = [pithosAccounts indexOfObject:syncPithosAccount];
286 d8426ffb Miltiadis Vasilakis
    
287 d8426ffb Miltiadis Vasilakis
    PithosAccount *singleSyncPithosAccount = nil;
288 d8426ffb Miltiadis Vasilakis
    for (PithosAccount *pithosAccount in pithosAccounts) {
289 d8426ffb Miltiadis Vasilakis
        if (!singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
290 d8426ffb Miltiadis Vasilakis
            singleSyncPithosAccount = pithosAccount;
291 d8426ffb Miltiadis Vasilakis
        } else if (singleSyncPithosAccount && pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
292 d8426ffb Miltiadis Vasilakis
            singleSyncPithosAccount = nil;
293 d8426ffb Miltiadis Vasilakis
            break;
294 d8426ffb Miltiadis Vasilakis
        }
295 d8426ffb Miltiadis Vasilakis
    }
296 d8426ffb Miltiadis Vasilakis
    
297 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
298 d8426ffb Miltiadis Vasilakis
        // An active syncDaemon was previously syncing
299 d8426ffb Miltiadis Vasilakis
        if (singleSyncPithosAccount && [singleSyncPithosAccount isEqualTo:syncPithosAccount]) {
300 d8426ffb Miltiadis Vasilakis
            // It's the only one, sync again
301 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon startDaemon];
302 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon sync];
303 d8426ffb Miltiadis Vasilakis
            return;
304 d8426ffb Miltiadis Vasilakis
        } else if ([syncPithosAccount.syncDaemon isSyncing]) {
305 d8426ffb Miltiadis Vasilakis
            // It's still syncing, mark it as late and return
306 d8426ffb Miltiadis Vasilakis
            [syncPithosAccount.syncDaemon syncLate];
307 d8426ffb Miltiadis Vasilakis
            return;
308 d8426ffb Miltiadis Vasilakis
        }
309 d8426ffb Miltiadis Vasilakis
    }
310 d8426ffb Miltiadis Vasilakis
    PithosAccount *newSyncPithosAccount = nil;
311 d8426ffb Miltiadis Vasilakis
    if (syncPithosAccountFound) {
312 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(syncIndex + 1, [pithosAccounts count] - syncIndex - 1)]]) {
313 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
314 d8426ffb Miltiadis Vasilakis
                newSyncPithosAccount = pithosAccount;
315 d8426ffb Miltiadis Vasilakis
                break;
316 d8426ffb Miltiadis Vasilakis
            }
317 d8426ffb Miltiadis Vasilakis
        }
318 d8426ffb Miltiadis Vasilakis
        if (!newSyncPithosAccount) {
319 d8426ffb Miltiadis Vasilakis
            for (PithosAccount *pithosAccount in [pithosAccounts objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, syncIndex)]]) {
320 d8426ffb Miltiadis Vasilakis
                if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
321 d8426ffb Miltiadis Vasilakis
                    newSyncPithosAccount = pithosAccount;
322 d8426ffb Miltiadis Vasilakis
                    break;
323 d8426ffb Miltiadis Vasilakis
                }
324 d8426ffb Miltiadis Vasilakis
            }
325 d8426ffb Miltiadis Vasilakis
        }
326 d8426ffb Miltiadis Vasilakis
    } else {
327 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
328 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active && pithosAccount.syncActive && pithosAccount.syncDaemon) {
329 d8426ffb Miltiadis Vasilakis
                newSyncPithosAccount = pithosAccount;
330 d8426ffb Miltiadis Vasilakis
                break;
331 d8426ffb Miltiadis Vasilakis
            }
332 d8426ffb Miltiadis Vasilakis
        }
333 d8426ffb Miltiadis Vasilakis
    }        
334 d8426ffb Miltiadis Vasilakis
    if (newSyncPithosAccount) {
335 d8426ffb Miltiadis Vasilakis
        // A different syncDaemon is found, sync it
336 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = newSyncPithosAccount;
337 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon startDaemon];
338 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon sync];
339 d8426ffb Miltiadis Vasilakis
    } else if (syncPithosAccountFound && syncPithosAccount && syncPithosAccount.active && syncPithosAccount.syncActive && syncPithosAccount.syncDaemon) {
340 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon startDaemon];
341 d8426ffb Miltiadis Vasilakis
        [syncPithosAccount.syncDaemon sync];
342 d8426ffb Miltiadis Vasilakis
    } else {
343 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = nil;
344 d8426ffb Miltiadis Vasilakis
    }
345 0224a49f Miltiadis Vasilakis
}
346 0224a49f Miltiadis Vasilakis
347 d8426ffb Miltiadis Vasilakis
- (void)savePithosAccounts:(id)sender {
348 d8426ffb Miltiadis Vasilakis
    [userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:pithosAccounts] forKey:@"pithosAccounts"];
349 d8426ffb Miltiadis Vasilakis
    [userDefaults synchronize];
350 d8426ffb Miltiadis Vasilakis
}
351 589a14ca Miltiadis Vasilakis
352 d8426ffb Miltiadis Vasilakis
- (void)removedPithosAccount:(PithosAccount *)removedPithosAccount {
353 d8426ffb Miltiadis Vasilakis
    if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
354 d8426ffb Miltiadis Vasilakis
        for (PithosAccount *pithosAccount in pithosAccounts) {
355 d8426ffb Miltiadis Vasilakis
            if (pithosAccount.active) {
356 d8426ffb Miltiadis Vasilakis
                self.currentPithosAccount = pithosAccount;
357 d8426ffb Miltiadis Vasilakis
                pithosBrowserController.pithos = currentPithosAccount.pithos;
358 d8426ffb Miltiadis Vasilakis
                break;
359 d8426ffb Miltiadis Vasilakis
            }
360 d8426ffb Miltiadis Vasilakis
        }
361 d8426ffb Miltiadis Vasilakis
        if ([self.currentPithosAccount isEqualTo:removedPithosAccount]) {
362 d8426ffb Miltiadis Vasilakis
            self.activated = NO;
363 d8426ffb Miltiadis Vasilakis
            [pithosBrowserController.window close];
364 d8426ffb Miltiadis Vasilakis
            [pithosBrowserController resetBrowser];
365 d8426ffb Miltiadis Vasilakis
            self.currentPithosAccount = [pithosAccounts objectAtIndex:0];
366 d8426ffb Miltiadis Vasilakis
        }
367 d8426ffb Miltiadis Vasilakis
    }
368 d8426ffb Miltiadis Vasilakis
    if ([self.syncPithosAccount isEqualTo:removedPithosAccount])
369 d8426ffb Miltiadis Vasilakis
        self.syncPithosAccount = nil;
370 dbfd951b Miltiadis Vasilakis
}
371 dbfd951b Miltiadis Vasilakis
372 d8426ffb Miltiadis Vasilakis
#pragma mark -
373 d8426ffb Miltiadis Vasilakis
#pragma mark Menu Actions
374 d8426ffb Miltiadis Vasilakis
375 d8426ffb Miltiadis Vasilakis
- (void)menuChangePithosAccount:(NSMenuItem *)sender {
376 d8426ffb Miltiadis Vasilakis
    PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
377 d8426ffb Miltiadis Vasilakis
    if (!pithosAccount.active)
378 d8426ffb Miltiadis Vasilakis
        return;
379 d8426ffb Miltiadis Vasilakis
    if (![currentPithosAccount isEqualTo:pithosAccount] && [pithosAccounts containsObject:pithosAccount]) {
380 d8426ffb Miltiadis Vasilakis
        if ([self.pithosBrowserController operationsPending]) {
381 d8426ffb Miltiadis Vasilakis
            NSAlert *alert = [[[NSAlert alloc] init] autorelease];
382 d8426ffb Miltiadis Vasilakis
            [alert setMessageText:@"Pending Operations"];
383 d8426ffb Miltiadis Vasilakis
            [alert setInformativeText:@"There are pending operations in the browser, do you want to change accounts and cancel them?"];
384 d8426ffb Miltiadis Vasilakis
            [alert addButtonWithTitle:@"OK"];
385 d8426ffb Miltiadis Vasilakis
            [alert addButtonWithTitle:@"Cancel"];
386 d8426ffb Miltiadis Vasilakis
            NSInteger choice = [alert runModal];
387 d8426ffb Miltiadis Vasilakis
            if (choice == NSAlertSecondButtonReturn) 
388 d8426ffb Miltiadis Vasilakis
                return;
389 d8426ffb Miltiadis Vasilakis
        }
390 d8426ffb Miltiadis Vasilakis
        self.currentPithosAccount = pithosAccount;
391 d8426ffb Miltiadis Vasilakis
        [self showPithosBrowser:self];
392 d8426ffb Miltiadis Vasilakis
        pithosBrowserController.pithos = currentPithosAccount.pithos;
393 74314fd6 Miltiadis Vasilakis
    }
394 0224a49f Miltiadis Vasilakis
}
395 0224a49f Miltiadis Vasilakis
396 d8426ffb Miltiadis Vasilakis
- (void)menuChangeSyncActive:(NSMenuItem *)sender {
397 d8426ffb Miltiadis Vasilakis
    PithosAccount *pithosAccount = (PithosAccount *)[sender representedObject];
398 d8426ffb Miltiadis Vasilakis
    if (!pithosAccount.active)
399 d8426ffb Miltiadis Vasilakis
        return;
400 d8426ffb Miltiadis Vasilakis
    pithosAccount.syncActive = !pithosAccount.syncActive;
401 d8426ffb Miltiadis Vasilakis
    if (pithosPreferencesController && [pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount])
402 d8426ffb Miltiadis Vasilakis
        pithosPreferencesController.syncActive = pithosAccount.syncActive;
403 d8426ffb Miltiadis Vasilakis
    [self savePithosAccounts:self];
404 d8426ffb Miltiadis Vasilakis
}
405 d8426ffb Miltiadis Vasilakis
406 d8d08dc1 Miltiadis Vasilakis
@end