use crate::TreeIter;
use crate::TreeModel;
use crate::TreeStore;
use glib::object::{Cast, IsA};
use glib::translate::*;
use glib::{ToValue, Type, Value};
use libc::c_int;
impl TreeStore {
#[doc(alias = "gtk_tree_store_newv")]
pub fn new(column_types: &[Type]) -> TreeStore {
assert_initialized_main_thread!();
unsafe {
let mut column_types = column_types
.iter()
.map(|t| t.into_glib())
.collect::<Vec<_>>();
from_glib_full(ffi::gtk_tree_store_newv(
column_types.len() as c_int,
column_types.as_mut_ptr(),
))
}
}
}
mod sealed {
pub trait Sealed {}
impl<T: glib::IsA<crate::TreeStore>> Sealed for T {}
}
pub trait TreeStoreExtManual: IsA<TreeStore> + sealed::Sealed + 'static {
#[doc(alias = "gtk_tree_store_insert_with_valuesv")]
fn insert_with_values(
&self,
parent: Option<&TreeIter>,
position: Option<u32>,
columns_and_values: &[(u32, &dyn ToValue)],
) -> TreeIter {
unsafe {
assert!(
position.unwrap_or(0) <= i32::max_value() as u32,
"can't have more than {} rows",
i32::max_value()
);
let n_columns = ffi::gtk_tree_model_get_n_columns(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
) as u32;
assert!(
columns_and_values.len() <= n_columns as usize,
"got values for {} columns but only {n_columns} columns exist",
columns_and_values.len(),
);
for (column, value) in columns_and_values {
assert!(
*column < n_columns,
"got column {} which is higher than the number of columns {n_columns}",
*column,
);
let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
*column as c_int,
));
assert!(
Value::type_transformable(value.value_type(), type_),
"column {} is of type {type_} but found value of type {}",
*column,
value.value_type()
);
}
let columns = columns_and_values
.iter()
.map(|(c, _)| *c)
.collect::<Vec<_>>();
let values = columns_and_values
.iter()
.map(|(_, v)| v.to_value())
.collect::<Vec<_>>();
let mut iter = TreeIter::uninitialized();
ffi::gtk_tree_store_insert_with_valuesv(
self.as_ref().to_glib_none().0,
iter.to_glib_none_mut().0,
mut_override(parent.to_glib_none().0),
position.map_or(-1, |n| n as c_int),
mut_override(columns.as_ptr() as *const c_int),
mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
columns.len() as c_int,
);
iter
}
}
#[doc(alias = "gtk_tree_store_reorder")]
fn reorder(&self, parent: &TreeIter, new_order: &[u32]) {
unsafe {
let count = ffi::gtk_tree_model_iter_n_children(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
mut_override(parent.to_glib_none().0),
);
let safe_count = count as usize == new_order.len();
debug_assert!(
safe_count,
"Incorrect `new_order` slice length. Expected `{count}`, found `{}`.",
new_order.len()
);
let safe_values = new_order.iter().max().map_or(true, |&max| {
let max = max as i32;
max >= 0 && max < count
});
debug_assert!(
safe_values,
"Some `new_order` slice values are out of range. Maximum safe value: \
`{}`. The slice contents: `{new_order:?}`",
count - 1,
);
if safe_count && safe_values {
ffi::gtk_tree_store_reorder(
self.as_ref().to_glib_none().0,
mut_override(parent.to_glib_none().0),
mut_override(new_order.as_ptr() as *const c_int),
);
}
}
}
#[doc(alias = "gtk_tree_store_set")]
#[doc(alias = "gtk_tree_store_set_valuesv")]
fn set(&self, iter: &TreeIter, columns_and_values: &[(u32, &dyn ToValue)]) {
unsafe {
let n_columns = ffi::gtk_tree_model_get_n_columns(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
) as u32;
assert!(
columns_and_values.len() <= n_columns as usize,
"got values for {} columns but only {} columns exist",
columns_and_values.len(),
n_columns
);
for (column, value) in columns_and_values {
assert!(
*column < n_columns,
"got column {} which is higher than the number of columns {n_columns}",
*column,
);
let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
*column as c_int,
));
assert!(
Value::type_transformable(value.value_type(), type_),
"column {} is of type {type_} but found value of type {}",
*column,
value.value_type()
);
}
let columns = columns_and_values
.iter()
.map(|(c, _)| *c)
.collect::<Vec<_>>();
let values = columns_and_values
.iter()
.map(|(_, v)| v.to_value())
.collect::<Vec<_>>();
ffi::gtk_tree_store_set_valuesv(
self.as_ref().to_glib_none().0,
mut_override(iter.to_glib_none().0),
mut_override(columns.as_ptr() as *const c_int),
mut_override(values.as_ptr() as *const glib::gobject_ffi::GValue),
columns.len() as c_int,
);
}
}
#[doc(alias = "gtk_tree_store_set_value")]
fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
unsafe {
let columns = ffi::gtk_tree_model_get_n_columns(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
) as u32;
assert!(
column < columns,
"got column {column} which is higher than the number of columns {columns}",
);
let type_ = from_glib(ffi::gtk_tree_model_get_column_type(
self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
column as c_int,
));
assert!(
Value::type_transformable(value.type_(), type_),
"column {column} is of type {type_} but found value of type {}",
value.type_()
);
ffi::gtk_tree_store_set_value(
self.as_ref().to_glib_none().0,
mut_override(iter.to_glib_none().0),
column as c_int,
mut_override(value.to_glib_none().0),
);
}
}
}
impl<O: IsA<TreeStore>> TreeStoreExtManual for O {}