Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

How to display TreeView backed by a Vec of Rust objects #304

Closed
kornelski opened this issue Apr 18, 2020 · 9 comments
Closed

How to display TreeView backed by a Vec of Rust objects #304

kornelski opened this issue Apr 18, 2020 · 9 comments

Comments

@kornelski
Copy link

kornelski commented Apr 18, 2020

Examples show how to bind a ListStore or TreeStore to a TreeView, but it seems like this relies on the store being the source of truth for this data, and the data to be stored as separate Values in separate columns.

What I'm missing is how to use Rust-native type as the data source for a TreeView, especially if the TreeView is sortable.

My data lives in a Vec<RustStruct>, and I'd like to display some of the fields of that struct in TreeView's columns.

I can't find a way reliably connect the Vec to the ListStore or use it as the data source for the TreeView. My naive approach of mapping vec[n] to n-th row of the ListStore worked only for non-sortable view, but as soon as the view is sorted, Vec indices don't correspond to ListStore rows any more, so I can't update them (without searching the whole list store for a matching row).

I've tried wrapping my RustStruct to be a GObject subclass:

    let store = ListStore::new(&[RustStructGObjectWrapper::static_type()]);
    tree.set_model(Some(&store)); 

    // creates 3 columns here

but it seems like ListStore wants 1:1 mapping between number of columns in the ListStore:

'assertion failed: columns.len() <= n_columns as usize'

I hoped that TreeViewColumnExt::set_cell_data_func would let me have one object per row, and copy its properties into separate columns of the TreeView, but apparently that's not the way to do it.


So it would be helpful for me to see an example of how to go from struct Model {column1:RefCell<String>, column2:RefCell<String>}; Vec<Model> to a sortable TreeView that displays model's fields, and can update them in the UI when they change.

@GuillaumeGomez
Copy link
Member

GuillaumeGomez commented Apr 18, 2020

@kornelski
Copy link
Author

kornelski commented Apr 18, 2020

But this is the thing I'm struggling with: you're storing the data in the ListStore. I have my data in a Vec.

You're filling the store once, fully, with insert_with_values, and don't seem to update later.

But if vec[7] changed in my program, how do I know where vec[7]'s data is in the TreeView? which cell do I update?

@kornelski
Copy link
Author

kornelski commented Apr 18, 2020

So that's a linear search. It's going to be O(n^2) for me, because in my program I emit an event "7th row of the Vec changed, 3rd row of the Vec changed, 11th row of the Vec changed". If I use a treeiter to scan through entire store every time to find where my Vec's data ended up in, it'll be super slow.

I have my expectations set by Cocoa, where I can say "treeview.column1.text binds to mymodel.field1" and vec[7].field1.set() sends a message to treeview.column1 to update itself.

but here I have column.add_attribute(&cell, "text", 0); where 0 is the column number, not name of the field in the model.

@GuillaumeGomez
Copy link
Member

GuillaumeGomez commented Apr 18, 2020

You can try the other way around: using a vec of references to the liststore. Then no need to have the data twice.

@kornelski
Copy link
Author

kornelski commented Apr 18, 2020

Does the TreeIter survive sorting? i.e. if it was iter of 0th row, and user reverses sorting, is it going start pointing to the last row?

@GuillaumeGomez
Copy link
Member

Good question... I'm pretty sure you can have access to the data location directly, never looked how however. If you find out, please tell me. :3

@kornelski
Copy link
Author

gtk_list_store_set_valuesv: assertion 'iter_is_valid (iter, list_store)' failed

Nope, I can't store iters.

@kornelski
Copy link
Author

I think I've got a solution:

  1. Use an unsorted ListStore for 1:1 relationship with Vec, and copy data back and forth using index<>row mapping
  2. Prevent ListStore from being mixed up by wrapping it TreeModelSort https://stackoverflow.com/a/19063670/27009

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants