Where can I get a wxDataViewListCtrl::GetValue "col" argument? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
ColleenKobe
Earned some good credits
Earned some good credits
Posts: 109
Joined: Mon Aug 31, 2015 3:47 pm

Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by ColleenKobe »

I am using a wxDataViewListCtrl control called m_Channel_List to display five rows and four columns of data. My problem lies in getting the column number of a value in the wxDataViewListCtrl that changed.

The data structure loaded into the wxDataViewListCtrl is an array of structures: one array structure (element) per wxDataViewListCtrl row. Here is the a snippet from file MainFrame.cpp defining the database.

Code: Select all

// ...
// =============================================================================
//                       Constants Global Within This File
// =============================================================================
#define QTY_CHANNELS        4          // quantity of rows = QTY_CHANNELS + 1 (1 for a header row)
#define QTY_COLUMNS         4
#define COL_OF_CH           0           // column 0 = channel
#define COL_OF_SHUNT        1           // column 1 = shunt on/off
#define COL_OF_PGA          2           // column 2 = PGA value
#define COL_OF_ADC_DF       3           // column 3 = ADC DF value

// =============================================================================
//                         Types Public Within This File
// =============================================================================
enum    t_CH_Type
{   // Each one of these defines a single channel.
    ch_Type_01,                         // Notice number starts at 1, not 0.
    ch_Type_02,
    ch_Type_03,
    ch_Type_04
};  // Each one of these defines a single channel.

enum    t_Shunt_Type
{
    Shunt_Off,
    Shunt_On
};

#define QTY_PGAS   8
enum    t_PGA_Type
{
    PGA_000,    // 0
    PGA_001,    // 1
    PGA_002,    // 2
    PGA_005,    // 3
    PGA_010,    // 4
    PGA_020,    // 5
    PGA_050,    // 6
    PGA_100     // 7
};

#define QTY_ADC_DFS   4
enum    t_ADC_DF_Type
{
    ADC_DF_00,  // 0
    ADC_DF_01,  // 1
    ADC_DF_02,  // 2
    ADC_DF_03   // 3
};



//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Example of the wxDataViewListCtrl display:
//
//                    +------------------------------------+
//                    | Channel  Shunt    PGA      ADC DF  |
//                    | -------  -----    ---      ------  |
//                    |     1     off      50         3    |
//                    |     2      on     100         1    |
//                    |     3     off       2         2    |
//                    |     4     off      20         0    |
//                    +------------------------------------+
//
//  The following values appear as the COLUMN HEADERS for the
//  wxDataViewListCtrl.
//
//      Column #    Identifier  Data Type
//      --------    ----------  ---------
//         0        Channel #    choice: UInt16, [1..4]
//         1        Shunt        choice: 1 binary digit:    [0b0..0b1]
//         2        PGA          choice: 3 binary digits:   [0b000..0b111]
//         3        ADC_DF       choice: 2 binary digits:   [0b00..0b11]
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

typedef struct  t_Channel_Data
{
    t_CH_Type       Ch_Number;  //  0
    t_Shunt_Type    Shunt;      //  1
    t_PGA_Type      PGA;        //  2
    t_ADC_DF_Type   ADC_DF;     //  3
}   t_Channel_Record;   // structure_type_Channel_Data



// =============================================================================
//                         Variables Local to This File
// =============================================================================
static  t_Channel_Record        Orig_Ch_Data    [QTY_CHANNELS];
static  t_Channel_Record        Edited_Ch_Data  [QTY_CHANNELS];

static  bool                    A_Value_Changed;
static  MainFrame*              Local_MF_Ptr;

// ...
In my wxDataViewListCtrl, columns 1, 2, and 3 contain editable wxchoice fields.

I need both the row and column values in order to update my array of structures. I.e. Edited_Ch_Data [row].<correct column> = newvalue;

So, let's say my user changes the value in Row 3, Column 2 (which would be channel 3, PGA). I know I can use GetValue to get the new value:

Code: Select all

void wxDataViewListCtrl::GetValue   (  wxVariant &    value,
      unsigned int   row,
      unsigned int   col
   )
I know I can use GetSelectedRow to get the "row" argument for GetValue.

What I DON'T know is, how do I get the value for the "col" argument for GetValue?

To figure this out on my own:

* I looked at the sample wxDataViewListCtrl code, but it does not cover changing values in the fields. It features display-only information.
* I read and re-read the wxWidgets wxDataViewListCtrl page http://docs.wxwidgets.org/trunk/classwx ... _ctrl.html. I'm sure the right function is there, but I'm just not seeing it.
* I experimented with different values for "col" hardcoded into the GetValue call. The values I tried certainly worked correctly. But how do I know which column was the one that the user just edited?

Suggestions:
1. A GetSelectedCol function would be very handy, and its name would match the format of the GetSelectedRow function that already exists.
2. A GetSelectedPosition function to return both row and column of an edited field would be wonderfully handy, too.

Thanks in advance!!!

Colleen

Versions:
CodeLite 10.0.7
MinGW hard to tell, but I downloaded it on July 10, 2017
Windows 10 Pro, 64-bit, currently running in Test Mode
wxWidgets 3.0.2
wxCrafter 2.6
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by doublemax »

Using the current selection is a little unreliable.

Catch wxEVT_DATAVIEW_ITEM_VALUE_CHANGED event.
wxDataViewEvent::GetItem() returns the item
wxDataViewEvent::GetColumn() will return the column number.

Alternatively you could just update the whole row.

Additional little tip:
If your enums start from zero, use the last value for the total number. Then you don't have to worry about updating the quantity if you add a new value. Which is easily forgotten :)

Code: Select all

//#define QTY_PGAS   8
enum    t_PGA_Type
{
    PGA_000,    // 0
    PGA_001,    // 1
    PGA_002,    // 2
    PGA_005,    // 3
    PGA_010,    // 4
    PGA_020,    // 5
    PGA_050,    // 6
    PGA_100,    // 7
    QTY_PGAS    // 8
};
Use the source, Luke!
User avatar
ColleenKobe
Earned some good credits
Earned some good credits
Posts: 109
Joined: Mon Aug 31, 2015 3:47 pm

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by ColleenKobe »

Thank you for your quick reply, doublemax. Also, thanks for the tip. :-) I'll update my comments and code as you mentioned.

I am using CodeLite, so I don't have wxEVT_DATAVIEW_ITEM_VALUE_CHANGED event. But I do have wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED event, which calls my procedure OnChannel_list_ItemValueChanged.

I made changes that I thought would be "similar." I do get the column number now, and it is correct. Thank you!!!

But now I can't get the new value. :-( When I test my code, I always choose the same "cell" in the wxDataViewListCtrl "table," which is row 1, column 2 (channel 1, PGA). And I always change the value to be the fourth item in the wxchoice drop-down list, so I know the value to return should be 3 (for the 4th item). Using the CodeLite debugger, I can't quite tell what the new wxChoice value is. There are a lot of fields there and none of them looks like 0x0003.

Using event.GetItem(), my problem is that I can't figure out how to convert from wxDataViewItem to a simple short unsigned integer (UInt16).

I tried several different approaches to convert, but none worked. I left them in my code snippet below, along with a brief comment about why it is a problem.

How do I convert from wxDataViewItem to UInt16?

Code: Select all

// *****************************************************************************
//                        OnChannel_list_ItemValueChanged
// *****************************************************************************
void MainFrame::OnChannel_list_ItemValueChanged (wxDataViewEvent& event)
{
    UInt16      Curr_Col            = 0;
    UInt16      Curr_Row            = 0;
//    long        New_Value_as_long   = 0x8000;
    UInt16      New_Value_as_UInt16 = 0x7FFF;
    wxString    Debug_Msg           = "";

    Curr_Col    = event.GetColumn ();
    Curr_Row    = m_Channel_List->GetSelectedRow ();

    // Get the new value in the wxchoice list. Should be an integer
    // between 0 and 7, inclusive.
    wxDataViewItem  New_Value;
    New_Value   = event.GetItem();

//     New_Value_as_UInt16 = (UInt16) New_Value.GetID();   // fail--can't convert

//     New_Value   = wxDataViewEvent::GetItem(); // fail--wrong syntax
//     wxDataViewItem   New_Value;
//     New_Value   = event.GetItem (); // FAIL--this always returns 1, no matter what I pick

//      wxVariant   New_Value;
//      m_Channel_List->GetValue(New_Value, Curr_Row, Curr_Col); // FAIL--requires wxVariant arg, which I can't figure out how to convert to a 3-bit integer.
                                                                // also fail because it doesn't change New_Value.
    // Convert New_Value from variant to a long, even though all we really need
    // is a 3-bit nibble.

//     New_Value_as_long   = New_Value.GetInteger();       // FAIL--assert failure.
//     New_Value_as_UInt16 = (short) New_Value_as_long;

//     New_Value.Convert (&New_Value_as_long);       // FAIL--no Convert
//     New_Value_as_UInt16 = (short) New_Value;      // FAIL--invalid cast


    Debug_Msg = wxString::Format ("Debug: Coordinates are (row, col) = (%d, %d)\n       New_Value_as_UInt16 = %d.",
//         Curr_Row, Curr_Col, New_Value);      // FAIL--can't print a wxDataViewItem with %d as a format specifier.
        Curr_Row, Curr_Col, New_Value_as_UInt16);
    m_Comments->SetLabel (Debug_Msg);

    // Store the new value in Edited_Ch_Data.

    if (Curr_Col == COL_OF_SHUNT)
        Edited_Ch_Data  [Curr_Row].Shunt    = (t_Shunt_Type) New_Value_as_UInt16;

    else if (Curr_Col == COL_OF_PGA)
        Edited_Ch_Data  [Curr_Row].PGA      = (t_PGA_Type)   New_Value_as_UInt16;

    else if (Curr_Col == COL_OF_ADC_DF)
        Edited_Ch_Data  [Curr_Row].ADC_DF   = (t_ADC_DF_Type) New_Value_as_UInt16;

}
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by doublemax »

Use the source, Luke!
User avatar
ColleenKobe
Earned some good credits
Earned some good credits
Posts: 109
Joined: Mon Aug 31, 2015 3:47 pm

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by ColleenKobe »

I went to edit this post but ended up losing it. My mistake. -- Colleen
Last edited by ColleenKobe on Fri Sep 15, 2017 10:52 am, edited 2 times in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by doublemax »

I don't see any GetValue() call.

Code: Select all

wxDataViewItem  New_Value;
New_Value   = event.GetItem();
event.GetItem() returns the item - this is not the value.

Try something like this (untested):

Code: Select all

int col = event.GetColumn();
int row = m_Channel_List->ItemToRow( event.GetItem() );
wxVariant new_value;
m_Channel_List->GetValue( new_value, row, col );
wxLogMessage("new value = %d", new_value.GetLong() );
Use the source, Luke!
User avatar
ColleenKobe
Earned some good credits
Earned some good credits
Posts: 109
Joined: Mon Aug 31, 2015 3:47 pm

Re: Where can I get a wxDataViewListCtrl::GetValue "col" argument?

Post by ColleenKobe »

Beautiful! Thank you, doublemax!!! Your code worked. :D
Colleen
Post Reply