aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPAppController.m4
-rw-r--r--Source/SPConstants.h20
-rw-r--r--Source/SPConstants.m16
-rw-r--r--Source/SPFavoritesController.h20
-rw-r--r--Source/SPFavoritesController.m178
-rw-r--r--Source/SPPreferencesUpgrade.h1
-rw-r--r--Source/SPPreferencesUpgrade.m48
7 files changed, 271 insertions, 16 deletions
diff --git a/Source/SPAppController.m b/Source/SPAppController.m
index c6c5c44a..a1f8b292 100644
--- a/Source/SPAppController.m
+++ b/Source/SPAppController.m
@@ -31,6 +31,7 @@
#import "SPDataImport.h"
#import "SPEncodingPopupAccessory.h"
#import "SPWindowController.h"
+#import "SPPreferencesUpgrade.h"
#import <PSMTabBar/PSMTabBarControl.h>
#import <Sparkle/Sparkle.h>
@@ -61,6 +62,8 @@
// Register application defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PreferenceDefaults" ofType:@"plist"]]];
+ // Migrate old connection favorites to the app's support directory (only uncomment when ready)
+ //SPMigrateConnectionFavoritesData();
}
/**
@@ -68,7 +71,6 @@
*/
- (void)awakeFromNib
{
-
// Register url scheme handle
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
diff --git a/Source/SPConstants.h b/Source/SPConstants.h
index 651a68c5..6e20a5b3 100644
--- a/Source/SPConstants.h
+++ b/Source/SPConstants.h
@@ -241,6 +241,7 @@ extern NSString *SPBundleSupportFolder;
extern NSString *SPDataSupportFolder;
// Preference key constants
+//
// General Prefpane
extern NSString *SPDefaultFavorite;
extern NSString *SPSelectLastFavoriteUsed;
@@ -365,14 +366,13 @@ extern NSString *SPLastImportIntoNewTableEncoding;
extern NSString *SPLastImportIntoNewTableType;
extern NSString *SPGlobalValueHistory;
-
// URLs
extern NSString *SPDonationsURL;
extern NSString *SPMySQLSearchURL;
extern NSString *SPDevURL;
// Toolbar constants
-
+//
// Main window toolbar
extern NSString *SPMainToolbarDatabaseSelection;
extern NSString *SPMainToolbarHistoryNavigation;
@@ -396,3 +396,19 @@ extern NSString *SPPreferenceToolbarAutoUpdate;
extern NSString *SPPreferenceToolbarNetwork;
extern NSString *SPPreferenceToolbarEditor;
extern NSString *SPPreferenceToolbarShortcuts;
+
+// Connection favorite keys
+extern NSString *SPFavoritesRootKey;
+extern NSString *SPFavoriteChildrenKey;
+extern NSString *SPFavoriteIDKey;
+extern NSString *SPFavoriteNameKey;
+extern NSString *SPFavoriteDatabaseKey;
+extern NSString *SPFavoriteHostKey;
+extern NSString *SPFavoritePortKey;
+extern NSString *SPFavoriteUserKey;
+extern NSString *SPFavoriteTypeKey;
+extern NSString *SPFavoriteSocketKey;
+extern NSString *SPFavoriteSSHHostKey;
+extern NSString *SPFavoriteSSHPortKey;
+extern NSString *SPFavoriteSSHUserKey;
+extern NSString *SPFavoriteSSHKeyLocationKey;
diff --git a/Source/SPConstants.m b/Source/SPConstants.m
index bfacad2d..17e20849 100644
--- a/Source/SPConstants.m
+++ b/Source/SPConstants.m
@@ -216,3 +216,19 @@ NSString *SPPreferenceToolbarAutoUpdate = @"SPPreferenceToolbarAutoUpda
NSString *SPPreferenceToolbarNetwork = @"SPPreferenceToolbarNetwork";
NSString *SPPreferenceToolbarEditor = @"SPPreferenceToolbarEditor";
NSString *SPPreferenceToolbarShortcuts = @"SPPreferenceToolbarShortcuts";
+
+// Connection favorite keys
+NSString *SPFavoritesRootKey = @"Favorites Root";
+NSString *SPFavoriteChildrenKey = @"Children";
+NSString *SPFavoriteIDKey = @"id";
+NSString *SPFavoriteNameKey = @"name";
+NSString *SPFavoriteDatabaseKey = @"database";
+NSString *SPFavoriteHostKey = @"host";
+NSString *SPFavoritePortKey = @"port";
+NSString *SPFavoriteUserKey = @"user";
+NSString *SPFavoriteTypeKey = @"type";
+NSString *SPFavoriteSocketKey = @"socket";
+NSString *SPFavoriteSSHHostKey = @"sshHost";
+NSString *SPFavoriteSSHPortKey = @"sshPort";
+NSString *SPFavoriteSSHUserKey = @"sshUser";
+NSString *SPFavoriteSSHKeyLocationKey = @"sshKeyLocationEnabled";
diff --git a/Source/SPFavoritesController.h b/Source/SPFavoritesController.h
index 5e9d714c..bb698d16 100644
--- a/Source/SPFavoritesController.h
+++ b/Source/SPFavoritesController.h
@@ -25,11 +25,27 @@
#import "SPSingleton.h"
+/**
+ * @class SPFavoritesController SPFavoritesController.h
+ *
+ * @author Stuart Connolly http://stuconnolly.com/
+ *
+ * Connection favorites controller that provides a single point of access for managing the user's connection
+ * favorites in memory and on disk.
+ */
@interface SPFavoritesController : SPSingleton
{
- NSDictionary *favorties;
+ NSDictionary *favorites;
}
-- (SPFavoritesController *)sharedFavoritesController;
+/**
+ * @property favorites Favorites data dictionary
+ */
+@property (readonly) NSDictionary *favorites;
+
++ (SPFavoritesController *)sharedFavoritesController;
+
+- (void)saveFavorites;
+- (void)reloadFavoritesWithSave:(BOOL)save;
@end
diff --git a/Source/SPFavoritesController.m b/Source/SPFavoritesController.m
index dacd35dc..85f4e587 100644
--- a/Source/SPFavoritesController.m
+++ b/Source/SPFavoritesController.m
@@ -27,8 +27,41 @@
static SPFavoritesController *sharedFavoritesController = nil;
+@interface SPFavoritesController (PrivateAPI)
+
+- (void)_loadFavorites;
+
+@end
+
@implementation SPFavoritesController
+@synthesize favorites;
+
+#pragma mark -
+#pragma mark Initialisation
+
++ (id)allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ return [[self sharedFavoritesController] retain];
+ }
+}
+
+- (id)init
+{
+ if ((self = [super init])) {
+
+ favorites = nil;
+
+ [self _loadFavorites];
+ }
+
+ return self;
+}
+
+#pragma mark -
+#pragma mark Public API
+
/**
* Returns the shared favorites controller.
*/
@@ -43,20 +76,143 @@ static SPFavoritesController *sharedFavoritesController = nil;
return sharedFavoritesController;
}
-+ (id)allocWithZone:(NSZone *)zone
-{
- @synchronized(self) {
- return [[self sharedFavoritesController] retain];
- }
+/**
+ * Saves the current favorites dictionary in memory to disk. Note that the current favorites data file is moved
+ * rather than overwritten in the event that we can't write the new file, the original can simply be restored.
+ * This method also does a lot of error checking to ensure we don't lose the user's favorites data.
+ */
+- (void)saveFavorites
+{
+ NSError *error = nil;
+ NSString *errorString = nil;
+
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+
+ NSString *dataPath = [fileManager applicationSupportDirectoryForSubDirectory:SPDataSupportFolder error:&error];
+
+ if (error) {
+ NSLog(@"Error retrieving data directory path: %@", [error localizedDescription]);
+ return;
+ }
+
+ NSString *favoritesFile = [dataPath stringByAppendingPathComponent:SPFavoritesDataFile];
+ NSString *favoritesBackupFile = [dataPath stringByAppendingPathComponent:[@"~" stringByAppendingString:SPFavoritesDataFile]];
+
+ if ([fileManager fileExistsAtPath:favoritesFile]) {
+ [fileManager moveItemAtPath:favoritesFile toPath:favoritesBackupFile error:&error];
+ }
+
+ if (error) {
+ NSLog(@"Unable to backup (move) existing favorites data file during save. Deleting instead: %@", [error localizedDescription]);
+
+ error = nil;
+
+ if (![fileManager removeItemAtPath:favoritesFile error:&error] && error) {
+ NSLog(@"Unable to delete existing favorites data file during save. Something is wrong, permissions perhaps: %@", [error localizedDescription]);
+ return;
+ }
+ }
+ else {
+ NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:favorites
+ format:NSPropertyListXMLFormat_v1_0
+ errorDescription:&errorString];
+
+ if (plistData) {
+ [plistData writeToFile:favoritesFile options:NSAtomicWrite error:&error];
+
+ if (error) {
+ NSLog(@"Error writing favorites data. Restoring backup if available: %@", [error localizedDescription]);
+
+ [fileManager moveItemAtPath:favoritesBackupFile toPath:favoritesFile error:NULL];
+ }
+ else {
+ [fileManager removeItemAtPath:favoritesBackupFile error:NULL];
+ }
+ }
+ else if (errorString) {
+ NSLog(@"Error converting favorites data to plist format: %@", errorString);
+
+ [errorString release];
+ }
+ }
}
-- (id)init
+/**
+ * Reloads the favorites data from disk with the option to save before doing so.
+ *
+ * @param save Indicates whether the current favorites data in memory should be saved to disk before being
+ * reloaded. Specifying NO effectively discards any changes since the last save operation.
+ */
+- (void)reloadFavoritesWithSave:(BOOL)save
{
- if ((self = [super init])) {
-
- }
-
- return self;
+ if (save) [self saveFavorites];
+
+ if (favorites) [self _loadFavorites];
+}
+
+#pragma mark -
+#pragma mark Private API
+
+/**
+ * Attempts to load the users connection favorites from ~/Library/Application Support/Sequel Pro/Data/Favorites.plist
+ * If the 'Data' directory doesn't already exist it will be created, as well as an empty favorites plist.
+ */
+- (void)_loadFavorites
+{
+ NSError *error = nil;
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+
+ if (favorites) [favorites release], favorites = nil;
+
+ NSString *dataPath = [fileManager applicationSupportDirectoryForSubDirectory:SPDataSupportFolder error:&error];
+
+ if (error) {
+ NSLog(@"Error retrieving data directory path: %@", [error localizedDescription]);
+ return;
+ }
+
+ NSString *favoritesFile = [dataPath stringByAppendingPathComponent:SPFavoritesDataFile];
+
+ if ([fileManager fileExistsAtPath:favoritesFile]) {
+ favorites = [[NSDictionary alloc] initWithContentsOfFile:favoritesFile];
+ }
+ else {
+ NSDictionary *newFavorites = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSArray array] forKey:SPFavoriteChildrenKey] forKey:SPFavoritesRootKey];
+
+ NSError *error = nil;
+ NSString *errorString = nil;
+
+ NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:newFavorites
+ format:NSPropertyListXMLFormat_v1_0
+ errorDescription:&errorString];
+ if (plistData) {
+ [plistData writeToFile:favoritesFile options:NSAtomicWrite error:&error];
+
+ if (error) {
+ NSLog(@"Error writing default favorites data: %@", [error localizedDescription]);
+ }
+ }
+ else if (errorString) {
+ NSLog(@"Error converting default favorites data to plist format: %@", errorString);
+
+ [errorString release];
+ return;
+ }
+
+ favorites = newFavorites;
+ }
+}
+
+#pragma mark -
+
+/**
+ * Dealloc.
+ */
+- (void)dealloc
+{
+ if (favorites) [favorites release], favorites = nil;
+
+ [super dealloc];
}
@end
diff --git a/Source/SPPreferencesUpgrade.h b/Source/SPPreferencesUpgrade.h
index 03241880..33691da5 100644
--- a/Source/SPPreferencesUpgrade.h
+++ b/Source/SPPreferencesUpgrade.h
@@ -33,5 +33,6 @@
@interface SPPreferencesUpgrade : NSObject
void SPApplyRevisionChanges(void);
+void SPMigrateConnectionFavoritesData(void);
@end
diff --git a/Source/SPPreferencesUpgrade.m b/Source/SPPreferencesUpgrade.m
index 887289e7..081be36a 100644
--- a/Source/SPPreferencesUpgrade.m
+++ b/Source/SPPreferencesUpgrade.m
@@ -297,4 +297,52 @@ void SPApplyRevisionChanges(void)
[prefs setObject:[NSNumber numberWithInteger:currentVersionNumber] forKey:SPLastUsedVersion];
}
+/**
+ * Attempts to migrate the user's connection favorites from their preference file to the new Favaorites
+ * plist in the application's support 'Data' directory.
+ */
+void SPMigrateConnectionFavoritesData(void)
+{
+ NSError *error = nil;
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+
+ NSString *dataPath = [fileManager applicationSupportDirectoryForSubDirectory:SPDataSupportFolder error:&error];
+
+ if (error) {
+ NSLog(@"Error loading favorites: %@", [error localizedDescription]);
+ return;
+ }
+
+ NSString *favoritesFile = [dataPath stringByAppendingPathComponent:SPFavoritesDataFile];
+
+ // Only proceed if the new favorites plist doesn't already exist
+ if (![fileManager fileExistsAtPath:favoritesFile]) {
+ NSDictionary *newFavorites = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[[NSUserDefaults standardUserDefaults] objectForKey:SPFavorites] forKey:SPFavoriteChildrenKey] forKey:SPFavoritesRootKey];
+
+ NSError *error = nil;
+ NSString *errorString = nil;
+
+ NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:newFavorites
+ format:NSPropertyListXMLFormat_v1_0
+ errorDescription:&errorString];
+ if (plistData) {
+ [plistData writeToFile:favoritesFile options:NSAtomicWrite error:&error];
+
+ if (error) {
+ NSLog(@"Error migrating favorites data: %@", [error localizedDescription]);
+ }
+ else {
+ // Only uncomment when migration is complete
+ //[[NSUserDefaults standardUserDefaults] removeObjectForKey:SPFavorites];
+ }
+ }
+ else if (errorString) {
+ NSLog(@"Error converting migrating favorites data to plist format: %@", errorString);
+
+ [errorString release];
+ return;
+ }
+ }
+}
+
@end