2012-03-04 15:31:26 +01:00
//
// MPAppDelegate . m
// MasterPassword
//
// Created by Maarten Billemont on 04 / 03 / 12.
// Copyright ( c ) 2012 Lyndir . All rights reserved .
//
2012-05-13 10:24:19 +02:00
# import "MPAppDelegate.h"
# import "MPAppDelegate_Key.h"
# import "MPAppDelegate_Store.h"
2012-03-06 01:04:19 +01:00
# import "MPConfig.h"
2012-05-04 18:54:58 +02:00
# import "MPElementEntity.h"
2012-05-05 00:15:51 +02:00
# import < Carbon / Carbon . h >
2012-03-04 15:31:26 +01:00
2012-03-12 18:14:01 +01:00
2012-03-05 22:19:05 +01:00
@ implementation MPAppDelegate
2012-05-05 00:15:51 +02:00
@ synthesize statusItem ;
2012-05-05 13:32:09 +02:00
@ synthesize lockItem ;
@ synthesize showItem ;
@ synthesize statusMenu ;
2012-05-08 13:41:54 +02:00
@ synthesize useICloudItem ;
@ synthesize rememberPasswordItem ;
@ synthesize savePasswordItem ;
2012-03-05 22:19:05 +01:00
@ synthesize passwordWindow ;
2012-03-04 15:31:26 +01:00
2012-03-05 22:43:20 +01:00
@ synthesize key ;
2012-05-09 10:11:34 +02:00
@ synthesize keyID ;
2012-03-04 15:31:26 +01:00
2012-05-08 13:41:54 +02:00
# pragma GCC diagnostic ignored "-Wfour-char-constants"
2012-06-08 23:46:13 +02:00
static EventHotKeyID MPShowHotKey = { . signature = ' show ' , . id = 1 } ;
2012-05-05 00:15:51 +02:00
2012-03-06 01:04:19 +01:00
+ ( void ) initialize {
2012-06-08 23:46:13 +02:00
2012-03-06 01:04:19 +01:00
[ MPConfig get ] ;
2012-06-08 23:46:13 +02:00
2012-03-06 01:04:19 +01:00
# ifdef DEBUG
2012-05-05 00:15:51 +02:00
[ PearlLogger get ] . autoprintLevel = PearlLogLevelTrace ;
2012-03-06 01:04:19 +01:00
# endif
}
2012-05-13 10:24:19 +02:00
+ ( MPAppDelegate * ) get {
2012-06-08 23:46:13 +02:00
2012-05-13 10:24:19 +02:00
return ( MPAppDelegate * ) [ super get ] ;
}
2012-06-08 23:46:13 +02:00
static OSStatus MPHotKeyHander ( EventHandlerCallRef nextHandler , EventRef theEvent , void * userData ) {
2012-05-05 00:15:51 +02:00
// Extract the hotkey ID .
2012-06-08 23:46:13 +02:00
EventHotKeyID hotKeyID ;
GetEventParameter ( theEvent , kEventParamDirectObject , typeEventHotKeyID ,
NULL , sizeof ( hotKeyID ) , NULL , & hotKeyID ) ;
2012-05-05 00:15:51 +02:00
// Check which hotkey this was .
if ( hotKeyID . signature = = MPShowHotKey . signature && hotKeyID . id = = MPShowHotKey . id ) {
2012-05-05 13:32:09 +02:00
[ ( ( __bridge MPAppDelegate * ) userData ) activate : nil ] ;
2012-05-05 00:15:51 +02:00
return noErr ;
}
2012-06-08 23:46:13 +02:00
2012-05-05 00:15:51 +02:00
return eventNotHandledErr ;
}
2012-05-05 13:32:09 +02:00
- ( void ) showMenu {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
self . rememberPasswordItem . state = [ [ MPConfig get ] . rememberKey boolValue ] ? NSOnState : NSOffState ;
2012-06-08 23:46:13 +02:00
self . savePasswordItem . state = [ [ MPConfig get ] . saveKey boolValue ] ? NSOnState : NSOffState ;
self . showItem . enabled = ! [ self . passwordWindow . window isVisible ] ;
2012-05-05 13:32:09 +02:00
[ self . statusItem popUpStatusItemMenu : self . statusMenu ] ;
}
- ( IBAction ) activate : ( id ) sender {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
if ( [ [ NSApplication sharedApplication ] isActive ] )
[ self applicationDidBecomeActive : nil ] ;
else
[ [ NSApplication sharedApplication ] activateIgnoringOtherApps : YES ] ;
}
- ( IBAction ) togglePreference : ( NSMenuItem * ) sender {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
if ( sender = = useICloudItem )
2012-05-10 01:02:55 +02:00
[ self . storeManager useiCloudStore : sender . state = = NSOffState alertUser : YES ] ;
2012-05-08 13:41:54 +02:00
if ( sender = = rememberPasswordItem )
[ MPConfig get ] . rememberKey = [ NSNumber numberWithBool : ! [ [ MPConfig get ] . rememberKey boolValue ] ] ;
if ( sender = = savePasswordItem )
2012-06-08 23:46:13 +02:00
[ MPConfig get ] . saveKey = [ NSNumber numberWithBool : ! [ [ MPConfig get ] . saveKey boolValue ] ] ;
2012-05-05 00:15:51 +02:00
}
2012-05-10 01:02:55 +02:00
- ( void ) didUpdateConfigForKey : ( SEL ) configKey fromValue : ( id ) oldValue {
if ( configKey = = @ selector ( rememberKey ) )
self . rememberPasswordItem . state = [ [ MPConfig get ] . rememberKey boolValue ] ? NSOnState : NSOffState ;
if ( configKey = = @ selector ( saveKey ) )
2012-06-08 23:46:13 +02:00
self . savePasswordItem . state = [ [ MPConfig get ] . saveKey boolValue ] ? NSOnState : NSOffState ;
2012-05-10 01:02:55 +02:00
}
- ( void ) observeValueForKeyPath : ( NSString * ) keyPath ofObject : ( id ) object change : ( NSDictionary * ) change context : ( void * ) context {
2012-06-08 23:46:13 +02:00
2012-05-10 01:02:55 +02:00
if ( [ keyPath isEqualToString : @ "key" ] ) {
if ( self . key )
[ self . lockItem setEnabled : YES ] ;
else {
[ self . lockItem setEnabled : NO ] ;
[ self . passwordWindow close ] ;
}
}
}
- ( NSUndoManager * ) windowWillReturnUndoManager : ( NSWindow * ) window {
2012-06-08 23:46:13 +02:00
2012-05-10 01:02:55 +02:00
return [ [ self managedObjectContext ] undoManager ] ;
}
# pragma mark - NSApplicationDelegate
2012-03-05 22:19:05 +01:00
- ( void ) applicationDidFinishLaunching : ( NSNotification * ) aNotification {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
// Setup delegates and listeners .
[ MPConfig get ] . delegate = self ;
2012-05-05 13:32:09 +02:00
[ self addObserver : self forKeyPath : @ "key" options : 0 context : nil ] ;
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
// Initially , use iCloud .
if ( [ [ MPConfig get ] . firstRun boolValue ] )
2012-05-10 01:02:55 +02:00
[ [ self storeManager ] useiCloudStore : YES alertUser : YES ] ;
2012-06-08 23:46:13 +02:00
2012-05-05 00:15:51 +02:00
// Status item .
2012-06-08 23:46:13 +02:00
self . statusItem = [ [ NSStatusBar systemStatusBar ] statusItemWithLength : NSSquareStatusItemLength ] ;
self . statusItem . title = @ "•••" ;
self . statusItem . highlightMode = YES ;
self . statusItem . target = self ;
self . statusItem . action = @ selector ( showMenu ) ;
2012-05-05 00:15:51 +02:00
// Global hotkey .
EventHotKeyRef hotKeyRef ;
2012-06-08 23:46:13 +02:00
EventTypeSpec hotKeyEvents [ 1 ] = { { . eventClass = kEventClassKeyboard , . eventKind = kEventHotKeyPressed } } ;
OSStatus status = InstallApplicationEventHandler ( NewEventHandlerUPP ( MPHotKeyHander ) , GetEventTypeCount ( hotKeyEvents ) ,
hotKeyEvents ,
( __bridge void * ) self , NULL ) ;
if ( status ! = noErr )
err ( @ "Error installing application event handler: %d" , status ) ;
status = RegisterEventHotKey ( 35 / * p * / , controlKey + cmdKey , MPShowHotKey , GetApplicationEventTarget ( ) , 0 , & hotKeyRef ) ;
if ( status ! = noErr )
err ( @ "Error registering hotkey: %d" , status ) ;
2012-03-12 18:14:01 +01:00
}
2012-05-08 13:41:54 +02:00
- ( void ) applicationWillBecomeActive : ( NSNotification * ) notification {
2012-06-08 23:46:13 +02:00
2012-03-05 22:19:05 +01:00
if ( ! self . passwordWindow )
self . passwordWindow = [ [ MPPasswordWindowController alloc ] initWithWindowNibName : @ "MPPasswordWindowController" ] ;
2012-05-08 13:41:54 +02:00
}
- ( void ) applicationDidBecomeActive : ( NSNotification * ) notification {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
static BOOL firstTime = YES ;
if ( firstTime )
firstTime = NO ;
else
[ self . passwordWindow showWindow : self ] ;
}
- ( void ) applicationWillResignActive : ( NSNotification * ) notification {
2012-06-08 23:46:13 +02:00
2012-05-08 13:41:54 +02:00
if ( ! [ [ MPConfig get ] . rememberKey boolValue ] )
self . key = nil ;
}
2012-06-08 23:46:13 +02:00
- ( NSApplicationTerminateReply ) applicationShouldTerminate : ( NSApplication * ) sender {
2012-03-04 15:31:26 +01:00
// Save changes in the application ' s managed object context before the application terminates .
2012-06-08 23:46:13 +02:00
2012-05-07 22:18:01 +02:00
if ( ! [ self managedObjectContext ] ) {
2012-03-04 15:31:26 +01:00
return NSTerminateNow ;
}
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
if ( ! [ [ self managedObjectContext ] commitEditing ] ) {
NSLog ( @ "%@:%@ unable to commit editing to terminate" , [ self class ] , NSStringFromSelector ( _cmd ) ) ;
return NSTerminateCancel ;
}
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
if ( ! [ [ self managedObjectContext ] hasChanges ] ) {
return NSTerminateNow ;
}
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
NSError * error = nil ;
if ( ! [ [ self managedObjectContext ] save : & error ] ) {
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
// Customize this code block to include application - specific recovery steps .
BOOL result = [ sender presentError : error ] ;
if ( result ) {
return NSTerminateCancel ;
}
2012-06-08 23:46:13 +02:00
NSString * question = NSLocalizedString ( @ "Could not save changes while quitting. Quit anyway?" , @ "Quit without saves error question message" ) ;
NSString * info = NSLocalizedString ( @ "Quitting now will lose any changes you have made since the last successful save" , @ "Quit without saves error question info" ) ;
NSString * quitButton = NSLocalizedString ( @ "Quit anyway" , @ "Quit anyway button title" ) ;
2012-03-04 15:31:26 +01:00
NSString * cancelButton = NSLocalizedString ( @ "Cancel" , @ "Cancel button title" ) ;
2012-06-08 23:46:13 +02:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2012-03-04 15:31:26 +01:00
[ alert setMessageText : question ] ;
[ alert setInformativeText : info ] ;
[ alert addButtonWithTitle : quitButton ] ;
[ alert addButtonWithTitle : cancelButton ] ;
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
NSInteger answer = [ alert runModal ] ;
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
if ( answer = = NSAlertAlternateReturn ) {
return NSTerminateCancel ;
}
}
2012-06-08 23:46:13 +02:00
2012-03-04 15:31:26 +01:00
return NSTerminateNow ;
}
2012-05-10 01:02:55 +02:00
# pragma mark - UbiquityStoreManagerDelegate
2012-05-13 19:50:40 +02:00
- ( void ) ubiquityStoreManager : ( UbiquityStoreManager * ) manager didSwitchToiCloud : ( BOOL ) iCloudEnabled {
2012-06-08 23:46:13 +02:00
self . useICloudItem . state = iCloudEnabled ? NSOnState : NSOffState ;
2012-05-13 19:50:40 +02:00
self . useICloudItem . enabled = ! iCloudEnabled ;
2012-05-10 01:02:55 +02:00
}
2012-03-04 15:31:26 +01:00
@ end