Compiler Error: the trait `gtk::IsA<gtk::TreeModel>` is not implemented for `std::result::Result<gtk::ListStore, rusqlite::error::Error>`

Hello All,
Super Rust Noob is back at his weekend coding projects. Currently, I am trying to combine two previous projects (GTK list view and SQLITE db) into one app. Basically I have a very simple GTK list store / treeview GUI that is loaded from a SQLITE db to display various US state data.

This is a combining of two previous issues I was helped with by folks here:


I have worked through about 10 errors tonight and gotten it down to just one that has me stumped for the past two hours - which is not hard to do :frowning:

When I compile, I get this error:

I am guessing it is my lack of skills in working with traits & results. The error is at line 42 and has comments above & below it show where it is. I am almost certain that (&*model) being passed from create_model() is the culprit but do not know how to approach it.

My Code:

extern crate gio;
extern crate gtk;

use gtk::prelude::*;
use std::rc::Rc;
use std::env::args;
use gio::prelude::*;
use rusqlite::{Connection, Result, NO_PARAMS};

#[repr(i32)]
enum Columns {
    State,
    Population,
    Area,
    Date,
    Capital,
    Bird,
}

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_title("List Store");
    window.set_border_width(10);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(300, 500);

    let vbox = gtk::Box::new(gtk::Orientation::Vertical, 8);
    window.add(&vbox);

    let label = gtk::Label::new(Some("US State Facts"));
    vbox.add(&label);

    let sw = gtk::ScrolledWindow::new(None::<&gtk::Adjustment>, None::<&gtk::Adjustment>);
    sw.set_shadow_type(gtk::ShadowType::EtchedIn);
    sw.set_policy(gtk::PolicyType::Never, gtk::PolicyType::Automatic);
    vbox.add(&sw);

    let model = Rc::new(create_model());

    // OFFENDING CODE 
    let treeview = gtk::TreeView::new_with_model(&*model);
    // OFFENDING CODE

    treeview.set_vexpand(true);

    sw.add(&treeview);

    add_columns(&treeview);

    window.show_all();
}

struct Data {
    state: String,
    population: u32,
    area: u32,
    date: String,
    capital: String,
    bird: String,
}

#[derive(Debug)]
struct State {
    name: String,
    capital: String,
    population: u32,
    area: u32,
    date: String,
    bird: String,
}

fn create_model() -> Result<(gtk::ListStore)> {

    let col_types: [gtk::Type; 6] = [
        gtk::Type::String,
        gtk::Type::U32,
        gtk::Type::U32,
        gtk::Type::String,
        gtk::Type::String,
        gtk::Type::String,
    ];

    let conn = Connection::open("US_States.db")?;

    let mut stmt = conn
        .prepare(&"SELECT name, capital, population, area, date, bird FROM Table_Main ORDER BY   name ASC".to_string())?;
    let state_iter = stmt
        .query_map(NO_PARAMS, |row| Ok(State {
            name: row.get(0)?,
            capital: row.get(1)?,
            population: row.get(2)?,
            area: row.get(3)?,
            date: row.get(4)?,
            bird: row.get(5)?,
        }))?;

    let mut data = vec![];

    for state in state_iter.flatten() {
        data.push(Data{state: state.name,
                                  population: state.population,
                                  area: state.area,
                                  date: state.date,
                                  capital: state.capital,
                                  bird: state.bird});    
    }

    let store = gtk::ListStore::new(&col_types);

    let col_indices: [u32; 6] = [0, 1, 2, 3, 4, 5];

    for (_, d) in data.iter().enumerate() {
        let values: [&dyn ToValue; 6] = [
            &d.state,
            &d.population,
            &d.area,
            &d.date,
            &d.capital,
            &d.bird,
        ];
        store.set(&store.append(), &col_indices, &values);
    }

    Ok(store)
}

fn add_columns(treeview: &gtk::TreeView) {

    // Column for state name
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("State");
        column.add_attribute(&renderer, "text", Columns::State as i32);
        column.set_sort_column_id(Columns::State as i32);
        column.set_fixed_width(150);
        column.set_alignment(0.0);
        treeview.append_column(&column);
    }

    // Column for population
    {
        let renderer = gtk::CellRendererText::new();
        renderer.set_alignment(1.0, 1.0);
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Population");
        column.add_attribute(&renderer, "text", Columns::Population as i32);
        column.set_sort_column_id(Columns::Population as i32);
        column.set_fixed_width(100);
        column.set_alignment(1.0);
        treeview.append_column(&column);
    }

    // Column for area
    {
        let renderer = gtk::CellRendererText::new();
        renderer.set_alignment(1.0, 1.0);
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Area");
        column.add_attribute(&renderer, "text", Columns::Area as i32);
        column.set_sort_column_id(Columns::Area as i32);
        column.set_fixed_width(100);
        column.set_alignment(1.0);
        treeview.append_column(&column);
    }

    // Column for date
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Date");
        column.add_attribute(&renderer, "text", Columns::Date as i32);
        column.set_sort_column_id(Columns::Date as i32);
        column.set_fixed_width(150);
        column.set_alignment(0.5);
        treeview.append_column(&column);
    }

    // Column for capital city
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Capital");
        column.add_attribute(&renderer, "text", Columns::Capital as i32);
        column.set_sort_column_id(Columns::Capital as i32);
        column.set_fixed_width(150);
        column.set_alignment(0.0);
        treeview.append_column(&column);
    }

    // Column for bird
    {
        let renderer = gtk::CellRendererText::new();
        let column = gtk::TreeViewColumn::new();
        column.pack_start(&renderer, true);
        column.set_title("Bird");
        column.add_attribute(&renderer, "text", Columns::Bird as i32);
        column.set_sort_column_id(Columns::Bird as i32);
        column.set_fixed_width(200);
        column.set_alignment(0.0);
        treeview.append_column(&column);
    }
}

fn main() {
    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.list-store"),
        Default::default(),
    )
    .expect("Initialization failed...");

    application.connect_startup(|app| {
        build_ui(app);
    });

    application.connect_activate(|_| {});

    application.run(&args().collect::<Vec<_>>());
}

create_model returns a Result, meaning it could fail to make a model. You'll need to handle the failure case in build_ui - if you're OK crashing on failure, you could do

let model = Rc::new(create_model().unwrap());
1 Like

Thank you asymmetrikon! Your answer worked perfectly!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.