From 32a2907bd33438d2119d587aa9656c0d94e6e460 Mon Sep 17 00:00:00 2001 From: George Tasker Date: Sun, 10 Jun 2001 17:08:42 +0000 Subject: [PATCH] wxDbGrid additions contributed by Paul and Roger Gammans with additions/corrections from George Tasker git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10503 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dbgrid.h | 169 ++++++++++ include/wx/dbkeyg.h | 41 +++ src/common/dbgrid.cpp | 745 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 955 insertions(+) create mode 100644 include/wx/dbgrid.h create mode 100644 include/wx/dbkeyg.h create mode 100644 src/common/dbgrid.cpp diff --git a/include/wx/dbgrid.h b/include/wx/dbgrid.h new file mode 100644 index 0000000000..60f9ca0816 --- /dev/null +++ b/include/wx/dbgrid.h @@ -0,0 +1,169 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_ diff --git a/include/wx/dbkeyg.h b/include/wx/dbkeyg.h new file mode 100644 index 0000000000..d6187688b9 --- /dev/null +++ b/include/wx/dbkeyg.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: dbkeyg.h +// Purpose: Generic key support for wxDbTable +// Author: Roger Gammans +// Modified by: +// Created: +// RCS-ID: $Id$ +// Copyright: (c) 1999 The Computer Surgery (roger@computer-surgery.co.uk) +// Licence: wxWindows licence +// +// NOTE : There is no CPP file to go along with this +// +/////////////////////////////////////////////////////////////////////////////// +// Branched From : gkey.h,v 1.3 2001/06/01 10:31:41 +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_DBGKEY_H_ +#define _WX_DBGKEY_H_ + +class GenericKey +{ +public: + GenericKey(void *blk, size_t sz) { clone(blk,sz); } + GenericKey(const GenericKey &ref) { clone(ref.m_data,ref.m_sz); } + ~GenericKey() { free(m_data); } + + void *GetBlk(void) const { return m_data; } + +private: + void clone(void *blk, size_t sz) + { + m_data = malloc(sz); + memcpy(m_data,blk,sz); + m_sz = sz; + } + + void *m_data; + size_t m_sz; +}; + +#endif // _WX_DBGKEY_H_ diff --git a/src/common/dbgrid.cpp b/src/common/dbgrid.cpp new file mode 100644 index 0000000000..545d3072e8 --- /dev/null +++ b/src/common/dbgrid.cpp @@ -0,0 +1,745 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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(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 (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_DEFINE_OBJARRAY(keyarray); + +#endif // #if wxUSE_NEW_GRID +#endif // #if wxUSE_ODBC + -- 2.45.2