|
|
1.1 ! root 1: /* TableViewController.m: ! 2: * You may freely copy, distribute, and reuse the code in this example. ! 3: * NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 4: * fitness for any particular use. ! 5: * ! 6: * Written by: Mai Nguyen, NeXT Developer Support ! 7: * ! 8: * ! 9: */ ! 10: #import "TableViewController.h" ! 11: ! 12: #define INSTALL_MODEL NXLocalizedString("Please install SybaseDemo.dbmodela or OracleDemo.dbmodela in your project.", NULL, "Notify user that the ascii model files must be installed in his project directory.") ! 13: ! 14: /* Comment this line out if you want to run an Oracle version */ ! 15: #define SYBASE_DEMO 1 ! 16: ! 17: @implementation TableViewController ! 18: /* ! 19: * Miscellaneous initialization tasks: connect to database, initialize ! 20: * tableview, set up dbModule. ! 21: */ ! 22: -appDidInit:sender ! 23: { ! 24: NXRect viewFrame; ! 25: ! 26: #ifdef SYBASE_DEMO ! 27: /* Notify the user if the database can't be found */ ! 28: if (!(dbDatabase = [DBDatabase findDatabaseNamed:"SybaseDemo" ! 29: connect:YES])) { ! 30: NXRunAlertPanel(NULL,INSTALL_MODEL, "OK", NULL, NULL); ! 31: return self; ! 32: } ! 33: #else ! 34: /* Notify the user if the database can't be found */ ! 35: if (!(dbDatabase = [DBDatabase findDatabaseNamed:"OracleDemo" ! 36: connect:YES])) { ! 37: NXRunAlertPanel(NULL,INSTALL_MODEL, "OK", NULL, NULL); ! 38: return self; ! 39: } ! 40: #endif ! 41: ! 42: [dbDatabase setDelegate:self]; ! 43: ! 44: /* Install the tableview into the custom view */ ! 45: [[dbTableView getFrame:&viewFrame] free]; ! 46: dbTableView = [[DBTableView alloc] initFrame:&viewFrame]; ! 47: [[window contentView] addSubview:dbTableView]; ! 48: [dbTableView setHorizScrollerRequired:YES]; ! 49: [dbTableView setVertScrollerRequired:YES]; ! 50: [dbTableView setDelegate: self]; ! 51: ! 52: #ifdef SYBASE_DEMO ! 53: rootEntity = [dbDatabase entityNamed:"Author"]; ! 54: #else ! 55: rootEntity = [dbDatabase entityNamed:"Order"]; ! 56: #endif ! 57: /* Must initialize your dbModule */ ! 58: dbModule = [[DBModule alloc] initDatabase:dbDatabase ! 59: entity:rootEntity]; ! 60: dbFetchGroup = [dbModule rootFetchGroup]; ! 61: [dbFetchGroup setDelegate:self]; ! 62: #ifdef SYBASE_DEMO ! 63: dbQualifier = [[DBQualifier alloc] initForEntity:[dbModule entity] ! 64: fromDescription:"state = %s", "CA"]; ! 65: #else ! 66: dbQualifier = [[DBQualifier alloc] initForEntity:[dbModule entity] ! 67: fromDescription:"customer.state = %s", "CA"]; ! 68: #endif ! 69: [window disableFlushWindow]; ! 70: [self initTableView]; ! 71: [[window reenableFlushWindow] flushWindow]; ! 72: ! 73: return self; ! 74: } ! 75: - showAll:sender ! 76: { ! 77: [dbFetchGroup fetchContentsOf:[dbModule entity] ! 78: usingQualifier:dbQualifier]; ! 79: [dbTableView display]; ! 80: ! 81: return self; ! 82: } ! 83: ! 84: /* In order to replicate the Interface Builder functionality, one has to ! 85: * add an expression to the fetchgroup for each attribute and subattribute. ! 86: */ ! 87: ! 88: - addTableColumn:(const char *)label ! 89: { ! 90: id newExpression; ! 91: ! 92: /* allocate a new expression, add it to the FetchGroup and add it */ ! 93: /* to the TableView */ ! 94: newExpression = [[DBExpression alloc] initForEntity:[dbModule entity] ! 95: fromDescription:label]; ! 96: [dbFetchGroup addExpression:newExpression]; ! 97: [dbTableView addColumn:newExpression withTitle:label]; ! 98: return self; ! 99: } ! 100: ! 101: ! 102: /* Get all the attributes and subattributes from the defined table and ! 103: * initialize the tableview accordingly. ! 104: */ ! 105: - initTableView ! 106: { ! 107: int i, j, propCount, subpropCount; ! 108: id prop, subprop, subpropList; ! 109: char buffer[100]; ! 110: id <DBEntities, DBTypes> theEntity; ! 111: ! 112: propList = [[List alloc] init]; ! 113: [rootEntity getProperties: propList]; ! 114: propCount = [propList count]; ! 115: ! 116: for (i = 0; i < propCount; i++) { ! 117: prop = [propList objectAt:i]; ! 118: theEntity = (id<DBTypes>)[prop propertyType]; ! 119: if(! [theEntity isEntity]) { ! 120: ! 121: /* add top-level attribute */ ! 122: [self addTableColumn:[prop name]]; /* defined above */ ! 123: } else if ([prop isSingular]) { ! 124: ! 125: /* add all sub-attributes but skip sub-relationships. ! 126: Note that getting sub-attributes only work for ! 127: to-one relationship ! 128: */ ! 129: subpropList = [[List alloc] init]; ! 130: ! 131: [theEntity getProperties:subpropList]; ! 132: subpropCount = [subpropList count]; ! 133: for (j = 0; j < subpropCount; j++) { ! 134: subprop = [subpropList objectAt:j]; ! 135: if (![[subprop propertyType] isEntity]) { ! 136: sprintf(buffer, "%s.%s", [prop name], [subprop name]); ! 137: [self addTableColumn:buffer]; /* defined above */ ! 138: } ! 139: } ! 140: [subpropList free]; /* to prevent a memory leak */ ! 141: } ! 142: } ! 143: ! 144: /* Making this association will make the fetchgroup ! 145: * become the tableview data source. ! 146: */ ! 147: [dbFetchGroup makeAssociationFrom:nil to:dbTableView]; ! 148: /* ! 149: * free property list which is no longer needed ! 150: */ ! 151: [propList free]; ! 152: [window makeKeyAndOrderFront:self]; ! 153: return self; ! 154: } ! 155: ! 156: ! 157: /* Set the sort order before the actual fetch */ ! 158: - fetchGroupWillFetch: sender ! 159: { ! 160: if( sortProp == nil) { ! 161: sortProp = [[dbTableView columnAt: 0] identifier]; ! 162: } ! 163: [[sender recordList] ! 164: addRetrieveOrder: DB_AscendingOrder ! 165: for: sortProp]; ! 166: return self; ! 167: } ! 168: ! 169: /* Find the new sort property every time the tableView column gets moved */ ! 170: - tableView:sender movedColumnFrom:(unsigned int) old to:(unsigned int) new ! 171: { ! 172: sortProp = [[sender columnAt: new] identifier]; ! 173: return [dbModule fetchAllRecords: self]; ! 174: } ! 175: ! 176: ! 177: ! 178: ! 179: - free ! 180: { ! 181: if (dbQualifier) ! 182: [dbQualifier free]; ! 183: if (dbTableView) ! 184: [dbTableView free]; ! 185: return [super free]; ! 186: } ! 187: ! 188: /* DBDatabase delegate methods to log SQL queries - Useful for debugging */ ! 189: ! 190: - (BOOL)db:aDb willEvaluateString:(const char*)aString usingBinder:aBinder ! 191: { ! 192: fprintf(stderr, "SQL query:%s\n", aString); ! 193: return YES; ! 194: } ! 195: ! 196: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.