source: users/rhwood/Pallet/PortAuthority.m @ 23856

Last change on this file since 23856 was 23856, checked in by rhwood@…, 14 years ago

Use generic code to take strings from PortIndex and turn them into Arrays.
All arrays items in the Pallet PortIndex memory model also get a item_as_string string representation to keep the search code in the controller simple.
The indexing code could be cleaned up some.

File size: 22.6 KB
Line 
1/*
2        Class MPAuthority
3        Project Pallet
4 
5        Copyright (C) 2006 MacPorts.
6 
7        This code is free software; you can redistribute it and/or modify it under
8        the terms of the GNU General Public License as published by the Free
9        Software Foundation; either version 2 of the License, or any later version.
10 
11        This code is distributed in the hope that it will be useful, but WITHOUT ANY
12        WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13        FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14        details.
15 
16        For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
17        write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
18        Boston, MA 02111-1307, USA.
19 
20        More information is available at http://www.macports.org or macports-users@lists.macosforge.org
21 
22        History:
23       
24        Created by Randall Wood rhwood@macports.org on 6 October 2006
25 */
26
27#import "PortAuthority.h"
28
29#include <tcl.h>
30
31@implementation PortAuthority
32
33enum portCommands {
34        portInstall,
35        portList,
36        portListAll,
37        portSync,
38        portSelfupdate,
39        portListInstalled,
40        portListOutdated
41};
42
43#pragma mark STARTUP
44
45- (void)awakeFromNib
46{
47        // Load/set preferences/defaults
48        if (![[[NSUserDefaultsController sharedUserDefaultsController] values] valueForKey:@"portInstallationPath"]) {
49                [[[NSUserDefaultsController sharedUserDefaultsController] values] setValue:@"/opt/local" forKey:@"portInstallationPath"];
50                NSString *userDefaultsValuesPath;
51                NSDictionary *userDefaultsValuesDict;
52                userDefaultsValuesPath = [[NSBundle mainBundle] pathForResource:@"UserDefaults"
53                                                                                                                                 ofType:@"plist"];
54                userDefaultsValuesDict = [NSDictionary dictionaryWithContentsOfFile:userDefaultsValuesPath];
55                [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict];
56                [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:userDefaultsValuesDict];
57        }
58        // Hide duplicate items in Windows menu
59        [portsWindow setExcludedFromWindowsMenu:YES];
60        [portLogWindow setExcludedFromWindowsMenu:YES];
61        // Locate port
62        macPortsPath = [[[NSUserDefaultsController sharedUserDefaultsController] values] valueForKey:@"portInstallationPath"];
63        macPortsPort = [[NSString alloc] initWithString:[macPortsPath stringByAppendingPathComponent:@"bin/port"]];
64        // Initialize the port settings cache
65        portSettings = [[NSMutableDictionary alloc] init];
66        // Clean the main window
67        [status setStringValue:@""];
68        // Setup the port task
69        portIsRunning = NO;
70        launcher = [[NSBundle mainBundle] pathForResource:@"Launcher" ofType:nil];
71        authPortTask = [[AuthorizedExecutable alloc] initWithExecutable:launcher];
72        killTask = [[AuthorizedExecutable alloc] initWithExecutable:launcher];
73        [authPortTask setDelegate:self];
74        [killTask setDelegate:self];
75        // Setup the value transformers used in bindings
76        NSValueTransformer *transformer = [[PAStatusTransformer alloc] init];
77        [NSValueTransformer setValueTransformer:transformer forName:@"PAStatusTransformer"];
78        // UI Tweaks
79        [[portsList headerView] setMenu:portsListHeaderMenu];
80        [[portsList cornerView] setMenu:portsListHeaderMenu];
81       
82        // TESTING TESTING TESTING
83        NSLog(@"Ports Database path: %@", [self configurationSetting:@"portdbpath"]);
84}
85
86/*
87        TODO: rewrite to run sync/selfupdate, and port list methods in thread so as not to block UI.
88 */
89- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
90{
91        // sync or selfupdate as required
92        if ([[[[NSUserDefaultsController sharedUserDefaultsController] values] valueForKey:@"updateMacPortsOnStartup"] boolValue] == YES) {
93                [self updateMacPorts:nil];
94        } else if ([[[[NSUserDefaultsController sharedUserDefaultsController] values] valueForKey:@"synchronizePortsListOnStartup"] boolValue] == YES) {
95                [self syncPortsList:nil];
96        }
97        // List ports
98        [self getPortIndexes];
99        [self populatePortIndex];
100}
101
102#pragma mark PORT INDEX
103
104- (void)getPortIndexes
105{
106        NSArray *conf;
107        NSString *path;
108        NSString *file;
109        NSMutableDictionary *sources;
110        NSEnumerator *enumerator;
111        id line;
112        NSMutableString *source;
113
114        source = [[NSMutableString alloc] init];
115        sources = [[NSMutableDictionary alloc] init];
116        path = [macPortsPath stringByAppendingPathComponent:@"etc/ports/sources.conf"];
117        file = [[NSString alloc] initWithContentsOfFile:path];
118        conf = [[NSArray alloc] initWithArray:[file componentsSeparatedByString:@"\n"]];
119        if ([conf count] == 1) {
120                [conf release];
121                conf = [[NSArray alloc] initWithArray:[file componentsSeparatedByString:@"\r"]];
122        }
123        enumerator = [conf objectEnumerator];
124        while (line = [enumerator nextObject]) {
125                @try {
126                        if ([line characterAtIndex:0] != '#') {
127                                [sources setValue:[self pathToPortIndexWithSource:line] forKey:line];
128                        }
129                }
130                @catch (NSException *exception) {
131                        // Exceptions will be thrown where line is nil or 0 length
132                        // Ignore the exception since it means only that the line was empty
133                }
134        }
135        if (portIndexes != nil) {
136                [portIndexes release];
137        }
138        portIndexes = [[NSDictionary alloc] initWithDictionary:sources copyItems:YES];
139}
140
141- (NSString *)pathToPortIndexWithSource:(NSString *)source
142{
143        NSMutableString *path;
144        path = [[NSMutableString alloc] init];
145        if ([[source substringToIndex:4] isEqualToString:@"file"]) {
146                [path setString:[source substringFromIndex:7]];
147        } else if ([[source substringToIndex:5] isEqualToString:@"rsync"]) {
148                [path setString:source];
149                [path replaceOccurrencesOfString:@"/" withString:@"_" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [path length])];
150                [path replaceOccurrencesOfString:@":__" withString:@"." options:NSCaseInsensitiveSearch range:NSMakeRange(0, [path length])];
151                [path setString:[[macPortsPath stringByAppendingPathComponent:@"var/db/dports/sources"] stringByAppendingPathComponent:path]];
152        }
153        return [path stringByAppendingPathComponent:@"PortIndex"];
154}
155
156- (void)parsePortIndex:(NSString *)index intoIndexObject:(id)indexObject
157{
158        NSString *file;
159        NSArray *lines;
160        NSMutableArray *arrays;
161        NSMutableDictionary *port;
162        NSArray *array;
163        NSEnumerator *indexEnumerator;
164        int counter;
165        int tclCount;
166        int tclResult;
167        const char **tclElements;
168        NSStringEncoding encoding;
169        NSString *key;
170        id value;
171        NSMutableArray *values;
172        NSEnumerator *valuesEnumerator;
173        int valuesCount;
174        int valuesCounter;
175        const char **valuesElements;
176        id line;
177        arrays = [[NSMutableArray alloc] init];
178        file = [[NSString alloc] initWithContentsOfFile:index];
179        lines = [file componentsSeparatedByString:@"\n"];
180        indexEnumerator = [lines objectEnumerator];
181        // throw away the lines that contain only two words (the portname and a number)
182        while (line = [indexEnumerator nextObject]) {
183                array = [line componentsSeparatedByString:@" "];
184                if ([array count] > 2) {
185                        [arrays addObject:line];
186                }
187        }
188        indexEnumerator = [arrays objectEnumerator];
189        encoding = [NSString defaultCStringEncoding];
190        while (line = [indexEnumerator nextObject]) {
191                port = [[NSMutableDictionary alloc] init];
192                tclResult = Tcl_SplitList(NULL, [line cString], &tclCount, &tclElements);
193                if (tclResult == TCL_OK && !(tclCount % 2)) {
194                        for (counter = 0; counter < tclCount; counter+=2) {
195                                key = [[NSString alloc] initWithCString:tclElements[counter] encoding:encoding];
196                                if ([key isEqualToString:@"maintainers"] ||
197                                        [key isEqualToString:@"depends_lib"] ||
198                                        [key isEqualToString:@"categories"]     ||
199                                        [key isEqualToString:@"depends_build"]) {
200                                        tclResult = Tcl_SplitList(NULL, tclElements[counter + 1], &valuesCount, &valuesElements);
201                                        if (tclResult == TCL_OK) {
202                                                values = [[NSMutableArray alloc] initWithCapacity:valuesCount];
203                                                for (valuesCounter = 0; valuesCounter < valuesCount; valuesCounter++) {
204                                                        [values addObject:[[NSString alloc] initWithCString:valuesElements[valuesCounter] encoding:encoding]];
205                                                }
206                                        } else {
207                                                values = [[NSArray alloc] init];
208                                        }
209                                        value = [[NSArray alloc] initWithArray:values];
210                                        // create a string containing all the tokens so that it can be rapidly and easily searched
211                                        [port setValue:[[NSString alloc] initWithCString:tclElements[counter + 1] encoding:encoding] forKey:[key stringByAppendingString:@"_as_string"]];
212                                } else {
213                                        value = [[NSString alloc] initWithCString:tclElements[counter + 1] encoding:encoding];
214                                }
215                                [port setValue:value forKey:key];
216                                //NSLog(@"%@: %@\n", key, value);
217                        }
218                        if ([port valueForKey:@"depends_lib"]) {
219                                values = [[NSMutableArray alloc] initWithArray:[port valueForKey:@"depends_lib"]];
220                                valuesCount = [values count];
221                                for (valuesCounter = 0; valuesCounter < valuesCount; valuesCounter++) {
222                                        value = [[[values objectAtIndex:valuesCounter] componentsSeparatedByString:@":"] lastObject];
223                                        [values replaceObjectAtIndex:valuesCounter withObject:value];
224                                }
225                                [port setValue:[[NSArray alloc] initWithArray:values] forKey:@"depends_lib"];
226                        }
227                        if ([port valueForKey:@"depends_build"]) {
228                                values = [[NSMutableArray alloc] initWithArray:[port valueForKey:@"depends_build"]];
229                                valuesCount = [values count];
230                                for (valuesCounter = 0; valuesCounter < valuesCount; valuesCounter++) {
231                                        value = [[[values objectAtIndex:valuesCounter] componentsSeparatedByString:@":"] lastObject];
232                                        [values replaceObjectAtIndex:valuesCounter withObject:value];
233                                }
234                                [port setValue:[[NSArray alloc] initWithArray:values] forKey:@"depends_build"];
235                        }
236                        @try {
237                                if ([[port valueForKey:@"long_description"] characterAtIndex:0] == '{') {
238                                        [port setValue:[port valueForKey:@"description"] forKey:@"long_description"];
239                                }
240                        }
241                        @catch (NSException *e) {
242                                [port setValue:[NSString stringWithFormat:
243                                        NSLocalizedStringWithDefaultValue(@"parsePortIndexDescreiptionError",
244                                                                                                          @"Localizable",
245                                                                                                          [NSBundle mainBundle],
246                                                                                                          @"Port has an invalid desciption or long_description key.",
247                                                                                                          @"Error statement for exception raised when testing long_description.")]
248                                                forKey:@"long_description"];
249                        }
250                        // generate a composite version string: version_revision
251                        [port setValue:[[[port valueForKey:@"version"] stringByAppendingString:@"_"] stringByAppendingString:[port valueForKey:@"revision"]] forKey:@"compositeVersion"];
252                        // set the status flag to unknown
253                        [port setValue:[NSNumber numberWithInt:portStatusUnknown] forKey:@"status"];
254                        [indexObject addObject:port];
255                } else {
256                        NSLog(@"Line \"%@\" from index %@ is bad.\n", line, index);
257                }
258        }
259        //NSLog(@"Parsed %d ports from index %@\n", [ports count], index);
260        Tcl_Free((char *)tclElements);
261}
262
263- (void)populatePortIndex
264{
265        NSEnumerator *indexEnumerator;
266        id index;
267        if (portIndex = nil) {
268                portIndex = [[NSMutableArray alloc] init];
269        }
270        indexEnumerator = [portIndexes keyEnumerator];
271        while (index = [indexEnumerator nextObject]) {
272                [progressIndicator startAnimation:nil];
273                [status setStringValue:@"Listing ports in all indexes..."];
274                [status setStringValue:[NSString stringWithFormat:
275                        NSLocalizedStringWithDefaultValue(@"statusPopulatePortIndex",
276                                                                                          @"Localizable",
277                                                                                          [NSBundle mainBundle],
278                                                                                          @"Listing ports in index %@",
279                                                                                          @"Status for [MPAuthority populatePortIndex] method"),
280                        index]];
281                [self parsePortIndex:[portIndexes valueForKey:index] intoIndexObject:portIndexController];
282        }
283        [status setStringValue:@""];
284        [progressIndicator stopAnimation:nil];
285}
286
287- (void)indexPortsInThread
288{
289       
290}
291
292#pragma mark PORT CONFIGURATION
293
294- (NSString *)configurationSetting:(NSString *)setting
295/*
296 For some reason, the below script can not find {$prefix}/etc/ports/ports.conf
297 So what we need to do is execute a tclsh resource script to get conf settings out of port
298 
299 Better yet, create a RFE for port to dump its configuration settings so we can read all port conf files
300 without knowing where the setting came from (default, ports.conf, .portrc, wherever)...
301 */
302{
303        if ([portSettings valueForKey:setting] == nil) {
304                int tclResult;
305                Tcl_Interp *tcl;
306                NSString *script = [[NSString alloc] initWithFormat:@"source %@/etc/ports/ports.conf\nproc %@ x {puts [list %2$@ $x]}", macPortsPath, setting, nil];
307                NSLog(script);
308                tcl = Tcl_CreateInterp();
309                tclResult = Tcl_EvalEx(tcl, [script cString], -1, TCL_EVAL_GLOBAL);
310                if (tclResult == TCL_OK) {
311                        NSLog(@"%s", Tcl_GetStringResult(tcl));
312                        [portSettings setValue:[NSString stringWithCString:Tcl_GetStringResult(tcl)] forKey:setting];
313                } else {
314                        NSLog(@"%s", Tcl_ErrnoMsg(Tcl_ErrnoId()));
315                }
316                Tcl_DeleteInterp(tcl);
317        }
318        return [portSettings valueForKey:setting];
319}
320
321#pragma mark PORT COMMANDS
322
323- (void)defaultAction:(id)items
324/*
325 rewrite to use other methods in this class to avoid duplication
326 */
327{
328        id item;
329        switch ([[item valueForKey:@"status"] intValue]) {
330                case portStatusActive:
331                        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
332                                @"uninstall",
333                                @"-dv",
334                                [item valueForKey:@"name"]]];
335                        break;
336                case portStatusInstalled:
337                        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
338                                @"activate",
339                                @"-dv",
340                                [item valueForKey:@"name"]]];
341                        break;
342                case portStatusOutdated:
343                        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
344                                @"upgrade",
345                                @"-dv",
346                                [item valueForKey:@"name"]]];
347                        break;
348                case portStatusUnknown:
349                        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
350                                @"install",
351                                @"-dv",
352                                [item valueForKey:@"name"]]];
353                        break;
354                default:
355                        break;
356        }
357}
358
359- (IBAction)installPort:(id)sender
360{
361        portCommand = portInstall;
362        NSArray *selection = [portIndexController selectedObjects];
363        NSEnumerator *selectionEnumerator = [selection objectEnumerator];
364        id port;
365        while (port = [selectionEnumerator nextObject]) {
366                [self installSinglePort:[port objectForKey:@"name"]];
367        }
368}
369
370- (void)installSinglePort:(NSString *)port
371{
372        [status setStringValue:[NSString localizedStringWithFormat:NSLocalizedStringWithDefaultValue(@"statusInstallPort",
373                                                                                                                         @"Localizable",
374                                                                                                                         [NSBundle mainBundle],
375                                                                                                                         @"Preparing to install %@",
376                                                                                                                         @"Status for [MPAuthority installPort] method"),
377                port]];
378        NSLog([status stringValue]);
379        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
380                @"-dv",
381                @"install",
382                port,
383                nil]];
384}
385
386- (IBAction)reinstallPort:(id)sender
387{
388}
389
390- (IBAction)removePort:(id)sender
391{
392}
393
394- (IBAction)syncPortsList:(id)sender
395{
396        portCommand = portSync;
397        [status setStringValue:NSLocalizedStringWithDefaultValue(@"statusSyncPortsList",
398                                                                                                                         @"Localizable",
399                                                                                                                         [NSBundle mainBundle],
400                                                                                                                         @"Syncing ports list with MacPorts",
401                                                                                                                         @"Status for [MPAuthority syncPortsList] method")];
402        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
403                @"sync",
404                @"-dv",
405                nil]];
406}
407
408- (IBAction)updateMacPorts:(id)sender
409{
410        portCommand = portSelfupdate;
411        [status setStringValue:NSLocalizedStringWithDefaultValue(@"statusUpdateMacPorts",
412                                                                                                                         @"Localizable",
413                                                                                                                         [NSBundle mainBundle],
414                                                                                                                         @"Updating MacPorts Installation",
415                                                                                                                         @"Status for [MPAuthority updateMacPorts] method")];
416        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
417                @"selfupdate",
418                nil]];
419}
420
421- (IBAction)upgradeOutdated:(id)sender
422{
423        NSLog(@"Upgrade Outdated\n");
424        portCommand = portSelfupdate;
425        [status setStringValue:NSLocalizedStringWithDefaultValue(@"statusUpgradeOutdated",
426                                                                                                                         @"Localizable",
427                                                                                                                         [NSBundle mainBundle],
428                                                                                                                         @"Preparing to upgrade all outdated ports...",
429                                                                                                                         @"Status for [MPAuthority upgradeOutdated] method")];
430        [self launchAuthorizedExecutableWithArguments:[NSArray arrayWithObjects:macPortsPort,
431                @"-dv",
432                @"upgrade",
433                @"outdated",
434                nil]];
435}
436
437- (IBAction)upgradePort:(id)sender
438{
439}
440
441- (IBAction)haltPortCommand:(id)sender
442{
443       
444}
445
446- (void)runPortCommand:(NSString *)action port:(NSString *)port
447{
448       
449}
450
451
452
453- (void)runPortCommandInThread:(id)parameters
454{
455       
456}
457
458#pragma mark TABLES
459
460- (void)updateAvailablePorts:(id)output
461{
462        NSMutableArray *fields;
463        NSMutableDictionary *columns;
464        columns = [[NSMutableDictionary alloc] initWithCapacity:4];
465        fields = [[NSMutableArray alloc] initWithArray:[output componentsSeparatedByString:@" "]];
466        [fields removeObjectIdenticalTo:[NSString string]];
467        [columns setValue:[NSNumber numberWithInt:portStatusUnknown] forKey:@"status"];
468        [columns setValue:[fields objectAtIndex:0] forKey:@"name"];
469        [columns setValue:[fields objectAtIndex:1] forKey:@"version"];
470        [columns setValue:[fields objectAtIndex:2] forKey:@"categories"];
471        [portIndex addObject:columns];
472        [portsList reloadData];
473}
474
475#pragma mark TABLE DATASOURCES
476
477- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
478{
479        NSLog(@"request for row %@ column %@\n", [NSNumber numberWithInt:rowIndex], [aTableColumn identifier]);
480        NSParameterAssert(rowIndex >= 0 && rowIndex < [portIndex count]);
481        if ([[[aTableColumn identifier] stringValue] isEqualToString:@"status"]) {
482                switch ([[[portIndex objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]] intValue]) {
483                        case portStatusInstalled:
484                                return nil;
485                                break;
486                        case portStatusActive:
487                                return nil;
488                                break;
489                        case portStatusOutdated:
490                                return nil;
491                                break;
492                        default:
493                                return nil;
494                }
495        }
496        return [[portIndex objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]];
497}
498
499- (int)numberOfRowsInTableView:(NSTableView *)aTableView
500{
501        return [portIndex count];
502}
503
504#pragma mark MENU ITEMS
505
506- (IBAction)about:(id)sender
507{
508        NSMutableDictionary *options;
509        NSMutableAttributedString *credits;
510        NSMutableString *version;
511       
512        version = [NSMutableString stringWithContentsOfFile:[macPortsPath stringByAppendingPathComponent:@"etc/ports/dp_version"]];
513        [version deleteCharactersInRange:NSMakeRange([version length] - 1, 1)];
514        credits = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:
515                NSLocalizedStringFromTable(@"MacPorts Version: %@",
516                                                                   @"Localizable",
517                                                                   @"MacPorts Version"),
518                version]];
519       
520        [credits setAlignment:NSCenterTextAlignment range:NSMakeRange(0, [credits length])];
521        [credits addAttribute:@"NSFontAttributeName" value:[NSFont labelFontOfSize:[NSFont labelFontSize]] range:NSMakeRange(0, [credits length])];
522        options = [[NSMutableDictionary alloc] init];
523        [options setObject:credits forKey:@"Credits"];
524        [NSApp orderFrontStandardAboutPanelWithOptions:options];
525}
526
527- (IBAction)macPortsSite:(id)sender
528{
529        [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.macports.org"]];
530}
531
532- (IBAction)portAuthoritySite:(id)sender
533{
534        [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.macports.org"]];
535}
536
537#pragma mark UTILITIES
538
539- (void)launchExecutableWithArguments:(NSMutableArray *)args
540{
541        if (!portIsRunning) {
542                portIsRunning = YES;
543                [NSApp setApplicationIconImage:[NSImage imageNamed:@"ApplicationIconBusy"]];
544                if (portTask != nil) {
545                        [portTask release];
546                }
547                portTask = [[TaskWrapper alloc] initWithController:self arguments:args];
548                [portTask startProcess];
549        }
550}
551
552- (void)launchAuthorizedExecutableWithArguments:(NSMutableArray *)args
553{
554        NSLog(@"Launching command %@", args);
555        if (!portIsRunning) {
556                portIsRunning = YES;
557                [NSApp setApplicationIconImage:[NSImage imageNamed:@"ApplicationIconBusy"]];
558                [authPortTask setArguments:args];
559                [authPortTask authorizeWithQuery];
560                [progressIndicator startAnimation:nil];
561                [authPortTask start];
562        } else {
563                [taskQueue addObject:args];
564        }
565}
566
567#pragma mark TOOLBAR
568
569- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
570{
571        return YES;
572}
573
574#pragma mark AUTHORIZED EXECUTABLE DELEGATES / TASK WRAPPER CONTROLLER
575// This callback is implemented as part of conforming to the ProcessController protocol.
576// It will be called whenever there is output from the TaskWrapper.
577- (void)appendOutput:(NSString *)output
578{
579    // add the string (a chunk of the results from locate) to the NSTextView's
580    // backing store, in the form of an attributed string
581    [[portLog textStorage] appendAttributedString: [[[NSAttributedString alloc]
582                             initWithString: output] autorelease]];
583    // setup a selector to be called the next time through the event loop to scroll
584    // the view to the just pasted text.  We don't want to scroll right now,
585    // because of a bug in Mac OS X version 10.1 that causes scrolling in the context
586    // of a text storage update to starve the app of events
587    [self performSelector:@selector(scrollToVisible:) withObject:nil afterDelay:0.0];
588        switch (portCommand) {
589        }
590}
591
592// This routine is called after adding new results to the text view's backing store.
593// We now need to scroll the NSScrollView in which the NSTextView sits to the part
594// that we just added at the end
595- (void)scrollToVisible:(id)ignore {
596    [portLog scrollRangeToVisible:NSMakeRange([[portLog string] length], 0)];
597}
598
599// A callback that gets called when a TaskWrapper is launched, allowing us to do any setup
600// that is needed from the app side.  This method is implemented as a part of conforming
601// to the ProcessController protocol.
602- (void)processStarted
603{
604    portIsRunning = YES;
605    [portLog setString:@""];
606        [progressIndicator startAnimation:nil];
607}
608
609// A callback that gets called when a TaskWrapper is completed, allowing us to do any cleanup
610// that is needed from the app side.  This method is implemented as a part of conforming
611// to the ProcessController protocol.
612- (void)processFinished
613{
614    portIsRunning = NO;
615        [status setStringValue:@""];
616        [progressIndicator stopAnimation:nil];
617        if ([taskQueue count]) {
618                [self launchAuthorizedExecutableWithArguments:[taskQueue objectAtIndex:0]];
619                [taskQueue removeObjectAtIndex:0];
620        }
621}
622
623- (void)captureOutput:(NSString*)str forExecutable:(AuthorizedExecutable*)exe
624{
625        NSRange marker, eol;
626    [[portLog textStorage] appendAttributedString: [[[NSAttributedString alloc]
627                             initWithString: str] autorelease]];
628        @try {
629                marker = [str rangeOfString:@"--->"];
630                eol = [str rangeOfString:@"\n" options:NSLiteralSearch range:NSMakeRange(marker.location + 4, [str length] - marker.location)];
631                NSLog([str substringWithRange:NSMakeRange(marker.location + 4, eol.location - (marker.location + 4))]);
632        }               
633        @catch (NSException *exception) {
634                // Exceptions will be thrown where "--->" is not in str
635                // Ignore the exceptions since we want to change the status line only if such a line exists
636        }
637    [self performSelector:@selector(scrollToVisible:) withObject:nil afterDelay:0.0];
638}
639
640- (void)executableFinished:(AuthorizedExecutable *)exe withStatus:(int)exeStatus
641{
642        NSLog(@"Launcher finished with status %u", exeStatus);
643        portIsRunning = NO;
644        [status setStringValue:@""];
645        [progressIndicator stopAnimation:nil];
646        if ([taskQueue count]) {
647                [self launchAuthorizedExecutableWithArguments:[taskQueue objectAtIndex:0]];
648                [taskQueue removeObjectAtIndex:0];
649        }
650}
651
652#pragma mark APPLICATION DELEGATES
653
654-(void)applicationWillTerminate:(NSNotification*)anotification
655{
656        [NSApp setApplicationIconImage:[NSImage imageNamed:@"ApplicationIcon"]];
657    [authPortTask unAuthorize];
658        [killTask unAuthorize];
659}
660
661
662@end
Note: See TracBrowser for help on using the repository browser.