summaryrefslogtreecommitdiffstats
path: root/mmc_updater/src/UpdateDialogCocoa.mm
diff options
context:
space:
mode:
Diffstat (limited to 'mmc_updater/src/UpdateDialogCocoa.mm')
-rw-r--r--mmc_updater/src/UpdateDialogCocoa.mm194
1 files changed, 194 insertions, 0 deletions
diff --git a/mmc_updater/src/UpdateDialogCocoa.mm b/mmc_updater/src/UpdateDialogCocoa.mm
new file mode 100644
index 00000000..f24f3c4d
--- /dev/null
+++ b/mmc_updater/src/UpdateDialogCocoa.mm
@@ -0,0 +1,194 @@
+#include "UpdateDialogCocoa.h"
+
+#include <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h>
+
+#include "AppInfo.h"
+#include "Log.h"
+#include "StringUtils.h"
+
+@interface UpdateDialogDelegate : NSObject
+{
+ @public UpdateDialogPrivate* dialog;
+}
+- (void) finishClicked;
+- (void) reportUpdateError:(id)arg;
+- (void) reportUpdateProgress:(id)arg;
+- (void) reportUpdateFinished:(id)arg;
+@end
+
+class UpdateDialogPrivate
+{
+ public:
+ UpdateDialogPrivate()
+ : hadError(false)
+ {
+ }
+
+ UpdateDialogDelegate* delegate;
+ NSAutoreleasePool* pool;
+ NSWindow* window;
+ NSButton* finishButton;
+ NSTextField* progressLabel;
+ NSProgressIndicator* progressBar;
+ bool hadError;
+};
+
+@implementation UpdateDialogDelegate
+- (void) finishClicked
+{
+ [NSApp stop:self];
+}
+- (void) reportUpdateError: (id)arg
+{
+ dialog->hadError = true;
+
+ NSAlert* alert = [NSAlert
+ alertWithMessageText: @"Update Problem"
+ defaultButton: nil
+ alternateButton: nil
+ otherButton: nil
+ informativeTextWithFormat: @"There was a problem installing the update:\n\n%@", arg];
+ [alert runModal];
+}
+- (void) reportUpdateProgress: (id)arg
+{
+ int percentage = [arg intValue];
+ [dialog->progressBar setDoubleValue:(percentage/100.0)];
+}
+- (void) reportUpdateFinished: (id)arg
+{
+ NSMutableString* message = [[NSMutableString alloc] init];
+ if (!dialog->hadError)
+ {
+ [message appendString:@"Updates installed."];
+ }
+ else
+ {
+ [message appendString:@"Update failed."];
+ }
+
+ [message appendString:@" Click 'Finish' to restart the application."];
+ [dialog->progressLabel setTitleWithMnemonic:message];
+ [message release];
+}
+@end
+
+UpdateDialogCocoa::UpdateDialogCocoa()
+: d(new UpdateDialogPrivate)
+{
+ [NSApplication sharedApplication];
+ d->pool = [[NSAutoreleasePool alloc] init];
+}
+
+UpdateDialogCocoa::~UpdateDialogCocoa()
+{
+ [d->pool release];
+}
+
+void UpdateDialogCocoa::enableDockIcon()
+{
+ // convert the application to a foreground application and in
+ // the process, enable the dock icon
+
+ // the reverse transformation is not possible, according to
+ // http://stackoverflow.com/questions/2832961/is-it-possible-to-hide-the-dock-icon-programmatically
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ TransformProcessType(&psn,kProcessTransformToForegroundApplication);
+}
+
+void UpdateDialogCocoa::init(int /* argc */, char** /* argv */)
+{
+ enableDockIcon();
+
+ // make the updater the active application. This does not
+ // happen automatically because the updater starts as a
+ // background application
+ [NSApp activateIgnoringOtherApps:YES];
+
+ d->delegate = [[UpdateDialogDelegate alloc] init];
+ d->delegate->dialog = d;
+
+ int width = 370;
+ int height = 100;
+
+ d->window = [[NSWindow alloc] initWithContentRect:NSMakeRect(200, 200, width, height)
+ styleMask:NSTitledWindowMask | NSMiniaturizableWindowMask
+ backing:NSBackingStoreBuffered defer:NO];
+ [d->window setTitle:[NSString stringWithUTF8String:AppInfo::name().c_str()]];
+
+ d->finishButton = [[NSButton alloc] init];
+ [d->finishButton setTitle:@"Finish"];
+ [d->finishButton setButtonType:NSMomentaryLightButton];
+ [d->finishButton setBezelStyle:NSRoundedBezelStyle];
+ [d->finishButton setTarget:d->delegate];
+ [d->finishButton setAction:@selector(finishClicked)];
+
+ d->progressBar = [[NSProgressIndicator alloc] init];
+ [d->progressBar setIndeterminate:false];
+ [d->progressBar setMinValue:0.0];
+ [d->progressBar setMaxValue:1.0];
+
+ d->progressLabel = [[NSTextField alloc] init];
+ [d->progressLabel setEditable:false];
+ [d->progressLabel setSelectable:false];
+ [d->progressLabel setTitleWithMnemonic:@"Installing Updates"];
+ [d->progressLabel setBezeled:false];
+ [d->progressLabel setDrawsBackground:false];
+
+ NSView* windowContent = [d->window contentView];
+ [windowContent addSubview:d->progressLabel];
+ [windowContent addSubview:d->progressBar];
+ [windowContent addSubview:d->finishButton];
+
+ [d->progressLabel setFrame:NSMakeRect(10,70,width - 10,20)];
+ [d->progressBar setFrame:NSMakeRect(10,40,width - 20,20)];
+ [d->finishButton setFrame:NSMakeRect(width - 85,5,80,30)];
+}
+
+void UpdateDialogCocoa::exec()
+{
+ [d->window makeKeyAndOrderFront:d->window];
+ [d->window center];
+ [NSApp run];
+}
+
+void UpdateDialogCocoa::updateError(const std::string& errorMessage)
+{
+ [d->delegate performSelectorOnMainThread:@selector(reportUpdateError:)
+ withObject:[NSString stringWithUTF8String:errorMessage.c_str()]
+ waitUntilDone:false];
+}
+
+void UpdateDialogCocoa::updateProgress(int percentage)
+{
+ [d->delegate performSelectorOnMainThread:@selector(reportUpdateProgress:)
+ withObject:[NSNumber numberWithInt:percentage]
+ waitUntilDone:false];
+}
+
+void UpdateDialogCocoa::updateFinished()
+{
+ [d->delegate performSelectorOnMainThread:@selector(reportUpdateFinished:)
+ withObject:nil
+ waitUntilDone:false];
+ UpdateDialog::updateFinished();
+}
+
+void* UpdateDialogCocoa::createAutoreleasePool()
+{
+ return [[NSAutoreleasePool alloc] init];
+}
+
+void UpdateDialogCocoa::releaseAutoreleasePool(void* arg)
+{
+ [(id)arg release];
+}
+
+void UpdateDialogCocoa::quit()
+{
+ [NSApp performSelectorOnMainThread:@selector(stop:) withObject:d->delegate waitUntilDone:false];
+}
+
+