3

I am creating GUI application using Rust and bindings for GTK+ 3 (called Gtk-rs or rust-gnome). I want to insert some data into gtk::ListStore (GtkListStore) using method insert_with_values

Working sample, but only one column: I can insert data if I have one column:

let type_of_a_column = &[gtk::Type::U32];
let data_for_column_1 = (2 as u32).to_value();
let model_list_of_data = ListStore::new(type_of_a_column);
model_list_of_data.insert_with_values(None, &[0 as u32], &[&data_for_column_1]);

However I don't know how to hand over more data if I have more columns. I know that internally it should call gtk_list_store_insert_with_valuesv() so I need probably an array or slice, but if I do something like:

Wanted to pass two elements in array, not working

let type_of_a_column = &[gtk::Type::U32, gtk::Type::I64];
let data_for_column_1 = (2 as u32).to_value();
let data_for_column_2 = (4 as i64).to_value();
let array_of_data = [&data_for_column_1, &data_for_column_2];
let model_list_of_data = ListStore::new(type_of_a_column);
model_list_of_data.insert_with_values(None, &[1 as u32], &[&array_of_data]);

it gives me during compilation:

error: the trait bound [&glib::Value; 2]: glib::IsA<glib::Object> is not satisfied [E0277]

and I don't know how to overcome it.

Not working MCVE

main.rs

extern crate gtk;

use gtk::prelude::*;
use gtk::{Box, ListStore, Orientation, TreeView, Window, WindowType};

fn exit_app() -> gtk::prelude::Inhibit {
    // Stop the main loop.
    gtk::main_quit();
    // Let the default handler destroy the window.
    Inhibit(false)
}

fn main() {
    if gtk::init().is_err() {
        panic!("Failed to initialize GTK.");
    }

    println!("Version of GTK+3:\t{}.{}",
             gtk::get_major_version(),
             gtk::get_minor_version());
    let window = Window::new(WindowType::Toplevel);
    window.set_title("Exercises with GtkTreeView and GtkListStore");
    window.set_position(gtk::WindowPosition::Center);
    window.connect_delete_event(|_, _| exit_app());

    let box_container = Box::new(Orientation::Vertical, 0);
    let view_list = TreeView::new();

    let types_inside_columns = &[gtk::Type::U32, gtk::Type::I64];
    let data_in_column_1 = (2 as u32).to_value();
    let data_in_column_2 = (4 as i64).to_value();

    let array_of_data = [&data_in_column_1, &data_in_column_2];

    let model_list_of_data = ListStore::new(types_inside_columns);

    model_list_of_data.insert_with_values(Some(0), &[0 as u32, 1 as u32], &[&array_of_data]);

    view_list.set_model(Some(&model_list_of_data));
    box_container.pack_start(&view_list, false, false, 0);
    window.add(&box_container);

    window.show_all();
    gtk::main();
}

Cargo.toml

[package]
name = "test_of_gtk_3"
version = "0.0.1"
authors = ["wm_obsd"]

[dependencies.gtk]
version = "0.1.0"
features = ["v3_16"]

[[bin]]
name = "main"
path = "src/main.rs"
wm_obsd
  • 43
  • 6
  • You also don't need to specify a `[[bin]]` section if your main file is `src/main.rs`, that's the conventional spot. – Shepmaster Jul 13 '16 at 19:51
  • @Shepmaster Changed to "&array_of_data", compiler complains: `expected &[&gtk::ToValue], found &[&gtk::Value; 2] (expected slice, found array of 2 elements)[E0308] ` --- Changed to "&array_of_data[..]", compiler complains: `expected `&[&gtk::ToValue], found &[&gtk::Value] (expected trait gtk::ToValue, found struct `gtk::Value`) [E0308]` --- Changed to "&[&array_of_data[..]]", compiler complains: `error: the trait bound `[&gtk::Value]: std::marker::Sized` is not satisfied [E0277] note: `[&gtk::Value]` does not have a constant size known at compile-time` – wm_obsd Jul 13 '16 at 19:55
  • It successfully compiled :D – wm_obsd Jul 13 '16 at 20:03
  • Note that `gtk::init().expect("Failed to initialize GTK");` is shorter **and** better — it prints the underlying error message. – Shepmaster Jul 14 '16 at 01:31

1 Answers1

3

Ultimately, you are most likely to want to write something like this:

model_list_of_data.insert_with_values(Some(0), &[0, 1], &[&2u32, &4i64]);

Let's break down the function definition a bit:

fn insert_with_values(&self,
                      position: Option<u32>,
                      columns: &[u32],
                      values: &[&ToValue])
                      -> TreeIter;

This function takes an immutable reference to a ListStore, an optional position, zero-or-more columns as integers, and zero-or-more references to the trait ToValue.

What types implement ToValue? The documentation says:

impl<T> ToValue for Option<T> where T: SetValueOptional
impl<T> ToValue for T where T: SetValue + ?Sized
impl ToValue for Value

Taking a look at SetValue, we can see that it's implemented for the primitive integer types.

Since u32 and i64 implement SetValue, they also implement ToValue. A reference to the number can be implicitly coerced into a reference to the trait as well.

With this change, the window appears, but...

blank window

You'll have to figure out the mysteries of GTK from here!

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366