-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: Add TypedListView type #440
Conversation
With seemingly no interest from the gtk-rs side to merge this into their crates, I suggest to merge this here first and then move it to gtk-rs later if desired. |
0a53e14
to
d5efedc
Compare
I'm not fully familiar with all the ins and outs of Relm4, but would it somehow be possible to get a typed |
Regarding Relm4, it is basically an abstraction layer over gtk-rs that tries to make everything as idiomatic as possible. In fact, you can mix Relm4 and gtk-rs as much as you want, there's nothing really special happening under the hood.
I think that should be possible. I just didn't think so far to be honest. So if you have an idea, I would be interested. |
Basically what I'm doing is to use a SQlite database as a I made a trait that can be implemented like so (ignore the async for now, I basically do a #[async_trait]
pub trait DatabaseView: Send + Sync + 'static {
type RustModel: Send;
type GObjectModel: StaticType + ObjectType + IsA<Object> + From<Self::RustModel>;
async fn read_at_offset(database_pool: &SqlitePool, offset: u32) -> anyhow::Result<Self::RustModel>;
async fn count(database_pool: &SqlitePool) -> u32;
}
#[async_trait]
trait DynamicDatabaseView {
fn rust_model(&self) -> TypeId;
fn gobject_model(&self) -> glib::Type;
async fn read_at_offset(&self, database_pool: &SqlitePool, offset: u32) -> anyhow::Result<Box<dyn Any + Send>>;
async fn count(&self, database_pool: &SqlitePool) -> u32;
fn convert(&self, rust_model: Box<dyn Any>) -> Object;
}
#[async_trait]
impl<T: DatabaseView> DynamicDatabaseView for T {
fn rust_model(&self) -> TypeId {
TypeId::of::<T::RustModel>()
}
fn gobject_model(&self) -> glib::Type {
T::GObjectModel::static_type()
}
async fn read_at_offset(&self, database_pool: &SqlitePool, offset: u32) -> anyhow::Result<Box<dyn Any + Send>> {
let model = T::read_at_offset(database_pool, offset).await?;
Ok(Box::new(model))
}
async fn count(&self, database_pool: &SqlitePool) -> u32 {
T::count(database_pool).await
}
fn convert(&self, rust_model: Box<dyn Any>) -> Object {
let rust_model = *rust_model.downcast::<T::RustModel>().expect("Incorrect type");
let gobject_model = T::GObjectModel::from(rust_model);
gobject_model.upcast()
}
} A user has to implement Based on that, I have implemented a custom GObject subclass that implements the I know this is very much still in a prototype in the "just get it to work" stage, but that's the general direction I've been going so far. |
Sounds very interesting. I really like the idea that you can implement your own storage backend. We could offer a default in-memory-store based on something like Btw. something similar was attempted in relm4-store, but has been abandoned by its maintainer for quite some time now. Maybe you can find some clues there: https://github.com/mskorkowski/relm4-store |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have had a look through and there are no issues that stand out to me, although I should note that I don't completely understand the interactions with GTK.
I know that this is not the most generic and powerful abstraction yet, but I'd like to merge this for now and continue tuning this feature in the future. |
Adds a
TypedListView
type as a high level abstraction overgtk::ListView
.The goal is to simplify the workflow regarding the following points:
Ord
traitThis won't be a solution for everyone because it isn't 100% as flexible as the raw bindings.
Yet, for most use-cases this should provide a massive reduction of boilerplate code and makes the implementation less error-prone.
The types_list_view example shows a small app with a sortable and filterable list view.
For now, it is still to be decided whether this type is merged here or will be included into gtk-rs directly.
It's basically slightly more than a proof-of-concept by now, but not complete. The API can still change in the future.
Checklist
Example with async
Screencast.from.2023-04-02.20-32-17.webm