This is HKGnatsReport.m in view mode; [Download] [Up]
/*
* LEGAL NOTICE
*
* Copyright (c) 1994 WSC Investment Services, Inc.
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND WSC INVESTMENT SERVICES (WSCIS)
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
* SHALL WSCIS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Users of this software agree to return to WSCIS any improvements
* or extensions that they make and grant WSCIS the rights to
* redistribute these changes.
*
* Export of this software is permitted only after complying with the
* regulations of the U.S. Deptartment of Commerce relating to the
* Export of Technical Data.
*/
#import "HKGnatsReport.h"
#import "HKSendPr.h"
#import <hk/HKString.h>
#import <errno.h>
#import <hk/HKDelimitedTable.h>
#import <appkit/NXHelpPanel.h>
@interface TextFieldCell(CheckIt)
- (const char *)stringValue;
@end
@implementation TextFieldCell(CheckIt)
- (const char *)stringValue;
{
const char * ret = [super stringValue];
return ret ? ret : "";
}
@end
@implementation HKGnatsReport
static id sharedInstance = nil;
- setupMenu;
{
int i, count;
id menuMatrix, menuCell;
id menu = [NXApp mainMenu];
if (installedMenu) return self;
if (!menu) {
return nil;
} else {
installedMenu = YES;
}
menuMatrix= [menu itemList];
count = [menuMatrix cellCount];
for(i = 0; (menuCell = [menuMatrix cellAt:i :0]); i++) {
if(strncmp([menuCell title],"Info",strlen("Info")) == 0) {
if ([menuCell hasSubmenu]){
id submenu = [menuCell target];
[[submenu addItem:"Bug Report..."
action:@selector(showPanel:)
keyEquivalent:0] setTarget:self];
} else {
id newMenu= [[Menu alloc] initTitle:"Info"];
SEL oldAction = [menuCell action];
id cell;
[menuMatrix removeRowAt:i andFree:NO];
[menuMatrix insertRowAt:i];
[[menuMatrix cellAt:i:0] setTitle:"Info"];
cell = [newMenu addItem:"Info..."
action:oldAction
keyEquivalent:0];
// the old switcheroo
[[[[newMenu itemList] cellList] replaceObject:cell
with:menuCell] free];
cell = [newMenu addItem:"Bug Report..."
action:@selector(showPanel:)
keyEquivalent:0];
[cell setTarget:self];
[menu setSubmenu:newMenu forItem:[menuMatrix cellAt:i:0]];
}
break;
}
}
// if (!menuCell) then add Info > Bug Report at the top
return self;
}
- awakeFromNib;
{
float left,right,top,bottom;
[self setupMenu];
[problemText getMarginLeft:&left right:&right top:&top bottom:&bottom];
left += 3.0;
top += 3.0;
[problemText setMarginLeft:left right:right top:top bottom:bottom];
return self;
}
- (BOOL)loadBundle:bundle;
{
char path[MAXPATHLEN+1];
BOOL errors = NO;
/*
* We have to load the categories before the nib
*/
if (![bundle getPath:path forResource:"categories" ofType:""]){
NXRunAlertPanel([self name],"Couldn't open \"categories\" in \"%s\" (%s)",0,0,0,
[bundle directory],strerror(errno));
errors = YES;
} else {
[categories readFromFilename:path];
}
/*
* The nib comes second so we can configure it from
* the categories.
*/
if (![bundle getPath:path forResource:"HKGnatsReport" ofType:"nib"]){
NXRunAlertPanel([self name],"Cound't find nib \"HKGnatsReport.nib\" (%s)",0,0,0,
strerror(errno));
errors = YES;
} else if (!([NXApp loadNibFile:path owner:self])){
NXRunAlertPanel([self name],"Couldn't open nib \"%s\" (%s)",0,0,0,
path,strerror(errno));
errors = YES;
}
#if 0
if (![bundle getPath:path forResource:"HKGnatsBundleHelp" ofType:""]){
NXRunAlertPanel([self name],"Couldn't find HKGnatsBundleHelp in \"%s\" (%s)",0,0,0,
[bundle directory],strerror(errno));
} else {
[[NXHelpPanel new] addSupplement:"TableOfContents.rtf" inPath:path];
}
#endif
[panel setTitle:[categories line:0 field:1]];
return errors;
}
- init;
{
BOOL errors = NO;
if (sharedInstance) {
[NXApp delayedFree:self];
return sharedInstance;
} else {
id bundle;
char path[MAXPATHLEN+1];
[super init];
sprintf(path,"%s/%s",[[NXBundle mainBundle] directory],"HKGnatsReport.bundle");
if (!(bundle = [[NXBundle alloc] initForDirectory:path])){
NXRunAlertPanel([self name],"Couldn't open bundle \"%s\" (%s).",0,0,0,
path,strerror(errno));
errors = YES;
} else {
sendPr = [[HKSendPr alloc] init];
categories = [[HKDelimitedTable alloc] init];
[sendPr setup];
errors = [self loadBundle:bundle];
[bundle free];
}
if (!errors) {
[self setupMenu];
current = problem = [[HKString alloc] init];
howToRepeat = [[HKString alloc] init];
possibleFix = [[HKString alloc] init];
return self;
} else {
[NXApp delayedFree:self];
return nil;
}
}
}
- free;
{
if (sharedInstance != self) {
return [super free];
} else {
return nil;
}
}
- changeExplanation:sender;
{
int tag = [[sender selectedCell] tag];
const char * exp = [categories line:tag field:1];
[panel setTitle:exp];
return self;
}
// configure popup lists
- setCategoryPop:sender;
{
id matrix = [[sender target] itemList];
int i,count = [categories count];
categoryPop = sender;
[matrix renewRows:count cols:1];
for(i=0;i<count;i++){
id cell = [matrix cellAt:i:0];
[cell setTitle:[categories line:i field:0]];
[cell setTag:i];
[cell setTarget:self];
[cell setAction:@selector(changeExplanation:)];
}
[categoryPop setTitle:[[matrix cellAt:0:0] title]];
return self;
}
- setClassPop:sender;
{
id matrix = [[sender target] itemList];
classPop = sender;
[[[matrix cellAt:0:0] setTitle:"Software Bug"] setTag:HK_SoftwareBug];
[[[matrix cellAt:0:1] setTitle:"Documentation Bug"] setTag:HK_DocumentationBug];
[[[matrix cellAt:0:2] setTitle:"Change Request"] setTag:HK_ChangeRequest];
[[[matrix cellAt:0:3] setTitle:"Support"] setTag:HK_Support];
return self;
}
- setPriorityPop:sender;
{
id matrix = [[sender target] itemList];
priorityPop = sender;
[[[matrix cellAt:0:0] setTitle:"Low"] setTag:HK_LowPriority];
[[[matrix cellAt:0:1] setTitle:"Medium"] setTag:HK_MediumPriority];
[[[matrix cellAt:0:2] setTitle:"High"] setTag:HK_HighPriority];
return self;
}
- setSeverityPop:sender;
{
id matrix = [[sender target] itemList];
severityPop = sender;
[[[matrix cellAt:0:0] setTitle:"Non-Critical"] setTag:HK_NonCriticalSeverity];
[[[matrix cellAt:0:1] setTitle:"Serious"] setTag:HK_SeriousSeverity];
[[[matrix cellAt:0:2] setTitle:"Critical"] setTag:HK_CriticalSeverity];
return self;
}
#define SUBMITTER "GnatsSubmitter"
#define ORGANIZATION "ORGANIZATION"
#define REPORTTO "GnatsReportTo"
- set:field from:(const char *)name;
{
const char * sub = getenv(name);
if (!sub) sub = NXReadDefault("Global",name);
if (!sub) sub = NXReadDefault([NXApp appName],name);
[field setStringValue:sub];
return self;
}
// configure fields
- setSubmitterField:sender;
{
[self set:sender from:SUBMITTER];
submitterField = sender;
return self;
}
- setOrganizationField:sender;
{
[self set:sender from:ORGANIZATION];
organizationField = sender;
return self;
}
- setReportToField:sender;
{
[self set:sender from:REPORTTO];
if (!strlen([sender stringValue])){
[sender setStringValue:"bugs"];
}
reportToField = sender;
return self;
}
// actions
- clear:sender;
{
[summaryField setStringValue:""];
[problemText setText:""];
[problem setStringValue:""];
[howToRepeat setStringValue:""];
[possibleFix setStringValue:""];
return self;
}
- (const char *)_version;
{
const char * release = 0;
id del = [NXApp delegate];
if (del != self && [del respondsTo:@selector(version)]){
release = (const char *)[del perform:@selector(version)];
} else {
release = [NXApp appName];
}
return release;
}
- change:sender;
{
int len = [problemText textLength];
id other;
char text[len+1];
[problemText getSubstring:text start:0 length:len];
text[len]='\0';
[current setStringValue:text];
switch([[sender selectedCell] tag]){
default:
case 0:
other = problem;
break;
case 1:
other = howToRepeat;
break;
case 2:
other = possibleFix;
break;
}
if (current!=other){
current = other;
[problemText setText:[current stringValue]];
}
return self;
}
// could be better about this
- writeAndTest:(const char *)defaultName with:(const char *)value;
{
NXWriteDefault([NXApp appName],defaultName,value);
return self;
}
- check;
{
[self change:controlMatrix];
if (!strlen([summaryField stringValue])){
return nil;
}
if (!strlen([problem stringValue])){
return nil;
}
[self writeAndTest:ORGANIZATION with:[organizationField stringValue]];
[self writeAndTest:SUBMITTER with:[submitterField stringValue]];
[self writeAndTest:REPORTTO with:[reportToField stringValue]];
return self;
}
- submit:sender;
{
if ([self check]){
[sendPr setEmailTo:[reportToField stringValue]];
[sendPr setSubmitterID:[submitterField stringValue]];
[sendPr setOrganization:[organizationField stringValue]];
[sendPr setConfidential:[confidentialSwitch state]];
[sendPr setSynopsis:[summaryField stringValue]];
[sendPr setSeverity:[severityPop selectedTag]];
[(HKSendPr *)sendPr setPriority:[priorityPop selectedTag]];
[sendPr setBugClass:[classPop selectedTag]];
[sendPr setCategory:[categoryPop title]];
[sendPr setRelease:[self _version]];
[sendPr setDescription:[problem stringValue]];
[sendPr setHowToRepeat:[howToRepeat stringValue]];
[sendPr setHowToFix:[possibleFix stringValue]];
if (![sendPr send]){
NXRunAlertPanel([self name],"Problem sending bug report.",0,0,0);
} else {
[panel performClose:self];
}
} else {
NXRunAlertPanel([self name],"The problem report is incomplete.",0,0,0);
}
return self;
}
- showPanel:sender;
{
[panel makeKeyAndOrderFront:self];
return self;
}
// set these programatically
- setReportTo:(const char *)name;
{
[reportToField setStringValue:name];
return self;
}
- setSubmitterID:(const char *)name;
{
[submitterField setStringValue:name];
return self;
}
//
// Only if he's appDelegate.
//
- appDidInit:sender;
{
[self showPanel:self];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.