Skip to content
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

Add a few more QmlEngine methods #302

Merged
merged 2 commits into from
Oct 12, 2023
Merged

Conversation

IriaSomobu
Copy link
Contributor

@IriaSomobu IriaSomobu commented Oct 11, 2023

I was implementing a basic hot-reload feature for a project of mine and had a difficulties I solved by adding a few additional methods to QmlEngine wrapper.

First, I should briefly explain how hot reloading works in my case:

  1. Rust code watches for changes in ./ui/ directroy where all my .qml's are stored;
  2. When file change occurs, rust code does the following (source):
    • Invokes method hot_reload_pre on my root ApplicationWindow -- this method clears PageLoader's source and sets it to inactive;
    • Trims and clears QmlEngine's component cache;
    • Invokes method hot_reload_post -- this method makes PageLoader become active and triggers loading of page where user was before hot reload.

In this scenario I faced two problems:

The first one was caused by cryptic QMetaMethod::invoke: Unable to invoke methods with return values in queued connections QmlEngine message happens when I try to call invoke_method on engine from my watcher thread. I've looked here and there and found this answer on SO. So I copied invoke_method, removed Q_RETURN_ARG from a template and renamed method to a invoke_method_noreturn (meaning this version of invoke_method has no return arg).

The second problem was -- QmlEngine and PageLoader was written by clever guys who cares about performance and do caching if possible. And in my case I need exactly opposite -- I need to reset Engine's/PageLoader's cache on hot reload. I found no possibilities to do it from qml itself (moving my PageLoader to inactive and then back to active state wont help), but I found a way to do it from C side by calling methods engine->trimComponentCache() and engine->clearComponentCache(). Unfortunately, named methods were absent in wrapper, so I've added them.

And with these two changes I was able to do my simple hot-reload.

I believe someone else may find these addition useful, so here's PR.

Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch.

The two extra method makes sense. But the _noreturn one should be changed not to return anything.

qmetaobject/src/qtdeclarative.rs Outdated Show resolved Hide resolved
Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

Tests would be nice if you can add them.

Another thing i'm wondering is whether we should actually call it invoke_method_queued and pass the Qt::QueuedConnection argument.
Is that not more what was your intention?

@ogoffart ogoffart merged commit 9d43036 into woboq:master Oct 12, 2023
19 checks passed
@IriaSomobu IriaSomobu deleted the qmlengine-fcns branch October 12, 2023 19:01
@IriaSomobu
Copy link
Contributor Author

It is more than I intended indeed -- I just wanted invoke to work one way or another, and with this PR it works.

I guess it is possible for me tinker with invoke_method and connections a bit later, when there will be more free time.

As for tests -- do you have any ideas on what exactly should we test on these functions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants