QmlEngine does not implement QObject
Closed this issue · 4 comments
In the Qt Framework, QmlEngine inherits from QObject. Thus, it can be passed as QObject in some cases like in KLocalizedContext creation. However, the QmlEngine does not implement the QObject trait in qmetaobject-rs and thus cannot be used under similar conditions.
Also, the current implementation actually uses a QmlEngineHolder class which stores the QmlEngine as a unique_pointer. So it might not even be a good idea to pass this QmlEngine the same way as a normal QObject. I kind of understand why the holder class is needed since I had to do the same thing for the KI18n bindings that I am trying to create.
I do not yet have any solution, but I think we need to make some modifications in QmlEngine implementation since there might be many places where Qt Frameworks treats QmlEngine as QObject.
Not sure what's the issue is here. If you reach to native code, which you need to do to call the C++ KLocalizedContext API, you can get a pointer to the engine with QmlEngine::cpp_ptr. and that is a QQmlEngine*
which inherit from QObject*
I mean, the qmetaobject::qtdeclarative::QmlEngine
rust type is just an API allowing to use a QML Engine. The fact that it inherit from QObject in C++ is an implementation detail, and it is not needed in rust.
I don't see a good reason for QmlEngine to implement the QObject
trait, because you don't want to expose the engine to itself.
Maybe you can describe what you are actually trying to do?
If you are simply trying to setup a KLocalizedContext, then you probably just want to do it in native code with the cpp! macro:
something like this, i guess:
fn install_localized_context(engine: &QmlEngine) {
let engine = engine.cpp_ptr();
cpp!(unsafe [engine as "QQmlEngine*"] {
engine->rootContext()->setContextObject(new KLocalizedContext(engine));
});
}
Or something like that.
Ok, so I am trying to create a general wrapper around the KLocalizedContext rather than using it with C++ directly in my project. Here is how I was trying to do it:
use cpp::{cpp, cpp_class};
use qmetaobject::prelude::*;
use qmetaobject::QObjectPinned;
cpp! {{
#include <KLocalizedContext>
#include <QObject>
struct KLocalizedContextHolder {
std::unique_ptr<KLocalizedContext> klocalized;
KLocalizedContextHolder(QObject *parent) : klocalized(new KLocalizedContext(parent)) {}
};
}}
cpp_class!(pub unsafe struct KLocalizedContext as "KLocalizedContextHolder");
impl KLocalizedContext {
pub fn new<T: QObject + Sized>(obj: QObjectPinned<T>) -> Self {
let obj_ptr = obj.get_or_create_cpp_object();
cpp!(unsafe [obj_ptr as "QObject *"] -> KLocalizedContext as "KLocalizedContextHolder" {
return KLocalizedContextHolder(obj_ptr);
})
}
}
KLocalizedContext has a signature of KLocalizedContext (QObject *parent=nullptr)
which means it can technically be created and used in just a particular portion of the application rather than registering with the Engine.
As you mentioned, I can create a separate method for working with QmlEngine which is what I am currently thinking about. However, I opened this issue since for QT, there isn't really any difference between QmlEngine and QObject in this context and for generalized wrappers of more parts of QT, there might be a need for a different solution since I am guessing that most other QT frameworks that are normally created with the Engine treat it as a QObject.