I have used "gintro" with a TreeView. There are some things that do not work 
the way I want (for instance the impossibility in Gtk3 to use alternate colors 
for rows if the theme doesn’t provide it), so I still use my previous version 
in gtk2. But here is how I proceed using _gintro_.

To allocate the _ListStore_ , I use this code:
    
    
    var types = [TYPE_STRING, TYPE_STRING]
    let store = newListStore(2, addr(types))
    
    
    Run

The types are missing in _gintro_ , so I have defined them in another file. 
Here is the beginning of this file with the types:
    
    
    import gintro/[gtk, gobject, glib]
    import gintro/gdk except Window
    
    const Lib* = "libgtk-3.so.0"
    {.pragma: libprag, cdecl, dynlib: Lib.}
    
    # GType values.
    const
      TYPE_NONE* = GType(1 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_CHAR* = GType(3 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_BOOLEAN* = GType(5 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_INT64* = GType(10 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_ENUM* = GType(12 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_STRING* = GType(16 shl TYPE_FUNDAMENTAL_SHIFT)
      TYPE_OBJECT* = GType(20 shl TYPE_FUNDAMENTAL_SHIFT)
    
    
    Run

I didn’t found the _typeFromName_ function, so there is a simpler way to do 
what you want without using my types declaration. But, anyway, you need to 
initialize an array and to pass its address to _newListStore_.

I have implemented a sort too but not when clicking on the header, so I cannot 
tell you how to catch the event. To sort, you can use a selection sort or use 
the reorder function of the Gtk3 API. I use the latter method. The selection 
sort method is simpler but uses an algorithm which is not very efficient (but 
it will be fine if you have not a lot of values to sort).

So, I build a list which contains tuples (value, position). In my case, the 
values are always strings, so that is easy. Then, you sort the list and use 
this sorted list to build a mapping from the new position to the old position. 
Finally, you have to call the method _reorder_ of the _ListStore_ with the 
address of the first element of the mapping as argument (not the address of the 
sequence, of course).

Here is an excerpt of the code I use:
    
    
    let store = app.store
    let count = store.iterNChildren()
    var sortlist = newSeqOfCap[tuple[val: string, pos: int32]](count)
    var iter: TreeIter
    
    # Build a list of tuples (value, position).
    discard store.getIterFirst(iter)
    var idx = 0'i32
    while true:
      var val: Value
      store.getValue(iter, 0, val)
      sortlist.add((val.getString().toUpper, idx))
      if not store.iterNext(iter):
        break   # No more row.
      idx += 1
      
      # Sort the list.
      sortlist.sort(system.cmp)
      
      # Build the mapping new position -> old position.
      var mapping = newSeq[int32](count)
      var changed = false
      for idx, item in sortlist:
        changed = changed or idx != item.pos
        mapping[idx] = item.pos
      if not changed: return      # Already sorted.
      
      # Apply the reorder mapping.
      app.store.reorder(addr(mapping[0]))
    
    
    Run

When you click in a cell, you have the possibility to execute a callback which 
gives you a path and a renderer. I think that it is possible to find the row 
and column numbers from the path. In my case, as I only needed the column 
number, I find it by searching the index of the renderer in a list of renderers 
I keep (I think that you need a list of renderers anyway). The path is a 
string, so there is still the possibility to parse it.

As I wrote this program several months ago, I don’t remember all the details, 
but, for sure, _TreeView_ in Gtk is not a simple thing. Initially, the program 
was written in PyQt. I converted it in Nim with Gtk2, then converted it to Gtk3 
using _gintro_. And, as I have said, I don’t use the Gtk3 version despite the 
_gintro_ code being cleaner. 

Reply via email to