source: trunk/Sparkle/SUUIBasedUpdateDriver.m @ 1046

Revision 232, 6.8 KB checked in by speck, 4 years ago (diff)

Opgraded Sparkle to current trunk.

Line 
1//
2//  SUUIBasedUpdateDriver.m
3//  Sparkle
4//
5//  Created by Andy Matuschak on 5/5/08.
6//  Copyright 2008 Andy Matuschak. All rights reserved.
7//
8
9#import "SUUIBasedUpdateDriver.h"
10
11#import "SUUpdateAlert.h"
12#import "SUHost.h"
13#import "SUStatusController.h"
14
15@implementation SUUIBasedUpdateDriver
16
17- (void)didFindValidUpdate
18{
19    updateAlert = [[SUUpdateAlert alloc] initWithAppcastItem:updateItem host:host];
20    [updateAlert setDelegate:self];
21   
22    if ([[updater delegate] respondsToSelector:@selector(updater:didFindValidUpdate:)])
23        [[updater delegate] updater:updater didFindValidUpdate:updateItem];
24
25    // If the app is a menubar app or the like, we need to focus it first and alter the
26    // update prompt to behave like a normal window. Otherwise if the window were hidden
27    // there may be no way for the application to be activated to make it visible again.
28    if ([host isBackgroundApplication])
29    {
30        [[updateAlert window] setHidesOnDeactivate:NO];
31        [NSApp activateIgnoringOtherApps:YES];
32    }
33   
34    // Only show the update alert if the app is active; otherwise, we'll wait until it is.
35    if ([NSApp isActive])
36        [[updateAlert window] makeKeyAndOrderFront:self];
37    else
38        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:NSApp];
39}
40
41- (void)didNotFindUpdate
42{
43    if ([[updater delegate] respondsToSelector:@selector(updaterDidNotFindUpdate:)])
44        [[updater delegate] updaterDidNotFindUpdate:updater];
45    NSAlert *alert = [NSAlert alertWithMessageText:SULocalizedString(@"You're up to date!", nil) defaultButton:SULocalizedString(@"OK", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:SULocalizedString(@"%@ %@ is currently the newest version available.", nil), [host name], [host displayVersion]];
46    [self showModalAlert:alert];
47    [self abortUpdate];
48}
49
50- (void)applicationDidBecomeActive:(NSNotification *)aNotification
51{
52    [[updateAlert window] makeKeyAndOrderFront:self];
53    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSApplicationDidBecomeActiveNotification" object:NSApp];
54}
55
56- (void)updateAlert:(SUUpdateAlert *)alert finishedWithChoice:(SUUpdateAlertChoice)choice
57{
58    [updateAlert release]; updateAlert = nil;
59    [host setObject:nil forUserDefaultsKey:SUSkippedVersionKey];
60    switch (choice)
61    {
62        case SUInstallUpdateChoice:
63            statusController = [[SUStatusController alloc] initWithHost:host];
64            [statusController beginActionWithTitle:SULocalizedString(@"Downloading update...", @"Take care not to overflow the status window.") maxProgressValue:0 statusText:nil];
65            [statusController setButtonTitle:SULocalizedString(@"Cancel", nil) target:self action:@selector(cancelDownload:) isDefault:NO];
66            [statusController showWindow:self];
67            [self downloadUpdate];
68            break;
69           
70        case SUSkipThisVersionChoice:
71            [host setObject:[updateItem versionString] forUserDefaultsKey:SUSkippedVersionKey];
72        case SURemindMeLaterChoice:
73            [self abortUpdate];
74            break;         
75    }           
76}
77
78- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response
79{
80    [statusController setMaxProgressValue:[response expectedContentLength]];
81}
82
83- (NSString *)_humanReadableSizeFromDouble:(double)value
84{
85    if (value < 1024)
86        return [NSString stringWithFormat:@"%.0lf %@", value, SULocalizedString(@"B", @"the unit for bytes")];
87   
88    if (value < 1024 * 1024)
89        return [NSString stringWithFormat:@"%.0lf %@", value / 1024.0, SULocalizedString(@"KB", @"the unit for kilobytes")];
90   
91    if (value < 1024 * 1024 * 1024)
92        return [NSString stringWithFormat:@"%.1lf %@", value / 1024.0 / 1024.0, SULocalizedString(@"MB", @"the unit for megabytes")];
93   
94    return [NSString stringWithFormat:@"%.2lf %@", value / 1024.0 / 1024.0 / 1024.0, SULocalizedString(@"GB", @"the unit for gigabytes")]; 
95}
96
97- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(NSUInteger)length
98{
99    [statusController setProgressValue:[statusController progressValue] + length];
100    if ([statusController maxProgressValue] > 0)
101        [statusController setStatusText:[NSString stringWithFormat:SULocalizedString(@"%@ of %@", nil), [self _humanReadableSizeFromDouble:[statusController progressValue]], [self _humanReadableSizeFromDouble:[statusController maxProgressValue]]]];
102    else
103        [statusController setStatusText:[NSString stringWithFormat:SULocalizedString(@"%@ downloaded", nil), [self _humanReadableSizeFromDouble:[statusController progressValue]]]];
104}
105
106- (IBAction)cancelDownload:sender
107{
108    if (download)
109        [download cancel];
110    [self abortUpdate];
111}
112
113- (void)extractUpdate
114{
115    // Now we have to extract the downloaded archive.
116    [statusController beginActionWithTitle:SULocalizedString(@"Extracting update...", @"Take care not to overflow the status window.") maxProgressValue:0 statusText:nil];
117    [statusController setButtonEnabled:NO];
118    [super extractUpdate];
119}
120
121- (void)unarchiver:(SUUnarchiver *)ua extractedLength:(long)length
122{
123    // We do this here instead of in extractUpdate so that we only have a determinate progress bar for archives with progress.
124    if ([statusController maxProgressValue] == 0)
125        [statusController setMaxProgressValue:[[[[NSFileManager defaultManager] fileAttributesAtPath:downloadPath traverseLink:NO] objectForKey:NSFileSize] doubleValue]];
126    [statusController setProgressValue:[statusController progressValue] + length];
127}
128
129- (void)unarchiverDidFinish:(SUUnarchiver *)ua
130{
131    [statusController beginActionWithTitle:SULocalizedString(@"Ready to Install", nil) maxProgressValue:1 statusText:nil];
132    [statusController setProgressValue:1]; // Fill the bar.
133    [statusController setButtonEnabled:YES];
134    [statusController setButtonTitle:SULocalizedString(@"Install and Relaunch", nil) target:self action:@selector(installAndRestart:) isDefault:YES];
135    [NSApp requestUserAttention:NSInformationalRequest];   
136}
137
138- (void)installAndRestart:sender { [self installUpdate]; }
139
140- (void)installUpdate
141{
142    [statusController beginActionWithTitle:SULocalizedString(@"Installing update...", @"Take care not to overflow the status window.") maxProgressValue:0 statusText:nil];
143    [statusController setButtonEnabled:NO];
144    [super installUpdate]; 
145}
146
147- (void)abortUpdateWithError:(NSError *)error
148{
149    NSAlert *alert = [NSAlert alertWithMessageText:SULocalizedString(@"Update Error!", nil) defaultButton:SULocalizedString(@"Cancel Update", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:[error localizedDescription]];
150    [self showModalAlert:alert];
151    [super abortUpdateWithError:error];
152}
153
154- (void)abortUpdate
155{
156    if (statusController)
157    {
158        [statusController close];
159        [statusController autorelease];
160    }
161    [super abortUpdate];
162}
163
164- (void)showModalAlert:(NSAlert *)alert
165{
166    // When showing a modal alert we need to ensure that background applications
167    // are focused to inform the user since there is no dock icon to notify them.
168    if ([host isBackgroundApplication]) { [NSApp activateIgnoringOtherApps:YES]; }
169   
170    [alert setIcon:[host icon]];
171    [alert runModal];
172}
173
174@end
Note: See TracBrowser for help on using the repository browser.