I try to port a small ruby+qt application to nim For nim language there is only one gui toolkit working for me and that is gintro. http://ssalewski.de/gintroreadme.html
The democode listview compiles and runs nice on my netbsd. https://github.com/StefanSalewski/gintro/blob/master/examples/listview.nim
But I need a listview(gtktreeview) with two columns I looked into nim.gtk but can't figure out which "casts" i should spell.
This works nice for N_COLUMNS=1 but not N_COLUMNS:2
Second when i have multiple colums I would like to make it sortable by clicking on the header (just like an excel table)
I try to port a small ruby+qt application to nim.For nim language there is only one gui toolkit working for me and that is gintro.
There should be many more working GUI toolkits now, like xnim, qlm, wxwidgets, win and the genUI ones from Mr Munch. I think Nim has a few paid devs currently, so just file GUI related github issues...
Of course I am happy that gintro works for you basically, but I guess you know that GTK is not very popular in general, and my feeling is that we have not many gintro users currently.
I can try to investigate your listview/treeview issues in the next days, maybe weekend. Treeview is not that easy, I was struggling with it myself years ago when using Ruby-GTK. For Nim it is generally easier, first task is generally finding a working plain C example, or at least an working example at all. Most of the time fixes for Nim are not difficult.
Feel free to open github issues -- the fact that there are still some open ones does not mean that I am ignoring them. It is just that some are very special, I am searching for really good fixes, and generally the reporters vanish from GTK and Nim short time after reporting, so there is not that much motivation from that side. And one very important point is, that each fix to gintro may break other stuff -- which may stay undiscovered for ever due to the fact that I have only a very limited number of small tests currently and that number of users may be indeed zero. So I have to be carefully.
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))
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)
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]))
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.
import gintro/[glib, gobject, gtk]
import gintro/gio except ListStore
const GroceryList = [(true, 1, "Paper Towels"), (true, 2, "Bread"),
(false, 1, "Butter"), (true, 1, "Milk"), (false, 3, "Chips"),
(true, 4, "Soda")]
## Add three columns to the GtkTreeView. All three of the columns will be
## displayed as text, although one is a gboolean value and another is an integer.
proc setupTreeView(treeview: TreeView) =
var renderer: CellRendererText
var column: TreeViewColumn
## Create a new GtkCellRendererText, add it to the tree view column and
## append the column to the tree view.
for i, t in ["Buy", "Count", "Product"]:
renderer = newCellRendererText()
column = newTreeViewColumn()
column.title = t
column.packStart(renderer, true)
column.addAttribute(renderer, "text", i)
discard treeview.appendColumn(column)
proc appActivate(app: Application) =
let window = newApplicationWindow(app)
window.title = "Grocery List"
window.borderWidth = 10
window.position = WindowPosition.center
window.setSizeRequest(250, 175)
let treeview = newTreeView()
setupTreeView(treeview)
## Create a new tree model with three columns, as string, gint and guint.
## store = gtk_list_store_new(, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING)
var h = [typeFromName("gboolean"), typeFromName("gint"), typeFromName("gchararray")]
let store = newListStore(3, cast[pointer]( unsafeaddr h)) # cast due to bug in gtk.nim
## Add all of the products to the GtkListStore.
for el in GroceryList:
var val: Value
var iter: TreeIter
var gtype: GType
let buy = el[0]
let quantity = el[1]
let product = el[2]
store.append(iter)
gtype = typeFromName("gboolean")
discard gValueInit(val, gtype)
setBoolean(val, buy)
store.setValue(iter, 0, val)
gtype = typeFromName("gint")
val.unset
discard gValueInit(val, gtype)
setint(val, quantity)
store.setValue(iter, 1, val)
gtype = typeFromName("gchararray")
val.unset
discard gValueInit(val, gtype)
setString(val, product)
store.setValue(iter, 2, val)
let scrolled_win = newScrolledWindow()
scrolled_win.setPolicy(PolicyType.automatic, PolicyType.automatic)
scrolled_win.add(treeview)
window.add(scrolled_win)
treeview.setModel(store)
showAll(window)
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", appActivate)
discard run(app)
main()
I took an old C example from the old GTK2 book of Andrew Krause, applied c2nim, mixed it with the other listview example, and fixed the rest. The ugly cast is still present, I have not touched gintro package yet, sorry.
Of course this example does only display the three columns, there is no code for modifying it yet. But adding that should be not that hard, as seen from the first example.
I noticed that you asked AT THE SAME Time at stackoverflow. Some consider that a bad habit, maybe you can at least link that one to this forum thread.