--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: dbgrid.h
+// Purpose: Displays a wxDbTable in a wxGrid.
+// Author: Roger Gammans, Paul Gammans
+// Modified by:
+// Created:
+// RCS-ID: $Id$
+// Copyright: (c) 1999 The Computer Surgery (roger@computer-surgery.co.uk)
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+// Branched From : dbgrid.h,v 1.19 2001/03/28 11:16:01
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_GENERIC_DBGRID_H_
+#define _WX_GENERIC_DBGRID_H_
+
+#ifdef __GNUG__
+ #pragma interface "dbgrid.h"
+#endif
+
+#if wxUSE_ODBC
+#if wxUSE_NEW_GRID
+
+#include "wx/log.h"
+#include "wx/dbtable.h"
+#include "wx/dynarray.h"
+#include "wx/grid.h"
+#include "wx/dbkeyg.h"
+
+#define wxGRID_VALUE_DBAUTO _T("dbauto")
+
+WX_DECLARE_OBJARRAY(GenericKey,keyarray);
+
+static const int wxUSE_QUERY = -1;
+
+class wxDbGridColInfoBase
+{
+public:
+ //Default ctor
+ wxDbGridColInfoBase() { }
+ wxDbGridColInfoBase(int colNo,
+ wxString type, wxString title) :
+ DbCol(colNo),
+ wxtypename(type),
+ Title(title)
+ { }
+ //Copy Ctor
+ wxDbGridColInfoBase(const wxDbGridColInfoBase& ref)
+ {
+ DbCol = ref.DbCol;
+ wxtypename = ref.wxtypename;
+ Title = ref.Title;
+ }
+ //Empty destructor for member obj's
+ ~wxDbGridColInfoBase() {}
+
+ int DbCol;
+ wxString wxtypename;
+ wxString Title;
+};
+
+
+class wxDbGridColInfo
+{
+public:
+ wxDbGridColInfo(int colNo,
+ wxString type,
+ wxString title,
+ wxDbGridColInfo *next) :
+ m_data(colNo,type,title)
+ {
+ m_next=next;
+ }
+
+ //Empty List
+ ~wxDbGridColInfo() { delete m_next; }
+
+ //Recurse to find length.
+ int Length() { return (m_next ? m_next->Length() +1 : 1); }
+
+ protected:
+ wxDbGridColInfoBase m_data;
+ wxDbGridColInfo *m_next;
+
+ friend class wxDbGridTableBase;
+};
+
+
+class wxDbGridCellAttrProvider : public wxGridCellAttrProvider
+{
+public:
+ wxDbGridCellAttrProvider();
+ wxDbGridCellAttrProvider(wxDbTable *tab, wxDbGridColInfoBase* ColInfo);
+ virtual ~wxDbGridCellAttrProvider();
+
+ virtual wxGridCellAttr *GetAttr(int row, int col,
+ wxGridCellAttr::wxAttrKind kind) const;
+ virtual void AssignDbTable(wxDbTable *tab);
+private:
+ wxDbTable *m_data;
+ wxDbGridColInfoBase *m_ColInfo;
+};
+
+
+class wxDbGridTableBase : public wxGridTableBase
+{
+public:
+ wxDbGridTableBase(wxDbTable *tab, wxDbGridColInfo *ColInfo,
+ int count = wxUSE_QUERY, bool takeOwnership = true);
+ ~wxDbGridTableBase();
+
+ virtual int GetNumberRows()
+ {
+ wxLogDebug(" GetNumberRows() = %i",m_rowtotal);
+ return m_rowtotal;
+ }
+ virtual int GetNumberCols()
+ {
+ wxLogDebug(" GetNumberCols() = %i",m_nocols);
+ return m_nocols;
+ }
+ virtual bool IsEmptyCell(int row, int col) ;
+ virtual wxString GetValue(int row, int col) ;
+ virtual void SetValue(int row, int col, const wxString& value);
+ virtual bool CanHaveAttributes();
+ virtual wxString GetTypeName(int row, int col);
+ virtual bool CanGetValueAs(int row, int col, const wxString& typeName);
+ virtual bool CanSetValueAs(int row, int col, const wxString& typeName);
+ virtual long GetValueAsLong(int row, int col);
+ virtual double GetValueAsDouble(int row, int col);
+ virtual bool GetValueAsBool(int row, int col);
+ virtual void SetValueAsLong(int row, int col, long value);
+ virtual void SetValueAsDouble(int row, int col, double value);
+ virtual void SetValueAsBool(int row, int col, bool value);
+ virtual void *GetValueAsCustom(int row, int col, const wxString& typeName);
+ virtual void SetValueAsCustom(int row, int col, const wxString& typeName, void* value);
+
+
+ virtual wxString wxDbGridTableBase::GetColLabelValue(int col);
+
+ virtual bool AssignDbTable(wxDbTable *tab, int count = wxUSE_QUERY, bool takeOwnership=true);
+ virtual void ValidateRow(int row);
+ virtual bool UpdateRow(int row) const
+ {
+ if (m_row != row)
+ return true;
+ else
+ return Writeback();
+ }
+
+private:
+ //Operates on the current row
+ bool Writeback() const;
+
+ typedef wxGridTableBase inherited;
+ keyarray m_keys;
+ wxDbTable *m_data;
+ bool m_dbowner;
+ int m_rowtotal;
+ int m_nocols;
+ int m_row;
+ wxDbGridColInfoBase *m_ColInfo;
+ bool m_rowmodified;
+};
+
+#endif // #if wxUSE_NEW_GRID
+#endif // #if wxUSE_ODBC
+
+#endif _WX_GENERIC_DBGRID_H_
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: dbgrid.cpp
+// Purpose: Displays a wxDbTable in a wxGrid.
+// Author: Roger Gammans, Paul Gammans
+// Modified by:
+// Created:
+// RCS-ID: $Id$
+// Copyright: (c) 1999 The Computer Surgery (roger@computer-surgery.co.uk)
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+// Branched From : dbgrid.cpp,v 1.18 2000/12/19 13:00:58
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+ #pragma implementation "dbgrid.h"
+#endif
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+
+#if wxUSE_ODBC
+#if wxUSE_NEW_GRID
+
+#ifndef WX_PRECOMP
+ #include "wx/textctrl.h"
+ #include "wx/dc.h"
+#endif // WX_PRECOMP
+
+#include "wx/generic/gridctrl.h"
+#include "wx/dbgrid.h"
+
+
+wxDbGridCellAttrProvider::wxDbGridCellAttrProvider()
+{
+ m_data=NULL;
+ m_ColInfo=NULL;
+}
+
+wxDbGridCellAttrProvider::wxDbGridCellAttrProvider(wxDbTable *tab, wxDbGridColInfoBase* ColInfo)
+{
+ m_data=tab;
+ m_ColInfo=ColInfo;
+}
+
+wxDbGridCellAttrProvider::~wxDbGridCellAttrProvider()
+{
+}
+
+wxGridCellAttr *wxDbGridCellAttrProvider::GetAttr(int row, int col,
+ wxGridCellAttr::wxAttrKind kind) const
+{
+ wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row,col,kind);
+
+ if (m_data && m_ColInfo && (m_data->GetNumberOfColumns() > m_ColInfo[col].DbCol))
+ {
+ //FIXME: this test could.
+ // ??::InsertPending == m_data->get_ModifiedStatus()
+ // and if InsertPending use colDef[].InsertAllowed
+ if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
+ {
+ switch(kind)
+ {
+ case (wxGridCellAttr::Any):
+ if (!attr)
+ {
+ attr = new wxGridCellAttr;
+ // Store so we don't keep creating / deleting this...
+ wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
+ attr->IncRef();
+ self->SetColAttr(attr, col);
+ attr->SetReadOnly();
+ }
+ else
+ {
+ //We now must check what we were returned. and do the right thing (tm)
+ wxGridCellAttr::wxAttrKind attrkind = attr->GetKind();
+ if ((attrkind == (wxGridCellAttr::Default)) || (attrkind == (wxGridCellAttr::Cell)) ||
+ (attrkind == (wxGridCellAttr::Col)))
+ {
+ wxGridCellAttr *attrtomerge = attr;
+ attr = new wxGridCellAttr;
+ attr->SetKind(wxGridCellAttr::Merged);
+ attr->MergeWith(attrtomerge);
+ attr->SetReadOnly();
+ attrtomerge->DecRef();
+ }
+ attr->SetReadOnly();
+ }
+ break;
+ case (wxGridCellAttr::Col):
+ //As we must have a Coll, and were setting Coll attributes
+ // we can based on wxdbTable's so just set RO if attr valid
+ if (!attr)
+ {
+ attr = new wxGridCellAttr;
+ wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
+ attr->IncRef();
+ self->SetColAttr(attr, col);
+ }
+ attr->SetReadOnly();
+ break;
+ default:
+ //Dont add RO for...
+ // wxGridCellAttr::Cell - Not required, will inherit on merge from row.
+ // wxGridCellAttr::Row - If wxDbtable ever supports row locking could add
+ // support to make RO on a row basis also.
+ // wxGridCellAttr::Default - Don't edit this ! or all cell with a attr will become readonly
+ // wxGridCellAttr::Merged - This should never be asked for.
+ break;
+ }
+ }
+
+ }
+ return attr;
+}
+
+void wxDbGridCellAttrProvider::AssignDbTable(wxDbTable *tab)
+{
+ m_data = tab;
+}
+
+wxDbGridTableBase::wxDbGridTableBase(wxDbTable *tab, wxDbGridColInfo* ColInfo,
+ int count, bool takeOwnership) :
+ m_keys(),
+ m_data(tab),
+ m_dbowner(takeOwnership),
+ m_rowmodified(false)
+{
+
+ if (count == wxUSE_QUERY)
+ {
+ m_rowtotal = m_data ? m_data->Count() : 0;
+ }
+ else
+ {
+ m_rowtotal = count;
+ }
+// m_keys.Size(m_rowtotal);
+ m_row = -1;
+ if (ColInfo)
+ {
+ m_nocols = ColInfo->Length();
+ m_ColInfo = new wxDbGridColInfoBase[m_nocols];
+ //Do Copy.
+ wxDbGridColInfo *ptr = ColInfo;
+ int i =0;
+ while (ptr && i < m_nocols)
+ {
+ m_ColInfo[i] = ptr->m_data;
+ ptr = ptr->m_next;
+ i++;
+ }
+#ifdef __WXDEBUG__
+ if (ptr)
+ {
+ wxLogDebug(wxT("NoCols over length after traversing %i items"),i);
+ }
+ if (i < m_nocols)
+ {
+ wxLogDebug(wxT("NoCols under length after traversing %i items"),i);
+ }
+#endif
+ }
+}
+
+wxDbGridTableBase::~wxDbGridTableBase()
+{
+ wxDbGridCellAttrProvider *provider;
+
+ //Can't check for update here as
+
+ //FIXME: should i remove m_ColInfo and m_data from m_attrProvider if a wxDbGridAttrProvider
+// if ((provider = dynamic_cast<wxDbGridCellAttrProvider *>(GetAttrProvider())))
+ // Using C casting for now until we can support dynamic_cast with wxWindows
+ if ((provider = (wxDbGridCellAttrProvider *)(GetAttrProvider())))
+ {
+ provider->AssignDbTable(NULL);
+ }
+ delete [] m_ColInfo;
+
+ Writeback();
+ if (m_dbowner)
+ {
+ delete m_data;
+ }
+}
+
+bool wxDbGridTableBase::CanHaveAttributes()
+{
+ if (!GetAttrProvider())
+ {
+ // use the default attr provider by default
+ SetAttrProvider(new wxDbGridCellAttrProvider(m_data, m_ColInfo));
+ }
+ return true;
+}
+
+
+bool wxDbGridTableBase::AssignDbTable(wxDbTable *tab, int count, bool takeOwnership)
+{
+ wxDbGridCellAttrProvider *provider;
+
+ //Remove Information from grid about old data
+ if (GetView())
+ {
+ wxGrid *grid = GetView();
+ grid->BeginBatch();
+ grid->ClearSelection();
+ if (grid->IsCellEditControlEnabled())
+ {
+ grid->DisableCellEditControl();
+ }
+ wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED,0,m_rowtotal);
+ grid->ProcessTableMessage(msg);
+ }
+
+ //reset our internals...
+ Writeback();
+ if (m_dbowner)
+ {
+ delete m_data;
+ }
+ m_keys.Empty();
+ m_data = tab;
+ //FIXME: Remove dynamic_cast before sumision to wxwin
+// if ((provider = dynamic_cast<wxDbGridCellAttrProvider *> (GetAttrProvider())))
+ // Using C casting for now until we can support dynamic_cast with wxWindows
+ if ((provider = (wxDbGridCellAttrProvider *)(GetAttrProvider())))
+ {
+ provider->AssignDbTable(m_data);
+ }
+
+ if (count == wxUSE_QUERY)
+ {
+ m_rowtotal = m_data ? m_data->Count() : 0;
+ }
+ else
+ {
+ m_rowtotal = count;
+ }
+ m_row = -1;
+
+ //Add Information to grid about new data
+ if (GetView())
+ {
+ wxGrid * grid = GetView();
+ wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rowtotal);
+ grid->ProcessTableMessage(msg);
+ grid->EndBatch();
+ }
+ m_dbowner = takeOwnership;
+ m_rowmodified = false;
+ return true;
+}
+
+wxString wxDbGridTableBase::GetTypeName(int row, int col)
+{
+ if (col == 8)
+ int breakpoint = 1;
+
+ if (GetNumberCols() > col)
+ {
+ if (m_ColInfo[col].wxtypename == wxGRID_VALUE_DBAUTO)
+ {
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use wxGRID_VALUE_DBAUTO for virtual columns"));
+ }
+ switch(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype)
+ {
+ case SQL_C_CHAR:
+ return wxGRID_VALUE_STRING;
+ break;
+ case SQL_C_SSHORT:
+ return wxGRID_VALUE_NUMBER;
+ break;
+ case SQL_C_USHORT:
+ return wxGRID_VALUE_NUMBER;
+ break;
+ case SQL_C_SLONG:
+ return wxGRID_VALUE_NUMBER;
+ break;
+ case SQL_C_ULONG:
+ return wxGRID_VALUE_NUMBER;
+ break;
+ case SQL_C_FLOAT:
+ return wxGRID_VALUE_FLOAT;
+ break;
+ case SQL_C_DOUBLE:
+ return wxGRID_VALUE_FLOAT;
+ break;
+ case SQL_C_DATE:
+ return wxGRID_VALUE_DATETIME;
+ break;
+ case SQL_C_TIME:
+ return wxGRID_VALUE_DATETIME;
+ break;
+ case SQL_C_TIMESTAMP:
+ return wxGRID_VALUE_DATETIME;
+ break;
+ default:
+ return wxGRID_VALUE_STRING;
+ break;
+ }
+ }
+ else
+ {
+ return m_ColInfo[col].wxtypename;
+ }
+ }
+ wxFAIL_MSG (_T("unknown column"));
+ return wxString();
+}
+
+bool wxDbGridTableBase::CanGetValueAs(int row, int col, const wxString& typeName)
+{
+ wxLogDebug(wxT("CanGetValueAs() on %i,%i"),row,col);
+ //Is this needed? As it will be validated on GetValueAsXXXX
+ ValidateRow(row);
+
+ if (typeName == wxGRID_VALUE_STRING)
+ {
+ //FIXME ummm What about blob field etc.
+ return true;
+ }
+
+ if (m_data->IsColNull(m_ColInfo[col].DbCol))
+ {
+ return false;
+ }
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ //If a virtual column then we can't find it's type. we have to
+ // return false to get using wxVariant.
+ return false;
+ }
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+
+ if (typeName == wxGRID_VALUE_DATETIME)
+ {
+ if ((sqltype == SQL_C_DATE) ||
+ (sqltype == SQL_C_TIME) ||
+ (sqltype == SQL_C_TIMESTAMP))
+ {
+ return true;
+ }
+ return false;
+ }
+ if (typeName == wxGRID_VALUE_NUMBER)
+ {
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG))
+ {
+ return true;
+ }
+ return false;
+ }
+ if (typeName == wxGRID_VALUE_FLOAT)
+ {
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG) ||
+ (sqltype == SQL_C_FLOAT) ||
+ (sqltype == SQL_C_DOUBLE))
+ {
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+bool wxDbGridTableBase::CanSetValueAs(int row, int col, const wxString& typeName)
+{
+ //Is this needed? As will be validated on SetValueAsXXXX
+ ValidateRow(row);
+
+ if (m_data->IsColNull(m_ColInfo[col].DbCol))
+ {
+ return false;
+ }
+
+ if (typeName == wxGRID_VALUE_STRING)
+ {
+ //FIXME ummm What about blob field etc.
+ return true;
+ }
+
+ if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
+ {
+ return false;
+ }
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ //If a virtual column then we can't find it's type. we have to faulse to
+ //get using wxVairent.
+ return false;
+ }
+
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+ if (typeName == wxGRID_VALUE_DATETIME)
+ {
+ if ((sqltype == SQL_C_DATE) ||
+ (sqltype == SQL_C_TIME) ||
+ (sqltype == SQL_C_TIMESTAMP))
+ {
+ return true;
+ }
+ return false;
+ }
+ if (typeName == wxGRID_VALUE_NUMBER)
+ {
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG))
+ {
+ return true;
+ }
+ return false;
+ }
+ if (typeName == wxGRID_VALUE_FLOAT)
+ {
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG) ||
+ (sqltype == SQL_C_FLOAT) ||
+ (sqltype == SQL_C_DOUBLE))
+ {
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+long wxDbGridTableBase::GetValueAsLong(int row, int col)
+{
+ ValidateRow(row);
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use GetValueAsLong for virtual columns"));
+ return 0;
+ }
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG))
+ {
+ wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
+ return val.GetLong();
+ }
+ wxFAIL_MSG (_T("unknown column, "));
+ return 0;
+}
+
+double wxDbGridTableBase::GetValueAsDouble(int row, int col)
+{
+ wxLogDebug(wxT("GetValueAsDouble() on %i,%i"),row,col);
+ ValidateRow(row);
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use GetValueAsDouble for virtual columns"));
+ return 0.0;
+ }
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG) ||
+ (sqltype == SQL_C_FLOAT) ||
+ (sqltype == SQL_C_DOUBLE))
+ {
+ wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
+ return val.GetDouble();
+ }
+ wxFAIL_MSG (_T("unknown column"));
+ return 0.0;
+}
+
+bool wxDbGridTableBase::GetValueAsBool(int row, int col)
+{
+ wxLogDebug(wxT("GetValueAsBool() on %i,%i"),row,col);
+ ValidateRow(row);
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use GetValueAsBool for virtual columns"));
+ return 0;
+ }
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+ if ((sqltype == SQL_C_SSHORT) ||
+ (sqltype == SQL_C_USHORT) ||
+ (sqltype == SQL_C_SLONG) ||
+ (sqltype == SQL_C_ULONG))
+ {
+ wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
+ return val.GetBool();
+ }
+ wxFAIL_MSG (_T("unknown column, "));
+ return 0;
+}
+
+void* wxDbGridTableBase::GetValueAsCustom(int row, int col, const wxString& typeName)
+{
+ wxLogDebug(wxT("GetValueAsCustom() on %i,%i"),row,col);
+ ValidateRow(row);
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use GetValueAsCustom for virtual columns"));
+ return NULL;
+ }
+ if (m_data->IsColNull(m_ColInfo[col].DbCol))
+ return NULL;
+
+ if (typeName == wxGRID_VALUE_DATETIME)
+ {
+ wxDbColDef *pColDefs = m_data->GetColDefs();
+ int sqltype = pColDefs[(m_ColInfo[col].DbCol)].SqlCtype;
+
+ if ((sqltype == SQL_C_DATE) ||
+ (sqltype == SQL_C_TIME) ||
+ (sqltype == SQL_C_TIMESTAMP))
+ {
+ wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
+ return new wxDateTime(val.GetDateTime());
+ }
+ }
+ wxFAIL_MSG (_T("unknown column data type "));
+ return NULL;
+}
+
+
+void wxDbGridTableBase::SetValueAsCustom(int row, int col, const wxString& typeName, void* value)
+{
+ wxLogDebug(wxT("SetValueAsCustom() on %i,%i"),row,col);
+ ValidateRow(row);
+
+ if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
+ {
+ wxFAIL_MSG (_T("You can not use SetValueAsCustom for virtual columns"));
+ return;
+ }
+
+ if (typeName == wxGRID_VALUE_DATETIME)
+ {
+ int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
+ if ((sqltype == SQL_C_DATE) ||
+ (sqltype == SQL_C_TIME) ||
+ (sqltype == SQL_C_TIMESTAMP))
+ {
+ //FIXME: you can't dynamic_cast from (void *)
+ //wxDateTime *date = wxDynamicCast(value, wxDateTime);
+ wxDateTime *date = (wxDateTime *)value;
+ if (!date)
+ {
+ wxFAIL_MSG (_T("Failed to convert data"));
+ return;
+ }
+ wxVariant val(date);
+ m_rowmodified = true;
+ m_data->SetCol(m_ColInfo[col].DbCol,val);
+ }
+ }
+ wxFAIL_MSG (_T("unknown column data type"));
+ return ;
+}
+
+
+wxString wxDbGridTableBase::GetColLabelValue(int col)
+{
+ if (GetNumberCols() > col)
+ {
+ return m_ColInfo[col].Title;
+ }
+ wxFAIL_MSG (_T("unknown column"));
+ return wxString();
+}
+
+bool wxDbGridTableBase::IsEmptyCell(int row, int col)
+{
+ wxLogDebug(wxT("IsEmtpyCell on %i,%i"),row,col);
+
+ ValidateRow(row);
+ return m_data->IsColNull(m_ColInfo[col].DbCol);
+}
+
+
+wxString wxDbGridTableBase::GetValue(int row, int col)
+{
+ wxLogDebug(wxT("GetValue() on %i,%i"),row,col);
+
+ ValidateRow(row);
+ wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
+ wxLogDebug(wxT("\tReturning \"%s\"\n"),val.GetString().c_str());
+
+ return val.GetString();
+}
+
+
+void wxDbGridTableBase::SetValue(int row, int col,const wxString& value)
+{
+ wxLogDebug(wxT("SetValue() on %i,%i"),row,col);
+
+ ValidateRow(row);
+ wxVariant val(value);
+
+ m_rowmodified = true;
+ m_data->SetCol(m_ColInfo[col].DbCol,val);
+}
+
+
+void wxDbGridTableBase::SetValueAsLong(int row, int col, long value)
+{
+ wxLogDebug(wxT("SetValueAsLong() on %i,%i"),row,col);
+
+ ValidateRow(row);
+ wxVariant val(value);
+
+ m_rowmodified = true;
+ m_data->SetCol(m_ColInfo[col].DbCol,val);
+}
+
+
+void wxDbGridTableBase::SetValueAsDouble(int row, int col, double value)
+{
+ wxLogDebug(wxT("SetValueAsDouble() on %i,%i"),row,col);
+
+ ValidateRow(row);
+ wxVariant val(value);
+
+ m_rowmodified = true;
+ m_data->SetCol(m_ColInfo[col].DbCol,val);
+
+}
+
+
+void wxDbGridTableBase::SetValueAsBool(int row, int col, bool value)
+{
+ wxLogDebug(wxT("SetValueAsBool() on %i,%i"),row,col);
+
+ ValidateRow(row);
+ wxVariant val(value);
+
+ m_rowmodified = true;
+ m_data->SetCol(m_ColInfo[col].DbCol,val);
+}
+
+
+void wxDbGridTableBase::ValidateRow(int row)
+{
+ wxLogDebug(wxT("ValidateRow(%i) currently on row (%i). Array count = %i"),row,m_row,m_keys.GetCount());
+
+ if (row == m_row)
+ return;
+ Writeback();
+
+ //We add to row as Count is unsigned!
+ if ((unsigned)(row+1) > m_keys.GetCount())
+ {
+ wxLogDebug(wxT("\trow key unknown"));
+ // Extend Array, iterate through data filling with keys
+ m_data->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
+ int trow;
+ for (trow = m_keys.GetCount(); trow <= row; trow++)
+ {
+ wxLogDebug(wxT("Fetching row %i.."), trow);
+ bool ret = m_data->GetNext();
+
+ wxLogDebug(wxT(" ...success=(%i)"),ret);
+ GenericKey k = m_data->GetKey();
+ m_keys.Add(k);
+ }
+ m_row = row;
+ }
+ else
+ {
+ wxLogDebug(wxT("\trow key known centering data"));
+ GenericKey k = m_keys.Item(row);
+ m_data->SetRowMode(wxDbTable::WX_ROW_MODE_INDIVIDUAL);
+ m_data->ClearMemberVars();
+ m_data->SetKey(k);
+ if (!m_data->QueryOnKeyFields())
+ {
+ wxDbLogExtendedErrorMsg("ODBC error during Query()\n\n", m_data->GetDb(),__FILE__,__LINE__);
+ }
+
+ m_data->GetNext();
+
+ m_row = row;
+ }
+ m_rowmodified = false;
+}
+
+bool wxDbGridTableBase::Writeback() const
+{
+ if (!m_rowmodified)
+ {
+ return true;
+ }
+
+ bool result=true;
+ wxLogDebug(wxT("\trow key unknown"));
+
+// FIXME: this code requires dbtable support for record status
+#if 0
+ switch (m_data->get_ModifiedStatus())
+ {
+ case wxDbTable::UpdatePending:
+ result = m_data->Update();
+ break;
+ case wxDbTable::InsertPending:
+ result = (m_data->Insert() == SQL_SUCCESS);
+ break;
+ default:
+ //Nothing
+ break;
+ }
+#else
+ wxLogDebug(wxT("WARNING : Row writeback not implemented "));
+#endif
+ return result;
+}
+
+#include <wx/arrimpl.cpp>
+
+WX_DEFINE_OBJARRAY(keyarray);
+
+#endif // #if wxUSE_NEW_GRID
+#endif // #if wxUSE_ODBC
+