142 lines
4.5 KiB
Rust
142 lines
4.5 KiB
Rust
use cxx::{type_id, ExternType};
|
|
use std::mem::MaybeUninit;
|
|
|
|
// Define a QModelIndex that is trivial for CXX
|
|
//
|
|
// TODO: later this will likely be in cxx-qt-lib
|
|
#[repr(C)]
|
|
pub struct QModelIndex {
|
|
_space: MaybeUninit<[usize; 3]>,
|
|
}
|
|
|
|
// Safety:
|
|
//
|
|
// Static checks on the C++ side to ensure the size is the same.
|
|
// TODO: later this will likely be in cxx-qt-lib
|
|
unsafe impl ExternType for QModelIndex {
|
|
type Id = type_id!("QModelIndex");
|
|
type Kind = cxx::kind::Trivial;
|
|
}
|
|
|
|
// ANCHOR: book_macro_code
|
|
#[cxx_qt::bridge(cxx_file_stem = "service_item_model")]
|
|
mod service_item_model {
|
|
// ANCHOR: book_base_include
|
|
unsafe extern "C++" {
|
|
include!("serviceitemmodel.h");
|
|
// ANCHOR_END: book_base_include
|
|
|
|
include!("cxx-qt-lib/qvariant.h");
|
|
type QVariant = cxx_qt_lib::QVariant;
|
|
|
|
// Define the interface of the QModelIndex
|
|
type QModelIndex = super::QModelIndex;
|
|
fn row(self: &QModelIndex) -> i32;
|
|
|
|
#[cxx_name = "beginInsertRows"]
|
|
fn begin_insert_rows(self: Pin<&mut CustomBaseClassQt>, first: i32, last: i32);
|
|
#[cxx_name = "endInsertRows"]
|
|
fn end_insert_rows(self: Pin<&mut CustomBaseClassQt>);
|
|
|
|
#[cxx_name = "beginRemoveRows"]
|
|
fn begin_remove_rows(self: Pin<&mut CustomBaseClassQt>, first: i32, last: i32);
|
|
#[cxx_name = "endRemoveRows"]
|
|
fn end_remove_rows(self: Pin<&mut CustomBaseClassQt>);
|
|
|
|
#[cxx_name = "beginResetModel"]
|
|
fn begin_reset_model(self: Pin<&mut CustomBaseClassQt>);
|
|
#[cxx_name = "endResetModel"]
|
|
fn end_reset_model(self: Pin<&mut CustomBaseClassQt>);
|
|
}
|
|
|
|
// ANCHOR: book_qobject_base
|
|
#[cxx_qt::qobject(base = "ServiceItemModel")]
|
|
#[derive(Default)]
|
|
pub struct ServiceItemModel {
|
|
// ANCHOR_END: book_qobject_base
|
|
id: u32,
|
|
vector: Vec<(u32, f64)>,
|
|
}
|
|
|
|
impl qobject::ServiceItemModel {
|
|
#[qinvokable]
|
|
pub fn add(self: Pin<&mut Self>) {
|
|
self.add_cpp_context();
|
|
}
|
|
|
|
#[qinvokable]
|
|
pub fn add_on_thread(self: Pin<&mut Self>, mut counter: i32) {
|
|
let qt_thread = self.qt_thread();
|
|
|
|
std::thread::spawn(move || {
|
|
while counter > 0 {
|
|
counter -= 1;
|
|
std::thread::sleep(std::time::Duration::from_millis(250));
|
|
|
|
// Use our add helper to add a row on the Qt event loop
|
|
// as seen in the threading demo channels could be used to pass info
|
|
qt_thread
|
|
.queue(|custom_base_class| {
|
|
custom_base_class.add_cpp_context();
|
|
})
|
|
.unwrap();
|
|
}
|
|
});
|
|
}
|
|
|
|
fn add_cpp_context(mut self: Pin<&mut Self>) {
|
|
let count = self.vector().len();
|
|
self.as_mut().begin_insert_rows(count as i32, count as i32);
|
|
let id = *self.id();
|
|
self.as_mut().set_id(id + 1);
|
|
self.as_mut().vector_mut().push((id, (id as f64) / 3.0));
|
|
self.as_mut().end_insert_rows();
|
|
}
|
|
|
|
#[qinvokable]
|
|
pub fn clear(mut self: Pin<&mut Self>) {
|
|
self.as_mut().begin_reset_model();
|
|
self.as_mut().set_id(0);
|
|
self.as_mut().vector_mut().clear();
|
|
self.as_mut().end_reset_model();
|
|
}
|
|
|
|
#[qinvokable]
|
|
pub fn remove(mut self: Pin<&mut Self>, index: i32) {
|
|
if index < 0 || (index as usize) >= self.vector().len() {
|
|
return;
|
|
}
|
|
|
|
self.as_mut().begin_remove_rows(index, index);
|
|
self.as_mut().vector_mut().remove(index as usize);
|
|
self.as_mut().end_remove_rows();
|
|
}
|
|
}
|
|
|
|
// QAbstractListModel implementation
|
|
impl qobject::ServiceItemModel {
|
|
#[qinvokable(cxx_override)]
|
|
fn data(&self, index: &QModelIndex, role: i32) -> QVariant {
|
|
if let Some((id, value)) = self.rust().vector.get(index.row() as usize) {
|
|
return match role {
|
|
0 => QVariant::from(*id),
|
|
1 => QVariant::from(*value),
|
|
_ => QVariant::default(),
|
|
};
|
|
}
|
|
|
|
QVariant::default()
|
|
}
|
|
|
|
#[qinvokable(cxx_override)]
|
|
pub fn role_names_as_vec(&self) -> Vec<String> {
|
|
vec!["id".to_owned(), "value".to_owned()]
|
|
}
|
|
|
|
#[qinvokable(cxx_override)]
|
|
pub fn row_count(&self, _parent: &QModelIndex) -> i32 {
|
|
self.rust().vector.len() as i32
|
|
}
|
|
}
|
|
}
|
|
// ANCHOR_END: book_macro_code
|