aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPFavoritesController.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPFavoritesController.m')
-rw-r--r--Source/SPFavoritesController.m178
1 files changed, 167 insertions, 11 deletions
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