Skip to content

Commit 7939a78

Browse files
committed
Found a couple dozen files which were in my BkmkMgrs project directory that should have been in my reusable code folders. Very tedious to move them to proper locations, then re-pointing in Xcode. I hope I didn’t screw anything up. Also looks like a couple checkboxes for new files which I neglected to switch on in previous commit.
1 parent a206c21 commit 7939a78

11 files changed

+478
-1
lines changed

SSYDeallocDetector.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#import <Cocoa/Cocoa.h>
2+
3+
4+
/*!
5+
@brief An instance of this class will send a given invocation
6+
during its deallocation.
7+
8+
@details We leave the usage of this class to your imagination!
9+
*/
10+
@interface SSYDeallocDetector : NSObject {
11+
NSInvocation* m_invocation ;
12+
}
13+
14+
@property (retain) NSInvocation* invocation ;
15+
16+
+ (SSYDeallocDetector*)detectorWithInvocation:(NSInvocation*)invocation ;
17+
18+
@end

SSYDeallocDetector.m

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#import "SSYDeallocDetector.h"
2+
3+
4+
@implementation SSYDeallocDetector
5+
6+
@synthesize invocation = m_invocation ;
7+
8+
#if 0
9+
#warning Logging R&R of Dealloc Detector
10+
- (id)retain {
11+
NSLog(@"75133: Retained SSYDeallocDetector %p", self) ;
12+
return [super retain] ;
13+
}
14+
15+
- (oneway void)release {
16+
NSLog(@"75143: Released SSYDeallocDetector %p", self) ;
17+
[super release] ;
18+
}
19+
#endif
20+
21+
- (void)dealloc {
22+
[[self invocation] invoke] ;
23+
[m_invocation release] ;
24+
[super dealloc] ;
25+
}
26+
27+
- (id)initWithInvocation:(NSInvocation*)invocation {
28+
self = [super init] ;
29+
if (self) {
30+
[self setInvocation:invocation] ;
31+
}
32+
33+
return self ;
34+
}
35+
36+
+ (SSYDeallocDetector*)detectorWithInvocation:(NSInvocation*)invocation {
37+
SSYDeallocDetector* instance = [[SSYDeallocDetector alloc] initWithInvocation:invocation] ;
38+
return [instance autorelease] ;
39+
}
40+
41+
@end

SSYExtrospectiveViewController.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#import <Cocoa/Cocoa.h>
2+
#import "SSYSizability.h"
3+
4+
@interface SSYExtrospectiveViewController : NSViewController {
5+
IBOutlet NSWindowController* windowController ;
6+
}
7+
8+
- (NSWindowController*)windowController ;
9+
10+
@end

SSYExtrospectiveViewController.m

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#import "SSYExtrospectiveViewController.h"
2+
#import "NSObject+SuperUtils.h"
3+
4+
@implementation SSYExtrospectiveViewController
5+
6+
- (void)awakeFromNib {
7+
// Safely invoke super
8+
[self safelySendSuperSelector:_cmd
9+
prettyFunction:__PRETTY_FUNCTION__
10+
arguments:nil] ;
11+
12+
[self setNextResponder:[windowController nextResponder]] ;
13+
[windowController setNextResponder:self] ;
14+
}
15+
16+
- (NSWindowController*)windowController {
17+
return windowController ;
18+
}
19+
20+
@end

SSYNull.h

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import <Cocoa/Cocoa.h>
2+
3+
4+
@interface SSYNull : NSNull {
5+
6+
}
7+
8+
@end

SSYNull.m

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#import "SSYNull.h"
2+
3+
4+
@implementation SSYNull
5+
6+
- (id)valueForUndefinedKey:(NSString *)key {
7+
return nil ;
8+
}
9+
10+
@end

SSYStarRatingView.m

+5-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ - (id)initWithFrame:(NSRect)frame
6161
return self;
6262
}
6363

64+
#if (__ppc__)
65+
#define NO_ARC 1
66+
#else
6467
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
6568
#define NO_ARC 1
6669
#else
@@ -70,6 +73,7 @@ - (id)initWithFrame:(NSRect)frame
7073
#define NO_ARC 1
7174
#endif
7275
#endif
76+
#endif
7377

7478
#if NO_ARC
7579
-(void)dealloc
@@ -207,7 +211,7 @@ - (void)drawRect:(NSRect)dirtyRect
207211
BOOL hasRemoveXButton = (removeXImageWidth > 0 ) ;
208212
if (hasRemoveXButton) {
209213
[self addToolTipRect:NSMakeRect(0.0, 0.0, removeXImageWidth, [self bounds].size.height)
210-
owner:@"Reset to 'Unrated'"
214+
owner:@"Reset to 'Unrated'" // We can get away with not retaining this because it is a constant string.
211215
userData:nil] ;
212216
}
213217
}

SSYTroubleZipper.h

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#import <Cocoa/Cocoa.h>
2+
3+
extern NSString* const SSYTroubleZipperErrorDomain ;
4+
extern NSString* const constKeySSYTroubleZipperURL ;
5+
6+
/*!
7+
@brief Class with one method, for downloading, unzipping,
8+
and running a Trouble Zipper app.
9+
*/
10+
@interface SSYTroubleZipper : NSObject <NSURLDownloadDelegate> {
11+
NSURLDownload* m_download ;
12+
NSString* m_destinationPath ;
13+
BOOL m_downloadDone ;
14+
}
15+
16+
/*!
17+
@brief Downloads, unzips, and runs the designated
18+
Trouble Zipper app.
19+
20+
@details The Trouble Zipper app is expected to be an
21+
application, with filename extension "app", compressed
22+
into a zip archive, with filename extension "zip",
23+
available for download from the URL which is the value for
24+
key constKeySSYTroubleZipperURLin this app's main
25+
bundle's Info.plist.
26+
27+
This method immediately spawns another thread where
28+
the download and control occurs. No progress is given
29+
unless something fails, in which case an error is
30+
displayed via an SSYAlert. The Trouble Zipper is
31+
downloaded to a temporary directory, unzipped to a
32+
temporary file, then upon launching Trouble Zipper,
33+
the zip archive is deleted but the unzipped app
34+
is not deleted, in case it contains resources which
35+
are needed during execution. It is left in a
36+
uniquely-named subdirectory in the temporary
37+
directory and is therefore never re-used unless the
38+
user hunts it down. Subsequent invocations of this
39+
method always cause a new Trouble Zipper to be
40+
downloaded and run. That is by design, in case Trouble
41+
Zipper is updated. Trouble Zippers will be deleted when
42+
temporary directories are destroyed by the system,
43+
which is when the user logs out.
44+
45+
So, you can pretty much just invoke this method in
46+
an action method, and then forget it.
47+
48+
If an error occurs, be sure to look for an underlyingError.
49+
*/
50+
+ (void)getAndRun ;
51+
52+
@end

SSYTroubleZipper.m

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#import "SSYTroubleZipper.h"
2+
#import "NSFileManager+TempFile.h"
3+
#import "SSYShellTasker.h"
4+
#import "SSYAlert.h"
5+
#import "SSYUuid.h"
6+
7+
NSString* const SSYTroubleZipperErrorDomain = @"SSYTroubleZipperErrorDomain" ;
8+
NSString* const constKeySSYTroubleZipperURL = @"SSYTroubleZipperURL" ;
9+
10+
@interface SSYTroubleZipper ()
11+
12+
@property (retain) NSURLDownload* download ;
13+
@property (copy) NSString* destinationPath ;
14+
@property BOOL downloadDone ;
15+
16+
@end
17+
18+
@implementation SSYTroubleZipper
19+
20+
@synthesize download = m_download ;
21+
@synthesize destinationPath = m_destinationPath ;
22+
@synthesize downloadDone = m_downloadDone ;
23+
24+
- (void)dealloc {
25+
[m_download release] ;
26+
[m_destinationPath release] ;
27+
28+
[super dealloc] ;
29+
}
30+
31+
+ (void)alertErrorCode:(NSInteger)code
32+
underlyingError:(NSError*)error {
33+
NSString* msg = [NSString stringWithFormat:
34+
@"Could not download, unzip, or run Trouble Zipper from %@",
35+
[[NSBundle mainBundle] objectForInfoDictionaryKey:constKeySSYTroubleZipperURL]] ;
36+
error = [NSError errorWithDomain:SSYTroubleZipperErrorDomain
37+
code:code
38+
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
39+
msg, NSLocalizedDescriptionKey,
40+
@"Try again, maybe later", NSLocalizedRecoverySuggestionErrorKey,
41+
constKeySSYTroubleZipperURL, @"Info.plist key where URL expected",
42+
error, NSUnderlyingErrorKey, // may be nil
43+
nil]] ;
44+
[SSYAlert performSelectorOnMainThread:@selector(alertError:)
45+
withObject:error
46+
waitUntilDone:NO] ;
47+
}
48+
49+
- (void)alertErrorCode:(NSInteger)code
50+
underlyingError:(NSError*)error {
51+
[SSYTroubleZipper alertErrorCode:code
52+
underlyingError:error] ;
53+
}
54+
55+
+ (void)alertErrorCode:(NSInteger)code {
56+
[self alertErrorCode:code
57+
underlyingError:nil] ;
58+
}
59+
60+
- (void)alertErrorCode:(NSInteger)code {
61+
[SSYTroubleZipper alertErrorCode:code] ;
62+
}
63+
64+
- (id)init {
65+
self = [super init] ;
66+
if (self) {
67+
NSString* urlString = [[NSBundle mainBundle] objectForInfoDictionaryKey:constKeySSYTroubleZipperURL] ;
68+
if (urlString) {
69+
[self setDestinationPath:[[[NSFileManager defaultManager] temporaryFilePath] stringByAppendingPathExtension:@"zip"]] ;
70+
NSURL* url = [NSURL URLWithString:urlString] ;
71+
NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
72+
NSURLDownload* download = [[NSURLDownload alloc] initWithRequest:request
73+
delegate:self] ;
74+
[self setDownload:download] ;
75+
[download release] ;
76+
[[self download] setDestination:[self destinationPath]
77+
allowOverwrite:YES] ;
78+
}
79+
else {
80+
[self alertErrorCode:159425] ;
81+
[self release] ;
82+
self = nil ;
83+
}
84+
}
85+
86+
if (!self) {
87+
// See http://lists.apple.com/archives/Objc-language/2008/Sep/msg00133.html ...
88+
[SSYTroubleZipper alertErrorCode:159426] ;
89+
[super dealloc] ;
90+
}
91+
92+
return self ;
93+
}
94+
95+
- (void)downloadDidFinish:(NSURLDownload*)download {
96+
[self setDownloadDone:YES] ;
97+
}
98+
99+
- (void) download:(NSURLDownload*)download
100+
didFailWithError:(NSError *)error {
101+
[self alertErrorCode:159427] ;
102+
[self setDownloadDone:YES] ;
103+
}
104+
105+
+ (void)troubleZipper {
106+
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] ;
107+
108+
SSYTroubleZipper* instance = [[SSYTroubleZipper alloc] init] ;
109+
110+
while (![instance downloadDone] && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
111+
beforeDate:[NSDate distantFuture]]) {
112+
}
113+
114+
NSError* error = nil ;
115+
NSString* directory = [[instance destinationPath] stringByDeletingLastPathComponent] ;
116+
// Create a subdirectory as a sibling of the destinationPath,
117+
// and unzip into this subdirectory, because otherwise we
118+
// have no way to positively identify which extracted file
119+
// in the temporary directory is ours.
120+
NSString* extractionDirectory = [directory stringByAppendingPathComponent:[SSYUuid compactUuid]] ;
121+
122+
BOOL ok = [[NSFileManager defaultManager] createDirectoryAtPath:extractionDirectory
123+
withIntermediateDirectories:YES
124+
attributes:nil
125+
error:&error] ;
126+
127+
if (ok) {
128+
NSInteger result = [SSYShellTasker doShellTaskCommand:@"/usr/bin/unzip"
129+
arguments:[NSArray arrayWithObjects:@"-o", @"-d", extractionDirectory, [instance destinationPath], nil]
130+
inDirectory:directory
131+
stdinData:nil
132+
stdoutData_p:NULL
133+
stderrData_p:NULL
134+
timeout:5.0
135+
error_p:&error] ;
136+
if (result == 0) {
137+
NSArray* filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:extractionDirectory
138+
error:NULL] ;
139+
NSString* appFilename = nil ;
140+
for (NSString* filename in filenames) {
141+
if ([[filename pathExtension] isEqualToString:@"app"]) {
142+
appFilename = filename ;
143+
}
144+
}
145+
146+
if (appFilename) {
147+
NSString* appleScriptAppPath = [extractionDirectory stringByAppendingPathComponent:appFilename] ;
148+
BOOL ok = [[NSWorkspace sharedWorkspace] launchApplication:appleScriptAppPath] ;
149+
if (!ok) {
150+
[self alertErrorCode:159433
151+
underlyingError:error] ;
152+
}
153+
}
154+
else {
155+
[self alertErrorCode:159429] ;
156+
}
157+
}
158+
else {
159+
[self alertErrorCode:159430
160+
underlyingError:error] ;
161+
}
162+
}
163+
else {
164+
[self alertErrorCode:159431
165+
underlyingError:error] ;
166+
}
167+
168+
[[NSFileManager defaultManager] removeItemAtPath:[instance destinationPath]
169+
error:NULL] ;
170+
171+
[instance release] ;
172+
[pool release] ;
173+
}
174+
175+
+ (void)getAndRun {
176+
[NSThread detachNewThreadSelector:@selector(troubleZipper)
177+
toTarget:self
178+
withObject:nil] ;
179+
}
180+
181+
@end

0 commit comments

Comments
 (0)