Accounting Software
Small Business Software Estimating Software
Time Tracking SoftwareTime Management SoftwareTime Billing SoftwareContact Management SoftwareCustomer Management SoftwareProject Management SoftwareBusiness Management Software

Object Data Tables (Source Code)

Link to: header | source 1 | tables directory

Copyright Turtle Creek Software 1996-2006. All Rights Reserved.

This class manages object data tables for the Goldenseal accounting software,
small business management software, construction project management software and
construction accounting software.

Source Code

/*********************************************************************************

GetRowObjectID TCS 9/29/98

return the object ID for the given row

*********************************************************************************/
DBid CObjectDataTable::GetRowObjectID(const TableIndexT row)
{
SFullObjectInfo info = GetRowObjectInfo(row);
return info.itemID;
}
/*********************************************************************************

GetRowObjectClass TCS 9/29/98

return the object class ID for the given row

*********************************************************************************/
UInt16 CObjectDataTable::GetRowObjectClass(const TableIndexT row)
{
SFullObjectInfo info = GetRowObjectInfo(row);
return info.classID;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

DrawSelf

draw the report contents

*********************************************************************************/
void CObjectDataTable::DrawSelf()
{
// usual clip & port saving calls
TStTextState textSaver;
TStColorPenState penSaver;
penSaver.Normalize();

// get the cell range which needs to be redrawn
TableCellT topLeftCell, botRightCell;
GetCellsToRedraw(&topLeftCell, &botRightCell);

// while we are drawing, we don't want to show multiple
// error messages (especially because we need to redraw after
// the error alert is closed, which might give more errors ad infinitum)
gShowOnlyOneError = true;

// now figure out which rows these are,
// and draw those rows
TableIndexT beginRow = ROW(topLeftCell),
endRow = ROW(botRightCell);
for (TableIndexT row = beginRow; row <= endRow; row++)
{
DrawRow(row);
}
}
/*********************************************************************************

DrawRow

draw the contents of the given row

*********************************************************************************/
void CObjectDataTable::DrawRow(const TableIndexT row)
{
// sanity check
TCS_FailNILMsg(mObjectInfoArray, TCS_GetErrString(errID_BadArray));
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));

// let's bracket this all with a TRY/CATCH block so we can continue
// drawing the table, even if there's a problem with one row TCS rev 9/21/02
TCS_TRY
{
// in a report array table, each row corresponds to
// a particular persistent object. Let's get that object now.
SFullObjectInfo info;
info.itemID = 0;
info.classID = 0;

mObjectInfoArray->FetchItemAt(row, info);

if (IS_TURTLE_CLASS_ID(info.classID)) // bugfix TCS 2/29/00
{
TCS_FailNILOnce(mDescriptor, TCS_GetErrString(errID_BadDescriptor));

DB_PersistentObject *object = nil;

TCS_TRY
{
object = gDBFile->GetOneObject(info.classID, info.itemID);
}
TCS_CATCH
{
object = nil;
}

// does the object exists?
if (object)
{
// we need to watch the object
DB_ObjectWatcher watcher(object);
DrawObjectDataCells(row, object);
}
else // TCS 7/22/03
{
DrawMissingObjectDataCells(row, info.itemID);
}
}
else if (info.classID == id_NeoHeader) // TCS 9/13/02
{
// there isn't an object for the header
DrawHeaderDataCells(row);
}
else if (info.classID == 0)
{
// it must be a space
DrawSpaceDataCells(row, info.itemID);
}
else if (IS_NEO_CLASS_ID(info.classID)) // TCS 9/13/02
{
CNeoMetaClass *descriptor = CNeoMetaClass::GetMetaClass(info.classID);
TCS_ASSERTOnce(descriptor && descriptor->getOne, TCS_GetErrString(errID_BadClassDescriptor));
CNeoPersist *neoObject = (CNeoPersist *)NeoCallGetOne(descriptor->getOne);

if (neoObject)
{
DB_ObjectWatcher watcher(neoObject);

NeoMark objectMark = DB_FileManager::FetchObjectMark(info.classID, info.itemID);

if (objectMark)
{
neoObject->setID(info.itemID);

CNeoContainerStream *stream = gDBFile->getStream();
TCS_FailNILOnce(stream, TCS_GetErrString(errID_BadStream));

// we temporarily set the file mark
neoObject->setMark(objectMark);
stream->setMark(objectMark); // TCS 9/14/02

TCS_TRY // TCS 9/21/02
{
// let's read in data from disk
neoObject->ReadObject(stream, kNeoObjectTag);
DrawObjectDataCells(row, neoObject);
}
TCS_CATCH {}

// we need to clear the object mark, so Neo won't think it's in the database
neoObject->setMark(0);
}
}
}
}
TCS_CATCH {} // we catch here so the rest of the table can draw
}
/*********************************************************************************

DrawObjectDataCells rev TCS 9/17/02

draw the cells in the given row, fetching info from the given object.

*********************************************************************************/
void CObjectDataTable::DrawObjectDataCells(const TableIndexT row, CNeoPersist *object)
{
TCS_FailNILMsg(object, TCS_GetErrString(errID_BadObject));

CTextString cstring;
SLETableColInfo colInfo;

// loop through the columns in the row and draw each cell.
for (SInt32 col = 1; col <= GetNumCols(); col++)
{
mColumns.FetchItemAt(col, colInfo);

if (!object->GetMemberValue(colInfo.tag, type_cstring, &cstring))
{ // couldn't get the member as a string, so
// put an appropriate value into the cell anyway
cstring = TCS_GetStockString(stockID_ItemNotAvailable);
}

DrawCell(row, col, cstring);
}
}
/*********************************************************************************

DrawHeaderDataCells rev TCS 9/17/02

draw the cells for the header row. We don't have an object for this,
so we just fill in info from scratch

*********************************************************************************/
void CObjectDataTable::DrawHeaderDataCells(const TableIndexT row)
{
CTextString cstring;

// loop through the columns in the row and draw each cell.
for (SInt32 col = 1; col <= GetNumCols(); col++)
{
switch (col)
{
case 1: // class name
cstring = DB_ClassDescriptor::GetClassName(id_NeoHeader);
break;

case 2: // class id
cstring.SetFromLong(id_NeoHeader);
break;

case 3: // object count
cstring.SetFromLong(1);
break;

case 4: // object name
cstring = cTwoDashString;
break;

case 5: // file mark
case 7: // memory location
cstring.SetFromLong(0);
break;

case 6: // length
cstring.SetFromLong(kNeoDatabaseHeadSpace);
break;

default:
cstring.MakeNull();
break;
}

DrawCell(row, col, cstring);
}
}
/*********************************************************************************

DrawSpaceDataCells rev TCS 9/17/02

draw the cells for an empty space row.

*********************************************************************************/
void CObjectDataTable::DrawSpaceDataCells(const TableIndexT row, const SInt32 mark)
{
TCS_FailNILMsg(mObjectInfoArray, TCS_GetErrString(errID_BadArray));

CTextString cstring;

// loop through the columns in the row and draw each cell.
for (SInt32 col = 1; col <= GetNumCols(); col++)
{
switch (col)
{
case 1: // class name
case 3: // object name
cstring = TCS_GetStockString(stockID_EmptySpace);
break;

case 2: // object id
case 4: // class id
cstring = cTwoDashString;
break;

case 5: // file mark
cstring.SetFromLong(mark);
break;

case 6: // length
{
DB_FileManager *fileManager =
TCS_SAFE_CAST(gDBFile->GetFirstObject(id_FileManager), DB_FileManager);

if (fileManager)
{
DB_ObjectWatcher watcher (fileManager);
SInt32 spaceLength = fileManager->GetSpaceLength(mark);
cstring.SetFromLong(spaceLength);
}
}
break;

default:
cstring.MakeNull();
break;
}

DrawCell(row, col, cstring);
}
}
/*********************************************************************************

DrawMissingObjectDataCells TCS 7/22/03

draw the cells for a missing object

*********************************************************************************/
void CObjectDataTable::DrawMissingObjectDataCells(const TableIndexT row, const SInt32 mark)
{
TCS_FailNILMsg(mObjectInfoArray, TCS_GetErrString(errID_BadArray));

CTextString cstring;

// loop through the columns in the row and draw each cell.
for (SInt32 col = 1; col <= GetNumCols(); col++)
{
switch (col)
{
case 1: // class name
case 3: // object name
cstring = TCS_GetStockString(stockID_MissingObject);
break;

case 2: // object id
case 4: // class id
cstring = cTwoDashString;
break;

case 5: // file mark
cstring.SetFromLong(mark);
break;

case 6: // length
{
DB_FileManager *fileManager =
TCS_SAFE_CAST(gDBFile->GetFirstObject(id_FileManager), DB_FileManager);

if (fileManager)
{
DB_ObjectWatcher watcher (fileManager);
SInt32 objectLength = fileManager->GetObjectLength(mark);
cstring.SetFromLong(objectLength);
}
}
break;

default:
cstring.MakeNull();
break;
}

DrawCell(row, col, cstring);
}
}
/*********************************************************************************

HiliteCell

we override, since we don't want any hiliting at all

*********************************************************************************/
void CObjectDataTable::HiliteCell(const TableCellT &/*inCell*/, const Boolean /*hiliting*/)
{
}
/*********************************************************************************

WriteTextToOutputStream TCS 12/27/01

write text to a stream. Used for report 'save as text'. We override, since
it's more efficient to write a whole row at a time
*********************************************************************************/
void CObjectDataTable::WriteTextToOutputStream(CTextOutputStream &stream)
{
TCS_FailNILMsg(mObjectInfoArray, TCS_GetErrString(errID_BadArray));

CTextString cellText;

TableIndexT firstRow = GetFirstReportingRow(),
lastRow = GetLastReportingRow();
DB_PersistentObject *object = nil;
SFullObjectInfo info;
info.itemID = 0;
info.classID = 0;
CTextString cstring;

// if we have enough rows, set up a progress bar
CProgressBar *progressDialog = nil; // TCS 2/14/03

if (lastRow - firstRow > 60)
{
progressDialog = CProgressBar::CreateBar(cEmptyString, DLOG_ProgressWithStop);

if (progressDialog)
{
progressDialog->SetValue(0);
progressDialog->SetMaxValue(lastRow - firstRow);
progressDialog->SetTextStep(10);
progressDialog->SetWindowTitle(TCS_GetStockString(stockID_SaveAsText));
progressDialog->SetMessage(TCS_GetStockString(stockID_WritingTable));
progressDialog->SetActionType(TCS_GetStockString(stockID_Row));
progressDialog->Refresh();
}
}

CProgressBarWatcher watcher(progressDialog);

for (TableIndexT row = firstRow; row <= lastRow; row++)
{
if (progressDialog) // TCS 2/14/03
{
if (progressDialog->Increment() != progress_continue)
break;
}

// in a report array table, each row corresponds to
// a particular persistent object. Let's get that object now.
mObjectInfoArray->FetchItemAt(row, info);

if (IS_TURTLE_CLASS_ID(info.classID)) // bugfix TCS 2/29/00
{
object = gDBFile->GetOneObject(info.classID, info.itemID);

// does the object exists?
if (object)
{
// we need to watch the object rev TCS 6/25/02
DB_ObjectWatcher watcher(object);

// now loop through the columns in the row and get text.
for (SInt32 col = 1; col <= GetNumCols(); col++)
{
SLETableColInfo colInfo;
mColumns.FetchItemAt(col, colInfo);

if (!object->GetMemberValue(colInfo.tag, type_cstring, &cstring))
{ // couldn't get the member as a string, so
// put an appropriate value into the cell anyway
cstring = TCS_GetStockString(stockID_ItemNotAvailable);
}

stream.WriteString(cstring);
}

stream.WriteEndOfLine();
}
}
else if (info.classID == id_NeoHeader) // TCS 12/29/02
{
// there is no object for the data header,
// so we just fill in some data from scratch
stream.WriteString(DB_ClassDescriptor::GetClassName(id_NeoHeader)); // class name
stream.WriteLong(1); // object id
stream.WriteString(cTwoDashString); // object name
stream.WriteLong(id_NeoHeader); // class id
stream.WriteLong(0); // file mark
stream.WriteLong(kNeoDatabaseHeadSpace); // length
stream.WriteEndOfLine();
}
else if (info.classID == 0) // TCS 12/29/02
{
// must be a space. We just fill in data from scratch
stream.WriteString(TCS_GetStockString(stockID_EmptySpace)); // class name
stream.WriteLong(0); // object id
stream.WriteString(TCS_GetStockString(stockID_EmptySpace)); // object name
stream.WriteString(cTwoDashString); // class id
stream.WriteLong(info.itemID); // file mark

// we need to fetch space length from the file manager
DB_FileManager *fileManager =
TCS_SAFE_CAST(gDBFile->GetFirstObject(id_FileManager), DB_FileManager);
TCS_FailNILMsg(fileManager, TCS_GetErrString(errID_BadFileManager));
DB_ObjectWatcher watcher (fileManager);
SInt32 spaceLength = fileManager->GetSpaceLength(info.itemID);
stream.WriteLong(spaceLength); // length

stream.WriteEndOfLine();
}
else if (IS_NEO_CLASS_ID(info.classID)) // TCS 12/29/02
{
/*CNeoMetaClass *descriptor = CNeoMetaClass::GetMetaClass(info.classID);
TCS_ASSERTMsg(descriptor && descriptor->getOne, TCS_GetErrString(errID_BadClassDescriptor));
CNeoPersist *neoObject = (CNeoPersist *)NeoCallGetOne(descriptor->getOne);

if (neoObject)
{
DB_ObjectWatcher watcher(neoObject);

NeoMark objectMark = DB_FileManager::FetchObjectMark(info.classID, info.itemID);

if (objectMark)
{
neoObject->setID(info.itemID);

CNeoContainerStream *stream = gDBFile->getStream();
TCS_FailNILMsg(stream, TCS_GetErrString(errID_BadStream));

// we temporarily set the file mark
neoObject->setMark(objectMark);
stream->setMark(objectMark);

TCS_TRY
{
// let's read in data from disk
neoObject->ReadObject(stream, kNeoObjectTag);
DrawObjectDataCells(row, neoObject);
}
TCS_CATCH {}

// we need to clear the object mark, so Neo won't think it's in the database
neoObject->setMark(0);
}
}*/
}
}
}