woboq / qmetaobject-rs

Integrate Qml and Rust by building the QMetaObject at compile time.
MIT License
637 stars 89 forks source link

Add QML signal example #73

Closed retro486 closed 4 years ago

retro486 commented 4 years ago

Sorry if this is obvious but I can’t seem to figure out how to make use of the signals in QML that get generated with the qt_signal! macro. Which scope or component do you target? How do you call it? Etc

HiruNya commented 4 years ago

I'm new to using this crate as well but is this what you wanted? https://gist.github.com/HiruNya/33b71aea41394b4812b1b7fe4f05a5d7

For signals in qml, remember to put the on before the signal and ensure that the signal is camel case (not sure if this is necessary). So in this case, mySignal was used by setting the onMySignal property.

retro486 commented 4 years ago

That’s a good example, yes. Thanks! I supposed I thought the signal needed to be caught within the component I wanted to update not within the mode itself but QML can be modified from there by ID so that works. I was trying to debug my QAbstractListModel not rendering in a ListView so I wanted to use these to debug.

HiruNya commented 4 years ago

@retro486 Did you fix that problem?

I may have encountered the same problem, my SimpleListModel is not updating my GridView even though I call the notify signal. I sort of fixed it by adding a signal handler but I'm not sure why it works and if there is a better way.

retro486 commented 4 years ago

@HiruNya Possibly the same issue. In my case I added rowsAboutToBeInserted and rowsInserted but I had to move my collection modification to the QML, I couldn't figure out how to keep it all in Rust (which is preferable since I want as little application logic as possible in my QML). Here's the main.rs for reference (it's my first Rust so I'll take any feedback). Using your way were you able to keep all the logic in Rust?

HiruNya commented 4 years ago

I got it working! I was using SimpleListModel and had to use its methods to change my list (I was replacing the whole list instead of using the reset_data method). Looking at the source code it seems that begin_insert_rows, end_insert_rows, begin_remove_rows, etc. were being used.

Since you are using QAbstractListModel, you can use begin_insert_rows and end_insert_rows in your add_dummy function, without having to call it in QML. (There's an example in the repo that does this)

retro486 commented 4 years ago

Hm. I've updated my code to more closely match the source example but now I can't access my struct members from the QML in the delegate. My guess is I need to update my role_names function to list the members I want to make accessible to QML?

retro486 commented 4 years ago

I realized this discussion got off track from my original question so I'll bring it back full circle (I'm not sure what a better discussion forum for this is; the UT app developers Telegram?). This appears to be the condensed example I was looking for when using custom signals to work:

// main.rs
#[allow(non_snake_case)]
#[derive(QObject,Default)]
struct Tasks {
    // when my_count value is modified, the countChanged signal is tripped.
    my_count: qt_property!(usize; NOTIFY countChanged),
    countChanged: qt_signal!(),
}

fn main() {
    ...
    qml_register_type::<Tasks>(cstr!("Tasks"), 1, 0, cstr!("Tasks"));
    ...
}
// Main.qml
import Tasks 1.0

Tasks {
    id: tasks
    // reactions to custom signals defined in a model should be implemented in the model QML:
    onCountChanged: {
        // Do something when this signal is sent
    }
}