1 | //␊ |
2 | // PreferencesControllerBase.mm␊ |
3 | // ChameleonPrefPane␊ |
4 | //␊ |
5 | // Created by Rekursor on 1/22/10.␊ |
6 | //␊ |
7 | ␊ |
8 | #import "PreferencesControllerBase.h"␊ |
9 | #import "KernOptionsParser.h"␊ |
10 | #include <string>␊ |
11 | #include <list>␊ |
12 | #include <map>␊ |
13 | #include <ctype.h>␊ |
14 | ␊ |
15 | //--------------------------------------------------------------------------␊ |
16 | static std::list< id<GroupControllerProtocol> > groupList;␊ |
17 | ␊ |
18 | // for unix-like options types␊ |
19 | static std::map<void*, std::string> IdToUCmdList;␊ |
20 | static KernOptionsParser kernelFlags;␊ |
21 | ␊ |
22 | //--------------------------------------------------------------------------␊ |
23 | NSString* GetLocStrDef(NSString* label, NSString* comment, NSString* def)␊ |
24 | {␊ |
25 | ␉return NSLocalizedStringWithDefaultValue(label, nil, ␊ |
26 | ␉␉␉␉␉␉␉␉␉␉␉ [NSBundle bundleForClass:[ChameleonPrefPane class]],␊ |
27 | ␉␉␉␉␉␉␉␉␉␉␉ def, ␊ |
28 | ␉␉␉␉␉␉␉␉␉␉␉ comment);␊ |
29 | }␊ |
30 | //--------------------------------------------------------------------------␊ |
31 | ␊ |
32 | @implementation PreferencesControllerBase␊ |
33 | ␊ |
34 | -(ChameleonPrefPane*) chameleon { return [ChameleonPrefPane instance]; }␊ |
35 | ␊ |
36 | ␊ |
37 | //--------------------------------------------------------------------------␊ |
38 | - (id) init␊ |
39 | {␊ |
40 | ␉self = [super init];␊ |
41 | ␉␊ |
42 | ␉[PreferencesControllerBase registerPreferencesGroup: self];␊ |
43 | ␉␊ |
44 | ␉return self;␊ |
45 | }␉␊ |
46 | //--------------------------------------------------------------------------␊ |
47 | - (id) getResourcePath: (NSString *) str ofType: (NSString*) sType␊ |
48 | {␊ |
49 | ␉if(!str) return nil;␊ |
50 | ␉NSBundle * b = [NSBundle bundleForClass:[self class]];␊ |
51 | ␉id sRes = [b pathForResource: str ofType:sType ];␊ |
52 | ␉return sRes;␊ |
53 | }␊ |
54 | ␊ |
55 | ␊ |
56 | //--------------------------------------------------------------------------␊ |
57 | // get authorisation from main panel lock␊ |
58 | - (AuthorizationRef) getAuthorization␊ |
59 | {␊ |
60 | ␉AuthorizationRef auth= [[self chameleon] isUnlocked] ? ␊ |
61 | ␉[[ [self chameleon]->authView authorization] authorizationRef] : NULL;␊ |
62 | ␉return auth;␊ |
63 | }␊ |
64 | //--------------------------------------------------------------------------␊ |
65 | + (void) registerPreferencesGroup:(id) myGroup␊ |
66 | {␊ |
67 | ␉groupList.push_back(myGroup);␊ |
68 | }␊ |
69 | ␊ |
70 | - (void) synchronizeTextContent:(const BootOptionDesc*) bod withValue:(int) val␊ |
71 | {␊ |
72 | ␉if(!bod || !bod->contentID) return;␊ |
73 | ␉id item = (id) bod->contentID;␊ |
74 | if ( [item isKindOfClass: [NSTextField class]] ||␊ |
75 | ␉␉[item isKindOfClass: [NSComboBox class]])␊ |
76 | ␉{␊ |
77 | ␉␉[item setEnabled: val];␊ |
78 | ␉␉[item setEditable: val];␊ |
79 | ␉}␊ |
80 | ␉␊ |
81 | }␊ |
82 | //--------------------------------------------------------------------------␊ |
83 | + (void) refreshLockState: (id) item␊ |
84 | {␊ |
85 | ␉const BootOptionDesc * bod = BootProp::instance().findOption(item);␊ |
86 | ␉if(!bod) bod=BootProp::instance().findOptionContent(item);␊ |
87 | ␉if(bod) [PreferencesControllerBase␉refreshBodLockState: bod];␊ |
88 | ␉else␉[item setEnabled: [[ChameleonPrefPane instance] isUnlocked]];␊ |
89 | }␊ |
90 | //--------------------------------------------------------------------------␊ |
91 | + (void) refreshBodLockState: (const BootOptionDesc*) bod␊ |
92 | {␊ |
93 | ␉if (!bod) return;␊ |
94 | ␉bool isUnlocked = [[ChameleonPrefPane instance] isUnlocked];␊ |
95 | ␉if (bod->ID) [(id) bod->ID setEnabled: isUnlocked];␊ |
96 | ␉int val = bod->ID ? [(id) bod->ID intValue] : 0;␊ |
97 | if ( [(id) bod->contentID isKindOfClass: [NSTextField class]] ||␊ |
98 | ␉␉[(id) bod->contentID isKindOfClass: [NSComboBox class]])␊ |
99 | ␉{␊ |
100 | ␉␉[(id) bod->contentID setEnabled: (isUnlocked && val) ];␊ |
101 | ␉␉[(id) bod->contentID setEditable: (isUnlocked && val) ];␊ |
102 | ␉}␊ |
103 | ␉else␊ |
104 | ␉␉[(id) bod->contentID setEnabled: isUnlocked];␊ |
105 | }␊ |
106 | ␊ |
107 | //--------------------------------------------------------------------------␊ |
108 | + (void) refreshLockStates␊ |
109 | {␊ |
110 | ␉for (const BootOptionDesc* bod=BootProp::instance().firstOption(); ␊ |
111 | ␉␉ bod; ␊ |
112 | ␉␉ bod=BootProp::instance().nextOption())␊ |
113 | ␉{␊ |
114 | ␉␉[self refreshLockState: (id) bod->ID ];␊ |
115 | ␉␉if (bod->contentID) [self refreshLockState: (id) bod->contentID ];␊ |
116 | ␉}␊ |
117 | ␉␊ |
118 | }␊ |
119 | //--------------------------------------------------------------------------␊ |
120 | + (void) doForEachGroup: (GroupAction) action withOption:(id) option␊ |
121 | {␊ |
122 | ␉std::list< id<GroupControllerProtocol> >::iterator it;␊ |
123 | ␉for (it=groupList.begin(); it!=groupList.end(); it++)␊ |
124 | ␉{␊ |
125 | ␉␉switch (action) {␊ |
126 | ␉␉␉case SetDefaultValues:␊ |
127 | ␉␉␉␉[*it setDefaultsValues: option];␊ |
128 | ␉␉␉␉break;␊ |
129 | ␉␉␉case RefreshLockStates:␊ |
130 | ␉␉␉␉[*it refreshLockStates ];␊ |
131 | ␉␉␉␉[PreferencesControllerBase refreshLockStates];␊ |
132 | ␉␉␉␉break;␊ |
133 | ␉␉␉case LoadPreferencesOptions:␊ |
134 | ␉␉␉␉[*it loadOptionsFromPreferencesFile: option];␊ |
135 | ␉␉␉␉break;␊ |
136 | ␉␉␉case LoadBootConfigOptions:␊ |
137 | ␉␉␉␉[PreferencesControllerBase loadOptionsFromBootFile];␊ |
138 | ␉␉␉␉break;␊ |
139 | ␉␉␉case AddOptionsDesc:␊ |
140 | ␉␉␉␉[*it addOptionsDesc];␊ |
141 | ␉␉␉␉break;␊ |
142 | ␉␉␉case SaveBootConfigOptions:␊ |
143 | ␉␉␉␉break;␊ |
144 | ␉␉␉default:␊ |
145 | ␉␉␉␉break;␊ |
146 | ␉␉}␊ |
147 | ␉}␊ |
148 | }␊ |
149 | ␉␉ ␊ |
150 | //--------------------------------------------------------------------------␊ |
151 | + (void) loadOptionsFromBootFile␊ |
152 | {␊ |
153 | ␉// parse unix like command string:␊ |
154 | ␉kernelFlags.parseOptions(BootProp::instance().getStringForKey(kKernelFlags));␊ |
155 | ␉␊ |
156 | ␉for (const BootOptionDesc* bod=BootProp::instance().firstOption(); ␊ |
157 | ␉␉ bod; ␊ |
158 | ␉␉ bod=BootProp::instance().nextOption())␊ |
159 | ␉{␊ |
160 | ␉␉[PreferencesControllerBase loadOptionFromBootFile:(id)bod->ID ];␊ |
161 | ␉}␊ |
162 | }␊ |
163 | ␊ |
164 | //--------------------------------------------------------------------------␊ |
165 | ␊ |
166 | + (void) loadOptionFromBootFile:(id) optionID␊ |
167 | {␊ |
168 | ␉const BootOptionDesc* bod = BootProp::instance().findOption(optionID);␊ |
169 | ␉if (!bod) ␊ |
170 | ␉{␊ |
171 | ␉␉NSRunAlertPanel(@"Error Parsing Option",@"loadOptionFromBootFile failed",@"OK", nil, nil);␊ |
172 | ␉␉return;␊ |
173 | ␉} ␊ |
174 | ␉␊ |
175 | ␉const char * stringForKey = BootProp::instance().getStringForKey(bod->Name);␊ |
176 | ␉std::string s = stringForKey ? trim(stringForKey) : "";␊ |
177 | ␉std::string def = trim(bod->Default ? bod->Default : "");␊ |
178 | ␉␊ |
179 | ␉switch (bod->Type) ␊ |
180 | ␉{␊ |
181 | ␉␉case OptionYesNo:␊ |
182 | ␉␉␉if (s.length()>0) ␊ |
183 | ␉␉␉␉[(NSButton*)optionID setIntValue: (toupper(s[0])=='Y' ? 1 : 0 ) ];␊ |
184 | ␉␉␉else␊ |
185 | ␉␉␉␉[(NSButton*)optionID setIntValue: (toupper(def[0])=='Y' ? 1 : 0 ) ];␊ |
186 | ␉␉␉break;␊ |
187 | ␉␉␉␊ |
188 | ␉␉case OptionKernel1:␊ |
189 | ␉␉{␊ |
190 | ␉␉␉int val = (s.length()>0 ? 1 : 0 );␊ |
191 | ␉␉␉[(NSButton*)optionID setIntValue: val ];␊ |
192 | ␉␉␉[(NSTextField*) bod->contentID setStringValue: ␊ |
193 | ␉␉␉ [[NSString alloc] initWithUTF8String: s.c_str()] ];␊ |
194 | ␉␉␉[(NSTextField*) bod->contentID setEnabled: val ? true : false]; ␊ |
195 | ␉␉␉[(NSTextField*) bod->contentID setEditable: val ? true : false]; ␊ |
196 | ␉␉}␊ |
197 | ␉␉␉break;␊ |
198 | ␉␉case OptionFileString:␊ |
199 | ␉␉case OptionString:␊ |
200 | ␉␉{␊ |
201 | ␉␉␉int val = (s.length()>0 ? 1 : 0 );␊ |
202 | ␉␉␉[(NSButton*)optionID setIntValue: val ];␊ |
203 | ␉␉␉[(NSTextField*) bod->contentID setStringValue: ␊ |
204 | ␉␉␉␉[[NSString alloc] initWithUTF8String: s.c_str()] ];␊ |
205 | ␉␉␉[(NSTextField*) bod->contentID setEnabled: val ? true: false]; ␊ |
206 | ␉␉␉[(NSTextField*) bod->contentID setEditable: val ? true : false]; ␊ |
207 | ␉␉}␊ |
208 | ␉␉␉break;␊ |
209 | ␉␉␉␊ |
210 | ␉␉case OptionUnix:␊ |
211 | ␉␉case OptionKernel:␊ |
212 | ␉␉{␊ |
213 | ␉␉␉std::string s = kernelFlags.stringFromKey(bod->Name);␊ |
214 | ␉␉␉if (s.length()>0)␊ |
215 | ␉␉␉{␊ |
216 | ␉␉␉␉[(NSButton*)optionID setIntValue: 1 ];␊ |
217 | ␉␉␉␉if(bod->Type==OptionKernel)␊ |
218 | ␉␉␉␉{␊ |
219 | ␉␉␉␉␉[(NSTextField*) bod->contentID setStringValue: ␊ |
220 | ␉␉␉␉␉ [[NSString alloc] initWithUTF8String: ␊ |
221 | ␉␉␉␉␉␉kernelFlags.rightMember(s).c_str()] ];␊ |
222 | ␉␉␉␉␉[(NSTextField*) bod->contentID setEnabled: true]; ␊ |
223 | ␉␉␉␉␉[(NSTextField*) bod->contentID setEditable: true]; ␊ |
224 | ␉␉␉␉}␊ |
225 | ␊ |
226 | ␉␉␉}␊ |
227 | ␉␉␉else␊ |
228 | ␉␉␉{ // set the default for thiso option ␊ |
229 | ␉␉␉␉[(NSButton*)optionID setIntValue: (bod->Default[0] ? 1 :0) ];␊ |
230 | ␉␉␉␉if(bod->Type==OptionKernel)␊ |
231 | ␉␉␉␉{␊ |
232 | ␉␉␉␉␉[(NSTextField*) bod->contentID setEnabled: false]; ␊ |
233 | ␉␉␉␉␉[(NSTextField*) bod->contentID setEditable: false]; ␊ |
234 | ␉␉␉␉}␊ |
235 | ␊ |
236 | ␉␉␉}␊ |
237 | ␉␉}␊ |
238 | ␉␉␉break;␊ |
239 | ␉␉default:␊ |
240 | ␉␉␉break;␊ |
241 | ␉}␊ |
242 | ␉␊ |
243 | }␊ |
244 | ␊ |
245 | //--------------------------------------------------------------------------␊ |
246 | - (void) loadPreferences␊ |
247 | {␊ |
248 | ␉[ [ChameleonPrefPane instance] loadPreferences];␊ |
249 | }␊ |
250 | ␊ |
251 | //--------------------------------------------------------------------------␊ |
252 | - (bool) savePreferences␊ |
253 | {␊ |
254 | ␉return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ];␊ |
255 | ␉␊ |
256 | }␊ |
257 | //--------------------------------------------------------------------------␊ |
258 | // update the boot Config with one option change and its associated desc ␊ |
259 | - (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod␊ |
260 | {␊ |
261 | ␉if(!bod) ␊ |
262 | ␉{␊ |
263 | ␉␉return false;␊ |
264 | ␉}␊ |
265 | ␉// load boot config file so that we don't risk to loose␊ |
266 | ␉// externally modified parameters␊ |
267 | ␉␊ |
268 | ␉int val = [(NSButton*) sender intValue ];␊ |
269 | ␉std::string sDefaultValue = trim(bod->Default ? bod->Default : "");␊ |
270 | ␉bool status = false;␊ |
271 | ␉std::string name = trim(bod->Name);␊ |
272 | ␉␊ |
273 | ␉switch (bod->Type) {␊ |
274 | ␉␉case OptionYesNo:␊ |
275 | ␉␉{␊ |
276 | ␉␉␉std::string sVal = val ? "Yes" : "No"; ␊ |
277 | ␉␉␉if (sDefaultValue.length()==0) sDefaultValue␉= "No";␊ |
278 | ␉␉␉// Avoid populating bootConfig with unnecessary options:␊ |
279 | ␉␉␉if (sVal == sDefaultValue) ␊ |
280 | ␉␉␉␉status = BootProp::instance().removeKeyAndValue(name.c_str());␊ |
281 | ␉␉␉else␊ |
282 | ␉␉␉␉status = BootProp::instance().setStringForKey(name, sVal.c_str());␊ |
283 | ␉␉}␊ |
284 | ␉␉␉break;␊ |
285 | ␉␉case OptionUnix:␊ |
286 | ␉␉␉if (!val)␉kernelFlags.removeFlag(name);␊ |
287 | ␉␉␉else␉␉kernelFlags.addFlag(name);␊ |
288 | ␉␉␉BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());␊ |
289 | ␉␉␉status = true;␊ |
290 | ␉␉␉break;␊ |
291 | ␉␉case OptionKernel:␊ |
292 | ␉␉{␊ |
293 | ␉␉␉std::string contentValue = trim(␊ |
294 | ␉␉␉[ [(NSTextField*) bod->contentID stringValue] UTF8String ]);␊ |
295 | ␉␉␉kernelFlags.removeFlag(kernelFlags.stringFromKey(bod->Name));␊ |
296 | ␉␉␉if(val && contentValue.length()>0)␊ |
297 | ␉␉␉{␊ |
298 | ␉␉␉␉std::string concat = trim(name);␊ |
299 | ␉␉␉␉concat+= "=";␊ |
300 | ␉␉␉␉concat+= trim(contentValue);␊ |
301 | ␉␉␉␉␊ |
302 | ␉␉␉␉kernelFlags.addFlag(concat);␊ |
303 | ␉␉␉}␊ |
304 | ␉␉␉BootProp::instance().setStringForKey(kKernelFlags,kernelFlags.options());␊ |
305 | ␉␉␉status = true;␊ |
306 | ␉␉}␊ |
307 | ␉␉␉break;␊ |
308 | ␉␉case OptionKernel1:␊ |
309 | ␉␉case OptionFileString:␊ |
310 | ␉␉case OptionString:␊ |
311 | ␉␉␉// Avoid populating bootConfig with unnecessary options:␊ |
312 | ␉␉␉if (val == 0 && bod->Type!=OptionKernel1) ␊ |
313 | ␉␉␉␉status = BootProp::instance().removeKeyAndValue(bod->Name);␊ |
314 | ␉␉␉else␊ |
315 | ␉␉␉{␊ |
316 | ␉␉␉␉std::string contentValue =␊ |
317 | ␉␉␉␉␉[ [(NSTextField*) bod->contentID stringValue] UTF8String ];␊ |
318 | ␉␉␉␉if (contentValue.length()>0)␊ |
319 | ␉␉␉␉␉status = BootProp::instance().setStringForKey(bod->Name, contentValue.c_str());␊ |
320 | ␉␉␉␉else {␊ |
321 | ␉␉␉␉␉return false; // no content to save so don't save it␊ |
322 | ␉␉␉␉}␊ |
323 | ␊ |
324 | ␉␉␉}␊ |
325 | ␉␉␉break;␊ |
326 | ␉␉default:␊ |
327 | ␉␉␉break;␊ |
328 | ␉}␊ |
329 | ␉␊ |
330 | ␉// Now save the bootConfig␊ |
331 | ␉AuthorizationRef auth = [self getAuthorization ];␊ |
332 | ␉if (status)␉status = BootProp::instance().save(auth);␊ |
333 | ␊ |
334 | ␉return status;␊ |
335 | }␊ |
336 | //--------------------------------------------------------------------------␊ |
337 | -(NSMutableDictionary*) preferencesFile␊ |
338 | {␉␊ |
339 | ␉return [[ChameleonPrefPane instance] preferencesFile];␊ |
340 | }␊ |
341 | ␊ |
342 | //--------------------------------------------------------------------------␊ |
343 | -(NSMutableDictionary*) preferencesParts ␊ |
344 | { ␊ |
345 | ␉return [[ChameleonPrefPane instance] preferencesParts];␊ |
346 | }␊ |
347 | ␊ |
348 | //--------------------------------------------------------------------------␊ |
349 | - (bool) handleSender: (id) sender␊ |
350 | {␊ |
351 | ␊ |
352 | ␉const BootOptionDesc * bod = BootProp::instance().findOption(sender);␊ |
353 | ␉␊ |
354 | ␉if (!bod) {␊ |
355 | ␉␉bod = BootProp::instance().findOptionContent(sender);␊ |
356 | ␉␉NSTextField* textField = (NSTextField*) sender;␊ |
357 | ␉␉std::string content = [[textField stringValue] UTF8String ];␊ |
358 | ␉␉if(bod->ID!=nil) sender = (id) bod->ID;␊ |
359 | ␉}␊ |
360 | ␉else␊ |
361 | ␉{␊ |
362 | ␉␉␊ |
363 | ␉␉int state = [sender intValue];␊ |
364 | ␉␊ |
365 | ␉␉switch (bod->Type) {␊ |
366 | ␉␉␉case OptionKernel:␊ |
367 | ␉␉␉case OptionKernel1:␊ |
368 | ␉␉␉case OptionFileString:␊ |
369 | ␉␉␉case OptionString:␊ |
370 | ␉␉␉[(NSTextField*) bod->contentID setEnabled: state ? true : false];␊ |
371 | ␉␉␉[(NSTextField*) bod->contentID setEditable: state ? true : false];␊ |
372 | ␉␉␉if (state && bod->Type==OptionFileString)␊ |
373 | ␉␉␉{␊ |
374 | ␉␉␉␉NSString* f = [self selectAnyFile ];␊ |
375 | ␉␉␉␉if (f) ␊ |
376 | ␉␉␉␉{␊ |
377 | ␉␉␉␉␉[(NSTextField*)bod->contentID setStringValue: f];␊ |
378 | ␉␉␉␉␉[f release];␉␊ |
379 | ␉␉␉␉}␊ |
380 | ␉␉␉}␊ |
381 | ␉␉␉[self synchronizeTextContent: bod withValue: state];␊ |
382 | ␉␉␉␉break;␊ |
383 | ␉␉␉default:␊ |
384 | ␉␉␉␉break;␊ |
385 | ␉␉}␊ |
386 | ␉}␉␊ |
387 | ␉if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID )␊ |
388 | ␉{ // Couldn't save, so warn user ...␊ |
389 | ␉␉NSRunAlertPanel(@"Error saving bootConfig", @"Could not save org.chameleon.Boot.plist",␊ |
390 | ␉␉␉␉␉␉␉@"OK", nil, nil);␊ |
391 | ␉}␊ |
392 | ␉return true;␊ |
393 | }␊ |
394 | ␊ |
395 | - (bool) executeTaskAndWaitForTermination: (NSString*)taskPath␊ |
396 | {␊ |
397 | ␉return [ self executeTaskAndWaitForTermination:taskPath withArgs:nil ];␊ |
398 | }␊ |
399 | ␊ |
400 | - (bool) executeTaskAndWaitForTermination: (NSString*)taskPath withArgs:(NSArray*) args␊ |
401 | {␊ |
402 | ␉NSTask *task = [[NSTask alloc] init];␊ |
403 | ␉[task setLaunchPath:taskPath];␊ |
404 | ␉if (args) [task setArguments: args];␊ |
405 | ␉[task launch];␊ |
406 | ␉␊ |
407 | ␉[task waitUntilExit]; // wait for process termination␊ |
408 | ␉int status = [task terminationStatus];␊ |
409 | ␉␊ |
410 | ␉return (status == 0) ? true : false;␊ |
411 | }␊ |
412 | ␊ |
413 | -(NSString*) selectDirectory:(NSString*) dirName␊ |
414 | {␊ |
415 | ␉NSOpenPanel *oPanel = [NSOpenPanel openPanel]; ␊ |
416 | [oPanel setAllowsMultipleSelection:NO];␊ |
417 | ␉[oPanel setCanChooseFiles:NO];␊ |
418 | ␉[oPanel setCanChooseDirectories:YES]; ␊ |
419 | ␉[oPanel setDirectoryURL:[NSURL fileURLWithPath:dirName isDirectory: YES] ]; ␊ |
420 | ␊ |
421 | ␉BOOL result = [oPanel runModal];␊ |
422 | if (result == NSOKButton) ␊ |
423 | ␉{␊ |
424 | NSArray *dirToOpen = [oPanel filenames];␊ |
425 | int count = [dirToOpen count];␊ |
426 | if(count>0)␊ |
427 | ␉␉{␊ |
428 | NSString *aDir = [dirToOpen objectAtIndex:0];␊ |
429 | ␉␉␉return aDir;␊ |
430 | ␉␉}␊ |
431 | }␊ |
432 | ␉ return nil;␊ |
433 | }␊ |
434 | ␊ |
435 | - (NSString*) selectPlistFile:(NSString*) name␊ |
436 | {␊ |
437 | ␉NSArray* fileTypes = [NSArray arrayWithObjects: @"plist", nil];␊ |
438 | ␉NSString * s= [self selectFileWithFileTypes: @"/" withName: name ␊ |
439 | ␉␉␉␉␉␉␉ withTypes: fileTypes];␊ |
440 | ␉[fileTypes release];␊ |
441 | ␉return s;␊ |
442 | }␊ |
443 | ␊ |
444 | - (NSString*) selectAnyFile␊ |
445 | {␊ |
446 | ␉return [self selectFileWithFileTypes: @"/" withName: nil withTypes:nil];␊ |
447 | }␊ |
448 | ␊ |
449 | - (NSString*) selectFileWithFileTypes:(NSString*) dir withName: (NSString*) name withTypes:(NSArray*) fileTypes␊ |
450 | {␊ |
451 | int result;␊ |
452 | NSOpenPanel *oPanel = [NSOpenPanel openPanel];␊ |
453 | [oPanel setAllowsMultipleSelection:NO];␊ |
454 | ␉[oPanel setCanChooseFiles:YES];␊ |
455 | ␉[oPanel setCanChooseDirectories:NO];␊ |
456 | ␉[oPanel setAllowedFileTypes: fileTypes];␊ |
457 | ␉if (dir!=nil && [dir length] > 0 ) ␊ |
458 | ␉␉[oPanel setDirectoryURL:[NSURL fileURLWithPath:dir isDirectory: YES] ]; ␊ |
459 | ␉[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"AppleShowAllFiles"];␊ |
460 | ␊ |
461 | result = [oPanel runModal];␊ |
462 | if (result == NSOKButton) ␊ |
463 | ␉{␊ |
464 | NSArray *filesToOpen = [oPanel filenames];␊ |
465 | int count = [filesToOpen count];␊ |
466 | if(count>0)␊ |
467 | ␉␉{␊ |
468 | NSString *aFile = [filesToOpen objectAtIndex:0];␊ |
469 | ␉␉␉return aFile;␊ |
470 | ␉␉␉␊ |
471 | ␉␉}␊ |
472 | }␊ |
473 | ␊ |
474 | ␉return nil;␊ |
475 | }␊ |
476 | ␊ |
477 | -(void) msgBoxInfo:(NSString*) msg␊ |
478 | {␊ |
479 | ␉NSAlert *alert = [[NSAlert alloc] init];␊ |
480 | ␉[alert setAlertStyle: NSInformationalAlertStyle];␊ |
481 | ␉[alert setMessageText:msg ];␊ |
482 | ␉[alert runModal];␊ |
483 | ␉[alert release];␊ |
484 | }␊ |
485 | ␊ |
486 | -(void) msgBoxError:(NSString*) msg␊ |
487 | {␊ |
488 | ␉NSAlert *alert = [[NSAlert alloc] init];␊ |
489 | ␉[alert setAlertStyle: NSCriticalAlertStyle];␊ |
490 | ␉[alert setMessageText: msg ];␊ |
491 | ␉[alert runModal];␊ |
492 | ␉[alert release];␊ |
493 | }␊ |
494 | ␊ |
495 | @end␊ |
496 | |