home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / dbgrid.cpp < prev    next >
C/C++ Source or Header  |  2002-02-07  |  21KB  |  726 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        dbgrid.cpp
  3. // Purpose:     Displays a wxDbTable in a wxGrid.
  4. // Author:      Roger Gammans, Paul Gammans
  5. // Modified by:
  6. // Created:
  7. // RCS-ID:      $Id: dbgrid.cpp,v 1.8 2002/02/07 14:44:44 GT Exp $
  8. // Copyright:   (c) 1999 The Computer Surgery (roger@computer-surgery.co.uk)
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // Branched From : dbgrid.cpp,v 1.18 2000/12/19 13:00:58
  12. ///////////////////////////////////////////////////////////////////////////////
  13.  
  14. #ifdef __GNUG__
  15.     #pragma implementation "dbgrid.h"
  16. #endif
  17.  
  18. #include "wx/wxprec.h"
  19.  
  20. #ifdef __BORLANDC__
  21.     #pragma hdrstop
  22. #endif
  23.  
  24.  
  25. #if wxUSE_ODBC
  26. #if wxUSE_NEW_GRID
  27.  
  28. #ifndef WX_PRECOMP
  29.     #include "wx/textctrl.h"
  30.     #include "wx/dc.h"
  31. #endif // WX_PRECOMP
  32.  
  33. #include "wx/generic/gridctrl.h"
  34. #include "wx/dbgrid.h"
  35.  
  36.  
  37. wxDbGridCellAttrProvider::wxDbGridCellAttrProvider()
  38. {
  39.     m_data=NULL;
  40.     m_ColInfo=NULL;
  41. }
  42.  
  43. wxDbGridCellAttrProvider::wxDbGridCellAttrProvider(wxDbTable *tab, wxDbGridColInfoBase* ColInfo)
  44. {
  45.     m_data=tab;
  46.     m_ColInfo=ColInfo;
  47. }
  48.  
  49. wxDbGridCellAttrProvider::~wxDbGridCellAttrProvider()
  50. {
  51. }
  52.  
  53. wxGridCellAttr *wxDbGridCellAttrProvider::GetAttr(int row, int col,
  54.                                       wxGridCellAttr::wxAttrKind  kind) const
  55. {
  56.     wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row,col,kind);
  57.  
  58.     if (m_data && m_ColInfo && (m_data->GetNumberOfColumns() > m_ColInfo[col].DbCol))
  59.     {
  60.         //FIXME: this test could.
  61.         //  ??::InsertPending == m_data->get_ModifiedStatus()
  62.         //  and if InsertPending use colDef[].InsertAllowed
  63.         if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
  64.         {
  65.             switch(kind)
  66.             {
  67.                 case (wxGridCellAttr::Any):
  68.                     if (!attr)
  69.                     {
  70.                         attr = new wxGridCellAttr;
  71.                         // Store so we don't keep creating / deleting this...
  72.                         wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
  73.                         attr->IncRef();
  74.                         self->SetColAttr(attr, col);
  75.                         attr->SetReadOnly();
  76.                     }
  77.                     else
  78.                     {
  79.                         //We now must check what we were returned. and do the right thing (tm)
  80.                         wxGridCellAttr::wxAttrKind attrkind = attr->GetKind();
  81.                         if ((attrkind == (wxGridCellAttr::Default)) || (attrkind == (wxGridCellAttr::Cell)) ||
  82.                             (attrkind == (wxGridCellAttr::Col)))
  83.                         {
  84.                                 wxGridCellAttr *attrtomerge = attr;
  85.                                 attr = new wxGridCellAttr;
  86.                                 attr->SetKind(wxGridCellAttr::Merged);
  87.                                 attr->MergeWith(attrtomerge);
  88.                                 attr->SetReadOnly();
  89.                                 attrtomerge->DecRef();
  90.                         }
  91.                         attr->SetReadOnly();
  92.                     }
  93.                 break;
  94.                 case (wxGridCellAttr::Col):
  95.                     //As we must have a Coll, and were setting Coll attributes
  96.                     // we can based on wxdbTable's so just set RO if attr valid
  97.                     if (!attr)
  98.                     {
  99.                         attr = new wxGridCellAttr;
  100.                         wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
  101.                         attr->IncRef();
  102.                         self->SetColAttr(attr, col);
  103.                     }
  104.                     attr->SetReadOnly();
  105.                 break;
  106.                 default:
  107.                     //Dont add RO for...
  108.                     //  wxGridCellAttr::Cell - Not required, will inherit on merge from row.
  109.                     //  wxGridCellAttr::Row - If wxDbtable ever supports row locking could add
  110.                     //                        support to make RO on a row basis also.
  111.                     //  wxGridCellAttr::Default - Don't edit this ! or all cell with a attr will become readonly
  112.                     //  wxGridCellAttr::Merged - This should never be asked for.
  113.                 break;
  114.             }
  115.         }
  116.  
  117.     }
  118.     return attr;
  119. }
  120.  
  121. void wxDbGridCellAttrProvider::AssignDbTable(wxDbTable *tab)
  122. {
  123.     m_data = tab;
  124. }
  125.  
  126. wxDbGridTableBase::wxDbGridTableBase(wxDbTable *tab, wxDbGridColInfo*  ColInfo,
  127.                      int count, bool takeOwnership)  :
  128.     m_keys(),
  129.     m_data(tab),
  130.     m_dbowner(takeOwnership),
  131.     m_rowmodified(FALSE)
  132. {
  133.  
  134.     if (count == wxUSE_QUERY)
  135.     {
  136.         m_rowtotal = m_data ? m_data->Count() : 0;
  137.     }
  138.     else
  139.     {
  140.         m_rowtotal = count;
  141.     }
  142. //    m_keys.Size(m_rowtotal);
  143.     m_row = -1;
  144.     if (ColInfo)
  145.     {
  146.         m_nocols = ColInfo->Length();
  147.         m_ColInfo = new wxDbGridColInfoBase[m_nocols];
  148.         //Do Copy.
  149.         wxDbGridColInfo *ptr = ColInfo;
  150.         int i =0;
  151.         while (ptr && i < m_nocols)
  152.         {
  153.             m_ColInfo[i] = ptr->m_data;
  154.             ptr = ptr->m_next;
  155.             i++;
  156.         }
  157. #ifdef __WXDEBUG__
  158.         if (ptr)
  159.         {
  160.             wxLogDebug(wxT("NoCols over length after traversing %i items"),i);
  161.         }
  162.         if (i < m_nocols)
  163.         {
  164.             wxLogDebug(wxT("NoCols under length after traversing %i items"),i);
  165.         }
  166. #endif
  167.     }
  168. }
  169.  
  170. wxDbGridTableBase::~wxDbGridTableBase()
  171. {
  172.     wxDbGridCellAttrProvider *provider;
  173.  
  174.     //Can't check for update here as
  175.  
  176.     //FIXME: should i remove m_ColInfo and m_data from m_attrProvider if a wxDbGridAttrProvider
  177. //    if ((provider = dynamic_cast<wxDbGridCellAttrProvider *>(GetAttrProvider())))
  178.      // Using C casting for now until we can support dynamic_cast with wxWindows
  179.     provider = (wxDbGridCellAttrProvider *)(GetAttrProvider());
  180.     if (provider)
  181.     {
  182.         provider->AssignDbTable(NULL);
  183.     }
  184.     delete [] m_ColInfo;
  185.  
  186.     Writeback();
  187.     if (m_dbowner)
  188.     {
  189.         delete m_data;
  190.     }
  191. }
  192.  
  193. bool wxDbGridTableBase::CanHaveAttributes()
  194. {
  195.     if (!GetAttrProvider())
  196.     {
  197.         // use the default attr provider by default
  198.         SetAttrProvider(new wxDbGridCellAttrProvider(m_data, m_ColInfo));
  199.     }
  200.     return TRUE;
  201. }
  202.  
  203.  
  204. bool wxDbGridTableBase::AssignDbTable(wxDbTable *tab, int count, bool takeOwnership)
  205. {
  206.     wxDbGridCellAttrProvider *provider;
  207.  
  208.     //Remove Information from grid about old data
  209.     if (GetView())
  210.     {
  211.         wxGrid *grid = GetView();
  212.         grid->BeginBatch();
  213.         grid->ClearSelection();
  214.         if (grid->IsCellEditControlEnabled())
  215.         {
  216.             grid->DisableCellEditControl();
  217.         }
  218.         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED,0,m_rowtotal);
  219.         grid->ProcessTableMessage(msg);
  220.     }
  221.  
  222.     //reset our internals...
  223.     Writeback();
  224.     if (m_dbowner)
  225.     {
  226.         delete m_data;
  227.     }
  228.     m_keys.Empty();
  229.     m_data = tab;
  230.     //FIXME: Remove dynamic_cast before sumision to wxwin
  231. //    if ((provider = dynamic_cast<wxDbGridCellAttrProvider *> (GetAttrProvider())))
  232.      // Using C casting for now until we can support dynamic_cast with wxWindows
  233.     provider = (wxDbGridCellAttrProvider *)(GetAttrProvider());
  234.     if (provider)
  235.     {
  236.         provider->AssignDbTable(m_data);
  237.     }
  238.  
  239.     if (count == wxUSE_QUERY)
  240.     {
  241.         m_rowtotal = m_data ? m_data->Count() : 0;
  242.     }
  243.     else
  244.     {
  245.          m_rowtotal = count;
  246.     }
  247.     m_row = -1;
  248.  
  249.     //Add Information to grid about new data
  250.     if (GetView())
  251.     {
  252.         wxGrid * grid = GetView();
  253.         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rowtotal);
  254.         grid->ProcessTableMessage(msg);
  255.         grid->EndBatch();
  256.     }
  257.     m_dbowner = takeOwnership;
  258.     m_rowmodified = FALSE;
  259.     return TRUE;
  260. }
  261.  
  262. wxString wxDbGridTableBase::GetTypeName(int row, int col)
  263. {
  264.     if (GetNumberCols() > col)
  265.     {
  266.         if (m_ColInfo[col].wxtypename == wxGRID_VALUE_DBAUTO)
  267.         {
  268.             if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  269.             {
  270.                 wxFAIL_MSG (_T("You can not use wxGRID_VALUE_DBAUTO for virtual columns"));
  271.             }
  272.             switch(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype)
  273.             {
  274.                 case SQL_C_CHAR:
  275.                     return wxGRID_VALUE_STRING;
  276.                 case SQL_C_SSHORT:
  277.                     return wxGRID_VALUE_NUMBER;
  278.                 case SQL_C_USHORT:
  279.                     return wxGRID_VALUE_NUMBER;
  280.                 case SQL_C_SLONG:
  281.                     return wxGRID_VALUE_NUMBER;
  282.                 case SQL_C_ULONG:
  283.                     return wxGRID_VALUE_NUMBER;
  284.                 case SQL_C_FLOAT:
  285.                     return wxGRID_VALUE_FLOAT;
  286.                 case SQL_C_DOUBLE:
  287.                     return wxGRID_VALUE_FLOAT;
  288.                 case SQL_C_DATE:
  289.                     return wxGRID_VALUE_DATETIME;
  290.                 case SQL_C_TIME:
  291.                     return wxGRID_VALUE_DATETIME;
  292.                 case SQL_C_TIMESTAMP:
  293.                     return wxGRID_VALUE_DATETIME;
  294.                 default:
  295.                     return wxGRID_VALUE_STRING;
  296.             }
  297.         }
  298.         else
  299.         {
  300.             return m_ColInfo[col].wxtypename;
  301.         }
  302.     }
  303.     wxFAIL_MSG (_T("unknown column"));
  304.     return wxString();
  305. }
  306.  
  307. bool wxDbGridTableBase::CanGetValueAs(int row, int col, const wxString& typeName)
  308. {
  309.     wxLogDebug(wxT("CanGetValueAs() on %i,%i"),row,col);
  310.     //Is this needed? As it will be validated on GetValueAsXXXX
  311.     ValidateRow(row);
  312.  
  313.     if (typeName == wxGRID_VALUE_STRING)
  314.     {
  315.         //FIXME ummm What about blob field etc.
  316.         return TRUE;
  317.     }
  318.  
  319.     if (m_data->IsColNull(m_ColInfo[col].DbCol))
  320.     {
  321.         return FALSE;
  322.     }
  323.  
  324.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  325.     {
  326.         //If a virtual column then we can't find it's type. we have to
  327.         // return FALSE to get using wxVariant.
  328.         return FALSE;
  329.     }
  330.     int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  331.  
  332.     if (typeName == wxGRID_VALUE_DATETIME)
  333.     {
  334.         if ((sqltype == SQL_C_DATE) ||
  335.             (sqltype == SQL_C_TIME) ||
  336.             (sqltype == SQL_C_TIMESTAMP))
  337.         {
  338.             return TRUE;
  339.         }
  340.         return FALSE;
  341.     }
  342.     if (typeName == wxGRID_VALUE_NUMBER)
  343.     {
  344.         if ((sqltype == SQL_C_SSHORT) ||
  345.             (sqltype == SQL_C_USHORT) ||
  346.             (sqltype == SQL_C_SLONG)  ||
  347.             (sqltype == SQL_C_ULONG))
  348.         {
  349.             return TRUE;
  350.         }
  351.         return FALSE;
  352.     }
  353.     if (typeName == wxGRID_VALUE_FLOAT)
  354.     {
  355.         if ((sqltype == SQL_C_SSHORT) ||
  356.             (sqltype == SQL_C_USHORT) ||
  357.             (sqltype == SQL_C_SLONG)  ||
  358.             (sqltype == SQL_C_ULONG)  ||
  359.             (sqltype == SQL_C_FLOAT)  ||
  360.             (sqltype == SQL_C_DOUBLE))
  361.         {
  362.             return TRUE;
  363.         }
  364.         return FALSE;
  365.     }
  366.     return FALSE;
  367. }
  368.  
  369. bool wxDbGridTableBase::CanSetValueAs(int row, int col, const wxString& typeName)
  370. {
  371.     if (typeName == wxGRID_VALUE_STRING)
  372.     {
  373.         //FIXME ummm What about blob field etc.
  374.         return TRUE;
  375.     }
  376.  
  377.     if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
  378.     {
  379.         return FALSE;
  380.     }
  381.  
  382.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  383.     {
  384.         //If a virtual column then we can't find it's type. we have to faulse to
  385.         //get using wxVairent.
  386.         return FALSE;
  387.     }
  388.  
  389.     int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  390.     if (typeName == wxGRID_VALUE_DATETIME)
  391.     {
  392.         if ((sqltype == SQL_C_DATE) ||
  393.             (sqltype == SQL_C_TIME) ||
  394.             (sqltype == SQL_C_TIMESTAMP))
  395.         {
  396.             return TRUE;
  397.         }
  398.         return FALSE;
  399.     }
  400.     if (typeName == wxGRID_VALUE_NUMBER)
  401.     {
  402.         if ((sqltype == SQL_C_SSHORT) ||
  403.             (sqltype == SQL_C_USHORT) ||
  404.             (sqltype == SQL_C_SLONG)  ||
  405.             (sqltype == SQL_C_ULONG))
  406.         {
  407.             return TRUE;
  408.         }
  409.         return FALSE;
  410.     }
  411.     if (typeName == wxGRID_VALUE_FLOAT)
  412.     {
  413.         if ((sqltype == SQL_C_SSHORT) ||
  414.             (sqltype == SQL_C_USHORT) ||
  415.             (sqltype == SQL_C_SLONG)  ||
  416.             (sqltype == SQL_C_ULONG)  ||
  417.             (sqltype == SQL_C_FLOAT)  ||
  418.             (sqltype == SQL_C_DOUBLE))
  419.         {
  420.             return TRUE;
  421.         }
  422.         return FALSE;
  423.     }
  424.     return FALSE;
  425. }
  426.  
  427. long wxDbGridTableBase::GetValueAsLong(int row, int col)
  428. {
  429.     ValidateRow(row);
  430.  
  431.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  432.     {
  433.         wxFAIL_MSG (_T("You can not use GetValueAsLong for virtual columns"));
  434.         return 0;
  435.     }
  436.     int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  437.     if ((sqltype == SQL_C_SSHORT) ||
  438.         (sqltype == SQL_C_USHORT) ||
  439.         (sqltype == SQL_C_SLONG) ||
  440.         (sqltype == SQL_C_ULONG))
  441.     {
  442.         wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
  443.         return val.GetLong();
  444.     }
  445.     wxFAIL_MSG (_T("unknown column, "));
  446.     return 0;
  447. }
  448.  
  449. double wxDbGridTableBase::GetValueAsDouble(int row, int col)
  450. {
  451.     wxLogDebug(wxT("GetValueAsDouble() on %i,%i"),row,col);
  452.     ValidateRow(row);
  453.  
  454.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  455.     {
  456.         wxFAIL_MSG (_T("You can not use GetValueAsDouble for virtual columns"));
  457.         return 0.0;
  458.     }
  459.     int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  460.     if ((sqltype == SQL_C_SSHORT) ||
  461.         (sqltype == SQL_C_USHORT) ||
  462.         (sqltype == SQL_C_SLONG) ||
  463.         (sqltype == SQL_C_ULONG) ||
  464.         (sqltype == SQL_C_FLOAT) ||
  465.         (sqltype == SQL_C_DOUBLE))
  466.     {
  467.         wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
  468.         return val.GetDouble();
  469.     }
  470.     wxFAIL_MSG (_T("unknown column"));
  471.     return 0.0;
  472. }
  473.  
  474. bool wxDbGridTableBase::GetValueAsBool(int row, int col)
  475. {
  476.     wxLogDebug(wxT("GetValueAsBool() on %i,%i"),row,col);
  477.     ValidateRow(row);
  478.  
  479.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  480.     {
  481.         wxFAIL_MSG (_T("You can not use GetValueAsBool for virtual columns"));
  482.         return 0;
  483.     }
  484.     int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  485.     if ((sqltype == SQL_C_SSHORT) ||
  486.         (sqltype == SQL_C_USHORT) ||
  487.         (sqltype == SQL_C_SLONG) ||
  488.         (sqltype == SQL_C_ULONG))
  489.     {
  490.         wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
  491.         return val.GetBool();
  492.     }
  493.     wxFAIL_MSG (_T("unknown column, "));
  494.     return 0;
  495. }
  496.  
  497. void* wxDbGridTableBase::GetValueAsCustom(int row, int col, const wxString& typeName)
  498. {
  499.     wxLogDebug(wxT("GetValueAsCustom() on %i,%i"),row,col);
  500.     ValidateRow(row);
  501.  
  502.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  503.     {
  504.         wxFAIL_MSG (_T("You can not use GetValueAsCustom for virtual columns"));
  505.         return NULL;
  506.     }
  507.     if (m_data->IsColNull(m_ColInfo[col].DbCol))
  508.         return NULL;
  509.  
  510.     if (typeName == wxGRID_VALUE_DATETIME)
  511.     {
  512.         wxDbColDef *pColDefs = m_data->GetColDefs();
  513.         int sqltype = pColDefs[(m_ColInfo[col].DbCol)].SqlCtype;
  514.  
  515.         if ((sqltype == SQL_C_DATE) ||
  516.             (sqltype == SQL_C_TIME) ||
  517.             (sqltype == SQL_C_TIMESTAMP))
  518.         {
  519.             wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
  520.             return new wxDateTime(val.GetDateTime());
  521.         }
  522.     }
  523.     wxFAIL_MSG (_T("unknown column data type "));
  524.     return NULL;
  525. }
  526.  
  527.  
  528. void wxDbGridTableBase::SetValueAsCustom(int row, int col, const wxString& typeName, void* value)
  529. {
  530.     wxLogDebug(wxT("SetValueAsCustom() on %i,%i"),row,col);
  531.     ValidateRow(row);
  532.  
  533.     if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
  534.     {
  535.         wxFAIL_MSG (_T("You can not use SetValueAsCustom for virtual columns"));
  536.         return;
  537.     }
  538.  
  539.     if (typeName == wxGRID_VALUE_DATETIME)
  540.     {
  541.         int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
  542.         if ((sqltype == SQL_C_DATE) ||
  543.             (sqltype == SQL_C_TIME) ||
  544.             (sqltype == SQL_C_TIMESTAMP))
  545.         {
  546.             //FIXME: you can't dynamic_cast from (void *)
  547.             //wxDateTime *date = wxDynamicCast(value, wxDateTime);
  548.             wxDateTime *date = (wxDateTime *)value;
  549.             if (!date)
  550.             {
  551.                 wxFAIL_MSG (_T("Failed to convert data"));
  552.                 return;
  553.             }
  554.             wxVariant val(date);
  555.             m_rowmodified = TRUE;
  556.             m_data->SetCol(m_ColInfo[col].DbCol,val);
  557.         }
  558.     }
  559.     wxFAIL_MSG (_T("unknown column data type"));
  560.     return ;
  561. }
  562.  
  563.  
  564. wxString wxDbGridTableBase::GetColLabelValue(int col)
  565. {
  566.     if (GetNumberCols() > col)
  567.     {
  568.         return m_ColInfo[col].Title;
  569.     }
  570.     wxFAIL_MSG (_T("unknown column"));
  571.     return wxString();
  572. }
  573.  
  574. bool wxDbGridTableBase::IsEmptyCell(int row, int col)
  575. {
  576.     wxLogDebug(wxT("IsEmtpyCell on %i,%i"),row,col);
  577.  
  578.     ValidateRow(row);
  579.     return m_data->IsColNull(m_ColInfo[col].DbCol);
  580. }
  581.  
  582.  
  583. wxString wxDbGridTableBase::GetValue(int row, int col)
  584. {
  585.     wxLogDebug(wxT("GetValue() on %i,%i"),row,col);
  586.  
  587.     ValidateRow(row);
  588.     wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
  589.     wxLogDebug(wxT("\tReturning \"%s\"\n"),val.GetString().c_str());
  590.  
  591.     return val.GetString();
  592. }
  593.  
  594.  
  595. void wxDbGridTableBase::SetValue(int row, int col,const wxString& value)
  596. {
  597.     wxLogDebug(wxT("SetValue() on %i,%i"),row,col);
  598.  
  599.     ValidateRow(row);
  600.     wxVariant val(value);
  601.  
  602.     m_rowmodified = TRUE;
  603.     m_data->SetCol(m_ColInfo[col].DbCol,val);
  604. }
  605.  
  606.  
  607. void wxDbGridTableBase::SetValueAsLong(int row, int col, long value)
  608. {
  609.     wxLogDebug(wxT("SetValueAsLong() on %i,%i"),row,col);
  610.  
  611.     ValidateRow(row);
  612.     wxVariant val(value);
  613.  
  614.     m_rowmodified = TRUE;
  615.     m_data->SetCol(m_ColInfo[col].DbCol,val);
  616. }
  617.  
  618.  
  619. void wxDbGridTableBase::SetValueAsDouble(int row, int col, double value)
  620. {
  621.     wxLogDebug(wxT("SetValueAsDouble() on %i,%i"),row,col);
  622.  
  623.     ValidateRow(row);
  624.     wxVariant val(value);
  625.  
  626.     m_rowmodified = TRUE;
  627.     m_data->SetCol(m_ColInfo[col].DbCol,val);
  628.  
  629. }
  630.  
  631.  
  632. void wxDbGridTableBase::SetValueAsBool(int row, int col, bool value)
  633. {
  634.     wxLogDebug(wxT("SetValueAsBool() on %i,%i"),row,col);
  635.  
  636.     ValidateRow(row);
  637.     wxVariant val(value);
  638.  
  639.     m_rowmodified = TRUE;
  640.     m_data->SetCol(m_ColInfo[col].DbCol,val);
  641. }
  642.  
  643.  
  644. void wxDbGridTableBase::ValidateRow(int row)
  645. {
  646.     wxLogDebug(wxT("ValidateRow(%i) currently on row (%i). Array count = %i"),row,m_row,m_keys.GetCount());
  647.  
  648.     if (row == m_row)
  649.          return;
  650.     Writeback();
  651.  
  652.     //We add to row as Count is unsigned!
  653.     if ((unsigned)(row+1) > m_keys.GetCount())
  654.     {
  655.         wxLogDebug(wxT("\trow key unknown"));
  656.         // Extend Array, iterate through data filling with keys
  657.         m_data->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
  658.         int trow;
  659.         for (trow = m_keys.GetCount(); trow <= row; trow++)
  660.         {
  661.             wxLogDebug(wxT("Fetching row %i.."), trow);
  662.             bool ret = m_data->GetNext();
  663.  
  664.             wxLogDebug(wxT(" ...success=(%i)"),ret);
  665.             GenericKey k = m_data->GetKey();
  666.             m_keys.Add(k);
  667.         }
  668.         m_row = row;
  669.     }
  670.     else
  671.     {
  672.         wxLogDebug(wxT("\trow key known centering data"));
  673.         GenericKey k = m_keys.Item(row);
  674.         m_data->SetRowMode(wxDbTable::WX_ROW_MODE_INDIVIDUAL);
  675.         m_data->ClearMemberVars();
  676.         m_data->SetKey(k);
  677.         if (!m_data->QueryOnKeyFields())
  678.         {
  679.             wxDbLogExtendedErrorMsg("ODBC error during Query()\n\n", m_data->GetDb(),__FILE__,__LINE__);
  680.         }
  681.  
  682.         m_data->GetNext();
  683.  
  684.         m_row = row;
  685.     }
  686.     m_rowmodified = FALSE;
  687. }
  688.  
  689. bool wxDbGridTableBase::Writeback() const
  690. {
  691.     if (!m_rowmodified)
  692.     {
  693.         return TRUE;
  694.     }
  695.  
  696.     bool result=TRUE;
  697.     wxLogDebug(wxT("\trow key unknown"));
  698.  
  699. // FIXME: this code requires dbtable support for record status
  700. #if 0
  701.     switch (m_data->get_ModifiedStatus())
  702.     {
  703.         case wxDbTable::UpdatePending:
  704.             result = m_data->Update();
  705.            break;
  706.         case wxDbTable::InsertPending:
  707.             result = (m_data->Insert() == SQL_SUCCESS);
  708.         break;
  709.         default:
  710.             //Nothing
  711.         break;
  712.     }
  713. #else
  714.     wxLogDebug(wxT("WARNING : Row writeback not implemented "));
  715. #endif
  716.     return result;
  717. }
  718.  
  719. #include "wx/arrimpl.cpp"
  720.  
  721. WX_DEFINE_EXPORTED_OBJARRAY(keyarray);
  722.  
  723. #endif  // #if wxUSE_NEW_GRID
  724. #endif  // #if wxUSE_ODBC
  725.  
  726.