Force generic implementation of `wx.dataview.DataViewCtrl`

In one of my projects I use wx.dataview.DataViewCtrl. I want to use different colours for alternating rows, but the documentation states for the .SetAlternateRowColour() method:

True if customizing this colour is supported (currently only in the generic version).

Also sorting by multiple columns is only supported by the generic versions. My system uses wxGTK, so I miss these features.

Is there a way to force wxPython to use the generic version of DataViewCtrl?

If not, is there a trick known to get alternating colours for rows? And sorting by multiple columns?

I found a comment in an issue raised in the wxWidgets GitHub repository which said that in order to use the generic wxDataViewListCtrl on GTK, you would have to build wxWidgets using the configure option --disable-nativedvc. If you succeeded in doing that, you would then need to produce a custom build of wxPython in order to interface with it.

Below is a very simplified example that changes the background colour of alternate rows, which does work in the native version (I am using wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.4 + Python 3.12.3 + Linux Mint 22). I don’t know how to implement sorting by multiple columns.

import wx
import wx.dataview as dv

def getData(num_rows, num_cols):
    data = []
    for r in range(num_rows):
        values = []
        for c in range(num_cols):
            value = f"Item {r + 1},{c + 1}"
            values.append(value)
        data.append(values)
    return data

class ColourModel(dv.DataViewIndexListModel):
    def __init__(self, data):
        dv.DataViewIndexListModel.__init__(self, len(data))
        self.data = data

    # This method is called to provide the data object for a
    # particular row,col
    def GetValueByRow(self, row, col):
        return self.data[row][col]

    # This method is called when the user edits a data item in the view.
    def SetValueByRow(self, value, row, col):
        self.data[row][col] = value
        return True

    # Report how many columns this model provides data for.
    def GetColumnCount(self):
        return len(self.data[0])

    # Report the number of rows in the model
    def GetCount(self):
        return len(self.data)

    # Called to check if non-standard attributes
    # should be used in the cell at (row, col)
    # Note: These settings are not used for cells with None values
    def GetAttrByRow(self, row, col, attr):
        if row % 2 == 0:
            attr.SetBackgroundColour('#D0F0A0')
        else:
            attr.SetBackgroundColour('#A0D0E0')
        return True

class TestFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title="Coloured Rows")
        self.SetSize((340, 260))
        style = dv.DV_HORIZ_RULES | dv.DV_VERT_RULES
        self.dvc = dv.DataViewCtrl(self, style=style)
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(self.dvc, 1, wx.EXPAND, 0)
        self.SetSizer(main_sizer)
        self.Layout()

        self.num_rows = 8
        self.num_cols = 4
        data = getData(self.num_rows, self.num_cols)
        self.displayData(data)

    def displayData(self, data):
        self.model = ColourModel(data)
        self.dvc.AssociateModel(self.model)
        for c in range(self.num_cols):
            label = f"Col-{c+1}"
            renderer = dv.DataViewTextRenderer()
            col = dv.DataViewColumn(label, renderer, c)
            self.dvc.AppendColumn(col)

app = wx.App()
frame = TestFrame(None)
frame.Show()
app.MainLoop()

Screenshot at 2024-08-30 13-57-51

I might stay clear of compiling that stuff myself. :sweat: Only, because it would then only work on my computer. :sweat_smile: But thanks!

Regarding using GetAttrByRow(): I noticed that method, but thought, it would only work for pure texts (as it states in the documentation: ‘This only affects the DataViewTextRendererText() (sic) renderer’). I now tried it with different renderers and some others also work, such as the DataViewDateRenderer and the inert DataViewSpinRenderer (I haven’t tried any other). Some others do not change the background: The DataViewToggleRenderer, the DataViewChoiceRenderer and the DataViewProgressRenderer (I haven’t tried any other).

Thanks for rousing my curiosity to try it out.

BTW, nice colour choice!