Rows are added to a list store with GTree.list_store#append (gtk_list_store_append). This will insert a new empty row at the end of the list. There are other functions, documented in the GTree.list_store ( GtkListStore API reference), that give you more control about where exactly the new row is inserted, but as they work very similar to GTree.list_store#append and are fairly straight-forward to use, we will not deal with them here.
Here is a simple example of how to create a list store and add some (empty) rows to it:
let cols = new GTree.column_list in let col_name = cols#add Gobject.Data.string in let liststore = GTree.list_store cols in (* Append an empty row to the list store. Iter will point to the new row *) let iter = liststore#append () in (* Append an empty row to the list store. Iter will point to the new row *) let iter = liststore#append () in (* Append an empty row to the list store. Iter will point to the new row *) let iter = liststore#append () in
This in itself is not very useful yet of course. We will add data to the rows in the next section.
Adding rows to a tree store works similar to adding rows to a list store, only that GTree.tree_store#append (gtk_tree_store_append) is the function to use and one more argument is required, namely the tree iter to the parent of the row to insert. If you do NOT supply instead of providing the tree iter of another row, a new top-level row will be inserted. If you do provide a parent tree iter, the new empty row will be inserted after any already existing children of the parent. Again, there are other ways to insert a row into the tree store and they are documented in the GTree.tree_store (GtkTreeStore API reference manual). Another short example:
let cols = new GTree.column_list in let col_name = cols#add Gobject.Data.string in let treestore = GTree.tree_store cols in (* Append an empty top-level row to the tree store. * Iter will point to the new row *) let iter = treestore#append () in (* Append another empty top-level row to the tree store. * Iter will point to the new row *) let iter = treestore#append () in (* Append a child to the row we just added. * Child will point to the new row *) let child = treestore#append ~parent:iter () in (* Get the first row, and add a child to it as well (could have been done * right away earlier of course, this is just for demonstration purposes) *) match treestore#get_iter_first with | Some iter -> (* Child will point to new row *) let child = treestore#append ~parent:iter () in ... | None -> prerr_endline "Oops, we should have a first row in the tree store!"
A common scenario is that a model needs to be filled with a lot of rows at some point, either at start-up, or when some file is opened. An equally common scenario is that this takes an awfully long time even on powerful machines once the model contains more than a couple of thousand rows, with an exponentially decreasing rate of insertion. As already pointed out above, writing a custom model might be the best thing to do in this case. Nevertheless, there are some things you can do to work around this problem and speed things up a bit even with the stock Gtk+ models:
Firstly, you should detach your list store or tree store from the tree view before doing your mass insertions, then do your insertions, and only connect your store to the tree view again when you are done with your insertions. Like this:
... let model = view#model in view#set_model None; (* Detach model from view *) ... (* insert a couple of thousand rows *) ... view#set_model (Some model); (* Re-attach model to view *) ...
Secondly, you should make sure that sorting is disabled while you are doing your mass insertions, otherwise your store might be resorted after each and every single row insertion, which is going to be everything but fast.
Thirdly, you should not keep around a lot of tree row references if you have so many rows, because with each insertion (or removal) every single tree row reference will check whether its path needs to be updated or not.