# RubyFrictionlessAppDelegate.rb # RubyFrictionless # # Created by Pierce T. Wetter III on 4/3/07. # Copyright __MyCompanyName__ 2007 . All rights reserved. #require 'osx/cocoa' framework 'CoreData' #OSX.require_framework('CoreGraphics') framework 'SyncServices' #OSX.require_framework('ILCrashReporter') require 'ToodleDoSyncer.rb' class AppDelegate < NSObject attr_accessor :contextWindow,:browserWindows, :preferenceWindow, :contextWindowC, :templatesWindow def applicationDidFinishLaunching(notification) @@appDelegate=self self.performSelector('openAllWindows', withObject: nil, afterDelay: 0.0) @doSyncing = NSUserDefaults.standardUserDefaults.boolForKey('dotMacSyncing') syncClient.setSyncAlertHandler(self,selector:'client:mightWantToSyncEntityNames:') if @doSyncing #ILCrashReporter.defaultReporter.launchReporterForCompany_reportAddr("TwinForces","pierce@twinforces.com") #RuNSNotificationCenter.defaultCenter.addObserver_selector_name_object(self,'managedObjectContextDidChange:',NSManagedObjectContextObjectsDidChangeNotification,nil) end def openAllWindows actions=managedObjectContext.objectsForEntityNamed('Action') actions.each do |a| a.appLaunch end unless actions && actions.count > 0 %w{Work Home Errands Online Email Phone Waiting Weekend}.each do |cname| context=NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Context",managedObjectContext) managedObjectContext.processPendingChanges context.name=cname end [ "Professional @Work :area :note This is an area/role to hold your job related actions so you can easily focus on just those.", "Personal @Home :area :note This is an area/role to hold your home related actions so you can easily focus on just those.", "Spouse > Personal @Home :area :note This is possibly one of the roles you play in life. ", "Parent > Personal @Home :area :note This is possibly one of the roles you play in life.", "Child > Personal @Home :area :note This is possibly one of the roles you play in life.", "Homeowner > Personal @Home :area :note This is a good place to hold home maintenance tasks.", "Employee > Professional @Work :area :note To Quote Bob Dylan, you gotta serve somebody.", "Manager > Professional @Work :area :note Have people you have to manage?", "Coworker > Professional @Work :area :note I'm sure you work with people.", "Sample Project > Professional :note A project is anything with child actions or child projects", "Sample Action > Sample Project :note A Tasks is anything without any children", "Another Action > Sample Project :note A Tasks is anything without any children", ].each do |aname| newAction= NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Action",managedObjectContext) newAction.smartName=aname managedObjectContext.processPendingChanges end end actions=managedObjectContext.objectWithValue_forKey_entityNamed("YES","noteOpen",'Action') if actions && actions.count > 0 actions.each {|a| a.openJustNotes} end newBrowserWindow(self) end def newQuickEntryWindow(sender) end def buildPreferenceWindow @preferenceWindow=AMPreferenceWindowController.alloc.initWithAutosaveName("Preferences") defaults={} gp=GeneralPreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) sp=SparklePreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) tp=TwitterPreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) tdp=ToodleDoPreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) mp=MailPreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) syp=SyncPreferences.alloc.initWithController_appDelegate(@preferenceWindow,self) end def preferenceWindow buildPreferenceWindow unless @preferenceWindow @preferenceWindow end def openPreferences(sender) preferenceWindow.showWindow(self) preferenceWindow.window.makeKeyAndOrderFront(self) end def managedObjectModel return @managedObjectModel if @managedObjectModel allBundles = NSMutableSet.alloc.init url = NSURL.fileURLWithPath(NSBundle.mainBundle.pathForResource("RubyFrictionless_DataModel",ofType:"momd"),isDirectory:false) @managedObjectModel = NSManagedObjectModel.alloc.initWithContentsOfURL(url) return @managedObjectModel end # Change this path/code to point to your App's data store. def applicationSupportFolder NSHomeDirectory().stringByAppendingPathComponent(File.join('Library', 'Application Support', 'Frictionless')) end def managedObjectContext return @managedObjectContext if @managedObjectContext fileManager = NSFileManager.defaultManager storeFolder = applicationSupportFolder unless fileManager.fileExistsAtPath(storeFolder, isDirectory:nil) fileManager.createDirectoryAtPath(storeFolder, attributes:nil) end @shouldRefreshSync=false oldurl = NSURL.fileURLWithPath(storeFolder.stringByAppendingPathComponent("Frictionless.xml")) url = NSURL.fileURLWithPath(storeFolder.stringByAppendingPathComponent("Frictionless.sqlite3")) if (fileManager.fileExistsAtPath(storeFolder.stringByAppendingPathComponent("Frictionless.xml")) && !fileManager.fileExistsAtPath(storeFolder.stringByAppendingPathComponent("Frictionless.sqlite3"))) then print "migrating from XML store to SQL store\n" mappingModel=NSMappingModel.mappingModelFromBundles(NSArray.arrayWithObject(NSBundle.mainBundle()),forSourceModel:managedObjectModel,destinationModel:managedObjectModel) if (!mappingModel) then print "auto mapping didn't work\n" nopurl = NSURL.fileURLWithPath(NSBundle.mainBundle.pathForResource_ofType("XMLupdate",isDirectory:"xcmappingmodel"),false) mappingModel=NSMappingModel.alloc.initWithContentsOfURL(nopurl) end if (mappingModel) then print "mapping model: #{mappingModel}\n" migrateManager= NSMigrationManager.alloc.initWithSourceModel(managedObjectModel,destinationModel:managedObjectModel) print "migrateManager: #{migrateManager}\n" result,error=migrateManager.migrateStoreFromURL( oldurl,type:NSXMLStoreType,options:nil,withMappingModel:mappingModel,toDestinationURL:url,destinationType:NSSQLiteStoreType,destinationOptions:nil) print "migration result, error: #{result},#{error}\n" else print "no mapping model!\n" exit end end unless fileManager.fileExistsAtPath(storeFolder.stringByAppendingPathComponent("Frictionless.sqlite3")) @shouldRefreshSync=true @storeMetaDeta=nil end coordinator = NSPersistentStoreCoordinator.alloc.initWithManagedObjectModel(managedObjectModel) # FIXME: cannot get errors options = { :NSMigratePersistentStoresAutomaticallyOption => NSNumber.numberWithBool(true) } persistentStore=coordinator.addPersistentStoreWithType("SQLite", configuration:nil, URL:url, options:options, error:error) if persistentStore then @managedObjectContext = NSManagedObjectContext.alloc.init @managedObjectContext.setPersistentStoreCoordinator(coordinator) fastsyncurl= NSURL.fileURLWithPath(storeFolder.stringByAppendingPathComponent("FrictionlessFastSync.fastSync")) coordinator.setStoresFastSyncDetailsAtURL(fastsyncurl,forPersistentStore:persistentStore) else NSApplication.sharedApplication.presentError(error) end $managedObjectContext=@managedObjectContext; return @managedObjectContext end def syncClient clientIdentifier=NSBundle.mainBundle.bundleIdentifier syncManager = ISyncManager.sharedManager client= syncManager.clientWithIdentifier(clientIdentifier) if (client == nil) if (syncManager.registerSchemaWithBundlePath( NSBundle.mainBundle.pathForResource_ofType("FrictionlessSyncSchema","syncschema"))) path=NSBundle.mainBundle.pathForResource_ofType("RubySelfClient","plist") client=syncManager.registerClientWithIdentifier_descriptionFilePath(clientIdentifier,path) client.setShouldSynchronize_withClientsOfType(true, ISyncClientTypeApplication) client.setShouldSynchronize_withClientsOfType(true, ISyncClientTypeDevice) client.setShouldSynchronize_withClientsOfType(true, ISyncClientTypeServer) client.setShouldSynchronize_withClientsOfType(true, ISyncClientTypePeer) end end client end def client(client,mightWantToSyncEntityNames: names) print "client syncing #{names}\n" saveAction(self) end def windowWillReturnUndoManager(window) return managedObjectContext.undoManager end def showContextWindow(sender) app=NSApplication.sharedApplication @contextWindowC=NSWindowController.alloc.initWithWindowNibName_owner("ContextsWindow",self) if not @contextWindow @contextWindowC.showWindow(self) @contextWindow.makeKeyAndOrderFront(nil) end def showTemplatesWindow(sender) app=NSApplication.sharedApplication @templatesWindowC=NSWindowController.alloc.initWithWindowNibName_owner("Templates",self) if not @templatesWindow @templatesWindowC.showWindow(self) #@templatesWindowC.makeKeyAndOrderFront(nil) end def newBrowserWindow(sender) @browserWindows ||=[] ab=ActionBrowser.alloc.init ab.setup(self) @browserWindows << ab ab end def newActionFocusWindow(action) return newFocusWindow([action]) end def newFocusWindow(focus) @browserWindows ||=[] ab=ActionBrowser.alloc.init ab.setup(self,focus) @browserWindows << ab ab end def newHelpWindow(sender) hw=HelpWindow.alloc.init hw.setup(self,nil) hw end def syncAction(sender) return unless @doSyncing #managedObjectContext.persistentStoreCoordinator.syncWithClient_inBackground_handler_error(syncClient,true,self,error) if syncClient print "starting sync\n" begin error=managedObjectContext.persistentStoreCoordinator.syncWithClient_inBackground_handler_error(syncClient,false,self) if syncClient rescue print $! end print "sync finished!\n" end def toodleSync(sender) @toodle=ToodleDoSyncer.alloc.init unless @toodle @toodle.syncAll(managedObjectContext) end def mailSync(sender) @mailSyncer=MailSyncer.alloc.init unless @mailSyncer @mailSyncer.syncMail(managedObjectContext) end def toodleClean(sender) @toodle=ToodleDoSyncer.alloc.init unless @toodle @toodle.clean(managedObjectContext) end def saveAction(sender) error = nil unless managedObjectContext.save?(error) NSApplication.sharedApplication.presentError(error) return end syncAction(sender) if @doSyncing end def saveInMainThread(sender) self.performSelector_withObject_afterDelay('saveAction:',sender,0.0) end def managedObjectContextsToMonitorWhenSyncingPersistentStoreCoordinator(psc) print "moctoMonitor\n" return [managedObjectContext] end def managedObjectContextsToReloadAfterSyncingPersistentStoreCoordinator(psc) print "moctoReload\n" return [managedObjectContext] end def applicationShouldTerminate(sender) reply = NSTerminateNow context = managedObjectContext if context if context.commitEditing? # FIXME: cannot get errors error = OCObject.new unless context.save?(error) error.userInfo.valueForKey("NSDetailedErrors").each { |e| print e.userInfo} errorResult = NSApplication.sharedApplication.presentError?(error) if errorResult reply = NSTerminateCancel else alertReturn = OSX.NSRunAlertPanel(nil, "Could not save changes while quitting. Quit anyway?", "Quit anyway", "Cancel", nil) if alertReturn == NSAlertAlternateReturn reply = NSTerminateCancel end end end else reply = NSTerminateCancel end end return reply end def statusesReceived_forRequest(statuses,identifier) print statuses end def directMessagesReceived_messages_forRequest(messages,identifier) print messages end def userInfoReceived_forRequest(userInfo,identifier) print userInfo end def requestSucceeded(requestIdentifier) print requestIdentifier end def requestFailed_withError(requestIdentifier,error) print "Twitter request failed! (#{requestIdentifier}) Error: #{error.localizedDescription} (#{error.userInfo})" end def persistentStoreCoordinatorShouldStartSyncing?(psc) print "persistentStoreCoordinatorShouldStartSyncing?\n" @syncChanges=false return false # don't ssince for now. end # def persistentStoreCoordinatorShouldStartSyncing(psc) # print "persistentStoreCoordinatorShouldStartSyncing\n" # return true # end def persistentStoreCoordinator_willPushChangesInSyncSession(psc,session) print "persistentStoreCoordinator_willPushChangesInSyncSession\n" end def persistentStoreCoordinator_didPushChangesInSyncSession(psc,session) print "persistentStoreCoordinator_didPushChangesInSyncSession\n" @syncChanges=true end def persistentStoreCoordinator_willPullChangesInSyncSession(psc,session) print "persistentStoreCoordinator_willPullChangesInSyncSession\n" end def persistentStoreCoordinator_didPullChangesInSyncSession(psc,session) print "persistentStoreCoordinator_didPullChangesInSyncSession\n" end def persistentStoreCoordinator_didFinishSyncSession(psc,session) print "persistentStoreCoordinator_didFinishSyncSession\n" if @syncChanges then print "resetting action caches\n" actions=managedObjectContext.objectsForEntityNamed('Action') actions.each do |a| #fix any bad parents a.reset_caches a.setParent(nil) if a.parent? and a.parent.hasAncestor?(a) end end end def persistentStoreCoordinator_didCancelSyncSession_error(psc,session,error) print "persistentStoreCoordinator_didCancelSyncSession_error\n" end def persistentStoreCoordinator_willPushRecord_forManagedObject_inSyncSession(psc,record,object,session) #print "pushing #{record} for object #{object}\n" @syncChanges=true record end def persistentStoreCoordinator_willDeleteRecordRecordWithIdentifier_inSyncSession(psc,record,object,session) print "persistentStoreCoordinator_willDeleteRecordRecordWithIdentifier_inSyncSession\n" @syncChanges=true return true end def persistentStoreCoordinator_willApplyChange_toManagedObject_inSyncSession(psc,change,object,session) print "changes #{change} for object #{object}\n" object.syncON if object @syncChanges=true change end def persistentStoreCoordinator_didApplyChange_toManagedObject_inSyncSession(psc,change,object,session) print "persistentStoreCoordinator_didApplyChange_toManagedObject_inSyncSession\n" object.syncOFF if object if (object && object.entity.name=="Action") object.setParent(nil) if object.parent? and object.hasAncestor?(object) end end def persistentStoreCoordinator_didCommitChanges_toManagedObject_inSyncSession(psc,change,object,session) print "persistentStoreCoordinator_didCommitChanges_toManagedObject_inSyncSession\n" @syncChanges=true end end