Todo example in Rust
vandenoever.info
vandenoever.info
Searching through the repo [0,1] it seems like you still need to write a certain amount of C++ especially if you're using QtWidgets instead of QML. So in my eyes this seems like a way to incorporate Rust code into a Qt project rather than build a Qt interface for use in Rust, as the end program is essentially a C++ program with some Rust bits.
From what I understand if you have a fair amount of existing Rust code to reuse in a Qt GUI application this is probably the best way to get them to talk together but it's a still a bit far from "Qt GUI for your Rust programs". I get that the distinction between the two is a bit blurry but in any case you still need to write a considerable amount of C++ especially if you opt for the QtWidgets way.
Of course it is entirely possible that I've completely missed the point so in that case please correct me.
[0] https://github.com/KDE/rust-qt-binding-generator/tree/master...
[1] https://github.com/KDE/rust-qt-binding-generator/tree/master...
This approach was chosen because it's hard to wrap Qt Widgets (let alone QML) safely in a Rust API. Generating binding code is a very pragmatic approach that works now. You do not need external libraries, just generate some code, include it in your project and use qmake/cmake/... and cargo together.
I've explained this approach in a presentation at FOSDEM [0].
That being said, there might well come a better solution that manages to wrap Qt and the mechanisms of deriving from Qt model classes in a Rust API. It may even manage to require only Cargo as a build tool. In fact, only yesterday Olivier Goffart presented a prototype that does just that. [1] And that project has the exact same to-do application in its examples with only Rust and QML (no JSON or C++).
Switching between those approaches should be very simple though. Especially since Rust has static typing which makes refactoring a breeze.
[0] https://fosdem.org/2018/schedule/event/rust_qt_binding_gener... [1] https://woboq.com/blog/qmetaobject-from-rust.html
Qt is enormous. There are projects that generate bindings automatically. But to know what is safe, you'd have to read the API docs and write the binding by hand. Some parts of Qt might never be safe. For example, loading QML with QQmlApplicationEngine::loadData is not safe because it runs possibly unsafe QML code. So a binding to QQmlApplicationEngine::loadData should be marked unsafe and its documentations should state: 'only load safe QML'.
Most current FFI examples in Rust go via C bindings. There's not a lot of work on wrapping C++ libraries yet (that I'm aware of). C++ is vastly more complex than C. So ensuring safety is harder.
In most Qt projects, there will be places in the code where you have to derive from a Qt class. So the binding should have a way to do that.
The Qt ownership models is hierarchical. If an object has a parent, it will be freed when the parent is freed. A Rust binding should translate that behavior in a safe API.
Signals and slots in Qt are tricky to wrap in a safe API too.
In short, wrapping Qt in a Rust API is a humongous task. Rust Qt Binding Generator takes a pragmatic approach and lets you combine Qt and Rust in one project. It does so by generating a binding around your data model instead of around the entire Qt API.
[0] https://doc.rust-lang.org/reference/behavior-considered-unde...
Author of the blog post here. I've started out the code in the post with a pure QML version of course and then replaced the model with a Rust model since the point of the blog is to show how to write the model in Rust.
I like your solution of using a DelegateModel to show All, Completed or Active items. I went for a different approach:
RowLayout {
property bool show: filter.currentIndex === 0
|| (filter.currentIndex === 1 && !completed)
|| (filter.currentIndex === 2 && completed)
visible: showAre you aware of Olivier Goffart's take on QML in Rust ? https://woboq.com/blog/qmetaobject-from-rust.html ; it seems that it could maybe be used instead of the custome code-gen you did.
That's a great time for Qt and Rust, no doubt :p
Olivier's approach is very clever. Especially the method of extending Qt classes.
Here's the reference for the drain() method on vectors which takes the range argument: https://doc.rust-lang.org/rust-by-example/flow_control/for.h...
Altogether, it sounds like (I haven't read the whole thing) it's supposed to drain from the current row until the end, including every row in between.
let strings = ["foo", "bar", "baz"];
let slice = &strings[0..2];
// prints "foo" and "bar"
for s in slice {
println!("{}", s);
}
Or looping over numbers: // prints 0, 1, 2, 3, and 4
for i in 0..5 {
println!("{}", i);
}