Skip to content

Commit

Permalink
Ask to be moved to /Applications, if not there already
Browse files Browse the repository at this point in the history
Using awesome public domain code from Potion Factory:
http://www.potionfactory.com/node/251
  • Loading branch information
ljcooke committed Sep 19, 2009
1 parent 3300282 commit 6df771f
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 364 deletions.
533 changes: 170 additions & 363 deletions English.lproj/MainMenu.nib/designable.nib

Large diffs are not rendered by default.

Binary file modified English.lproj/MainMenu.nib/keyedobjects.nib
Binary file not shown.
4 changes: 3 additions & 1 deletion Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<key>CFBundleIconFile</key>
<string>APPL</string>
<key>CFBundleIdentifier</key>
<string>ws.boxofjunk.Ryder</string>
<string>ws.boxofjunk.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
Expand All @@ -24,5 +24,7 @@
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
</dict>
</plist>
11 changes: 11 additions & 0 deletions PFMoveApplication.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// PFMoveApplication.h
// LetsMove
//
// Created by Andy Kim at Potion Factory LLC on 9/17/09
//
// The contents of this file are dedicated to the public domain.

#import <Foundation/Foundation.h>

extern void PFMoveToApplicationsFolderIfNecessary();
108 changes: 108 additions & 0 deletions PFMoveApplication.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// PFMoveApplication.m
// LetsMove
//
// Created by Andy Kim at Potion Factory LLC on 9/17/09
//
// The contents of this file are dedicated to the public domain.

#import "PFMoveApplication.h"

static NSString *AlertSuppressKey = @"moveToApplicationsFolderAlertSuppress";

void PFMoveToApplicationsFolderIfNecessary()
{
// Skip if user supressed the alert before
if ([[NSUserDefaults standardUserDefaults] boolForKey:AlertSuppressKey]) return;

// Path of the bundle
NSString *path = [[NSBundle mainBundle] bundlePath];

// Get all Applications directories, most importantly ~/Applications
NSArray *allApplicationsDirectories = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES);

// If the application is already in some Applications directory, skip.
for (NSString *appDirPath in allApplicationsDirectories) {
if ([path hasPrefix:appDirPath]) return;
}

// Since we are good to go, get /Applications
NSString *applicationsDirectory = [NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSLocalDomainMask, YES) lastObject];
if (applicationsDirectory == nil) {
NSLog(@"ERROR -- Could not find the Applications directory");
goto fail;
}

NSString *appBundleName = [path lastPathComponent];
NSError *error = nil;

// Open up the alert
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:NSLocalizedString(@"Move to Applications folder?", nil)];
[alert setInformativeText:NSLocalizedString(@"I can move myself to the Applications folder if you'd like. This will keep your Downloads folder uncluttered.", nil)];
[alert setShowsSuppressionButton:YES];
[[[alert suppressionButton] cell] setControlSize:NSSmallControlSize];
[[[alert suppressionButton] cell] setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
[alert addButtonWithTitle:NSLocalizedString(@"Move to Applications Folder", nil)];
[alert addButtonWithTitle:NSLocalizedString(@"Do Not Move", nil)];

if ([alert runModal] == NSAlertFirstButtonReturn) {
NSLog(@"Moving myself to the Applications folder");
NSFileManager *fm = [NSFileManager defaultManager];
NSString *destinationPath = [applicationsDirectory stringByAppendingPathComponent:appBundleName];

// If a copy already exists in /Applications, put it in the Trash
if ([fm fileExistsAtPath:destinationPath]) {
if (![[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation
source:applicationsDirectory
destination:@""
files:[NSArray arrayWithObject:appBundleName]
tag:NULL]) {
NSLog(@"ERROR -- Could not trash '%@'", destinationPath);
goto fail;
}
}

// Copy myself to /Applications
if (![fm copyItemAtPath:path toPath:destinationPath error:&error]) {
NSLog(@"ERROR -- Could not copy myself to /Applications (%@)", error);
goto fail;
}

// Put myself in Trash
if (![[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation
source:[path stringByDeletingLastPathComponent]
destination:@""
files:[NSArray arrayWithObject:appBundleName]
tag:NULL]) {
NSLog(@"ERROR -- Could not trash '%@'", path);
goto fail;
}

// Relaunch
NSString *executableName = [[[NSBundle mainBundle] executablePath] lastPathComponent];
NSString *relaunchPath = [destinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"Contents/MacOS/%@", executableName]];

[NSTask launchedTaskWithLaunchPath:relaunchPath
arguments:[NSArray arrayWithObjects:destinationPath,
[NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]],
nil]]; // The %d is not a 64-bit bug. The call to processIdentifier returns an int
[NSApp terminate:nil];
}
else {
// Save the alert suppress preference if checked
if ([[alert suppressionButton] state] == NSOnState) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:AlertSuppressKey];
}
}

return;

fail:
{
// Show failure message
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:NSLocalizedString(@"Could not move to Applications folder", nil)];
[alert runModal];
}
}
12 changes: 12 additions & 0 deletions Ryder.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
8D81FFD41065048500F953BE /* RyderAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D81FFD31065048500F953BE /* RyderAppDelegate.m */; };
8DB3753A0EC4E4BE007B2A1B /* RyderWindowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB375390EC4E4BE007B2A1B /* RyderWindowView.m */; };
8DB375530EC4EBC0007B2A1B /* RyderNamer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB375520EC4EBC0007B2A1B /* RyderNamer.m */; };
8DB3762B0EC4FDD0007B2A1B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8DB376290EC4FDD0007B2A1B /* Localizable.strings */; };
8DB3765F0EC50188007B2A1B /* RyderNameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB3765E0EC50188007B2A1B /* RyderNameView.m */; };
8DB376D70EC509B3007B2A1B /* RyderController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB376D60EC509B3007B2A1B /* RyderController.m */; };
8DD68FAC1065027500652D29 /* PFMoveApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DD68FAB1065027500652D29 /* PFMoveApplication.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -35,6 +37,8 @@
8D0A838B0EC653F300957EE2 /* Credits.rtfd */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; path = Credits.rtfd; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Ryder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ryder.app; sourceTree = BUILT_PRODUCTS_DIR; };
8D81FFD21065048500F953BE /* RyderAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RyderAppDelegate.h; sourceTree = "<group>"; };
8D81FFD31065048500F953BE /* RyderAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RyderAppDelegate.m; sourceTree = "<group>"; };
8DB375380EC4E4BE007B2A1B /* RyderWindowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RyderWindowView.h; sourceTree = "<group>"; };
8DB375390EC4E4BE007B2A1B /* RyderWindowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RyderWindowView.m; sourceTree = "<group>"; };
8DB375510EC4EBC0007B2A1B /* RyderNamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RyderNamer.h; sourceTree = "<group>"; };
Expand All @@ -44,6 +48,8 @@
8DB3765E0EC50188007B2A1B /* RyderNameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RyderNameView.m; sourceTree = "<group>"; };
8DB376D50EC509B3007B2A1B /* RyderController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RyderController.h; sourceTree = "<group>"; };
8DB376D60EC509B3007B2A1B /* RyderController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RyderController.m; sourceTree = "<group>"; };
8DD68FAA1065027500652D29 /* PFMoveApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFMoveApplication.h; sourceTree = "<group>"; };
8DD68FAB1065027500652D29 /* PFMoveApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFMoveApplication.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -61,6 +67,8 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
8DD68FAA1065027500652D29 /* PFMoveApplication.h */,
8DD68FAB1065027500652D29 /* PFMoveApplication.m */,
8DB375380EC4E4BE007B2A1B /* RyderWindowView.h */,
8DB375390EC4E4BE007B2A1B /* RyderWindowView.m */,
8DB375510EC4EBC0007B2A1B /* RyderNamer.h */,
Expand All @@ -69,6 +77,8 @@
8DB3765E0EC50188007B2A1B /* RyderNameView.m */,
8DB376D50EC509B3007B2A1B /* RyderController.h */,
8DB376D60EC509B3007B2A1B /* RyderController.m */,
8D81FFD21065048500F953BE /* RyderAppDelegate.h */,
8D81FFD31065048500F953BE /* RyderAppDelegate.m */,
);
name = Classes;
sourceTree = "<group>";
Expand Down Expand Up @@ -207,6 +217,8 @@
8DB375530EC4EBC0007B2A1B /* RyderNamer.m in Sources */,
8DB3765F0EC50188007B2A1B /* RyderNameView.m in Sources */,
8DB376D70EC509B3007B2A1B /* RyderController.m in Sources */,
8DD68FAC1065027500652D29 /* PFMoveApplication.m in Sources */,
8D81FFD41065048500F953BE /* RyderAppDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
9 changes: 9 additions & 0 deletions RyderAppDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import <Cocoa/Cocoa.h>

@interface RyderAppDelegate : NSObject {
NSWindow *window;
}

@property (assign) IBOutlet NSWindow *window;

@end
15 changes: 15 additions & 0 deletions RyderAppDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#import "RyderAppDelegate.h"
#import "PFMoveApplication.h"

@implementation RyderAppDelegate

@synthesize window;

- (void) applicationWillFinishLaunching:(NSNotification*)notification
{
[window center];

PFMoveToApplicationsFolderIfNecessary();
}

@end

0 comments on commit 6df771f

Please sign in to comment.