QT QML + C++ MVVM - qt

As far as I know in QT QML is not possible to instantiate a C++ class in QML Component, unless it is a QQuickItem.
I would not like to put all ViewModels on ViewEngine context because it is a very bad pratice create all classes in memory without using.
My question is: How can I instantiate a C++ ViewModel ou Services/API from a single QML component without usnig ViewEngine Context.
Do ViewModels have to be QQuickItem type?

C++ objects do not need to be QQuickItems, they need to be QObjects. You just need to register your class with the QQmlEngine, like this:
qmlRegisterType<MyObject>("my.component.library", 1, 0, "MyObject");
Then in your qml files, you can instantiate that class like this:
import my.component.library 1.0
MyObject {
...
}

Related

Qt: Using "setContextProperty" with "QObject" and "JavaScriptOwnership" causes item to be collected/deleted

I am integrating QML and .NET. (project link)
When I send .NET objects to QML, I wrap it with a NetValue : public QObject C++ type.
The NetValue type stores a strong reference to the underlying .NET object to prevent .NET GC while active in QML.
I use QQmlEngine::setObjectOwnership(netValue, QQmlEngine::JavaScriptOwnership); so that QML will delete NetValue when it is done with it. I then use NetValue::~NetValue() to tell .NET to release the strong reference.
This has worked well for me so far, but I am running into an issue. Consider the following.
QObject* testObject = new TestObject();
QQmlEngine::setObjectOwnership(testObject, QQmlEngine::JavaScriptOwnership);
engine.rootContext()->setContextProperty("testObject", testObject);
At a certain point, my TestObject will be destroyed.
I would expect setContextProperty to hold a strong reference to the QObject type, preventing it from being GC'd in QML.
Using QQmlEngine::CppOwnership fixes the issue, but as I've explained previously, I need to use QQmlEngine::JavaScriptOwnership to track the lifetime of the wrapping QML type that holds a reference to the .NET object.
Why doesn't setContextProperty store a strong reference (increase ref count, or something) to my QObject that I pass it?

Appropriate technique to create new object by user on front end in Qt

I'm creating an app that uses qml in the front end to create a new object onclicked. Is the appropriate way to go about this is to create a QOBJECT helper class that will solely serve to instantiate new objects of my other class?
Edit: I am wanting to create a C++ object from the front end with qml. I am not creating a qml object. So, if I click my button, C++ instantiates a new object. That is why I ask if I need to create a specialized QOBJECT class that has a public signal method solely to create new objects of my other class.
Or should I only have one class that can instantiate new objects of itself using a pointer?
The most efficient solution is to employ a singleton. It will avoid to overhead of the factory object lookup, and it will not associate the created object with any particular state, which is known to play tricks with object lifetime.
Additionally, if you create the QML object from C++, you can avoid a fair amount of memory usage bloat. You can also have a C++ object as a singleton:
qmlRegisterSingletonType<YourSingleton>("Module", 1, 0, "Singleton", singletonFactoryCallback);

Collect class hierarchy of Flex application

I was wondering: If I have built a Flex application, is it possible to somehow collect it's class hierarchy using reflection or some other method? For example if I have defined components: CustomButton which derives from Button and RedCustomButton which derives from CustomButton. Is it possible to get a result like: "Button <- CustomButton <- RedCustomButton"?
Thanks in advance for any help!
You can use describeType
trace(describeType(UIComponent));
public function describeType(value:*):XML Reference from Adobe Help
Produces an XML object that describes the ActionScript object named as
the parameter of the method. This method implements the programming
concept of reflection for the ActionScript language.
Also I recommend you to use Spicelib Reflect library.

Creating custom qml objects instances with Qt.createQmlObject()

I've got a custom QML object called Target.qml. I would like to create dynamic instances of this object using Qt.createQmlObject().
It works when using builtin qml objects like Image:
var newTarget = Qt.createQmlObject('import Qt 4.7; Image {source: "widgets/SlideSwitchImages/knob.png"; }', parent);
But fails when using any custom object types like:
var newTarget = Qt.createQmlObject('import Qt 4.7; Target {}', parent);
If however I use my custom Target type statically in QML everything works. Is this a known limitation, any workarounds?
If you just need an arbitrary number of Target instances it would be better to use Component.
Component {
id: targetFactory
Target {}
}
var newTarget = targetFactory.createObject(parent, properties)
However if you want to stick to the Qt.createQmlObject call I guess you have the Target component in a different directory and you're just missing out some import statement. The string parameter must be the content of a QML file that works on its own in the same directory as the one calling it.
E.g.
var newTarget = Qt.createQmlObject('import QtQuick 1.0; import "../Targets"; Target {}', parent);
BTW: The Qt 4.7 imports are deprecated because they don't allow additional versions of QtQuick.
From the docs:
There are two ways to create objects dynamically from JavaScript. You can either call Qt.createComponent() to dynamically create a Component object, or use Qt.createQmlObject() to create an item from a string of QML. Creating a component is better if you have an existing component defined in a .qml file, and you want to dynamically create instances of that component. Otherwise, creating an item from a string of QML is useful when the item QML itself is generated at runtime.
I understand this to mean that createQmlObject will only work if you've defined the item type at runtime and that the application is therefore aware of the existence of it.
createComponent seems to perform the same function but for item types pre-defined in .qml files, as in your case.

Qt: bring base class method into slots in derived class

I have a class which derives from a QWidget and a model class. Based on my reading, I can't have the model class to derive from QObject.
class PageWidget : public QWidget,
public MyModelClass
{
...
};
the model class MyModelClass already have method to set properties such as setWidth(bool). It seems that I can't use those method directly as slots. If I declare:
QObject::connect(button, SIGNAl(dataChanged(bool)), this, SLOT(setWidth(bool)));
Qt complains at runtime that no slot setWidth(bool). I have to manually add each method into PageWidget, which simply calls the same method of MyModelClass.
Is there any way to bring base methods into slots without redeclaring every method?
QMetaObject (the Qt part that allow you to use slots) and multiple inheritance do not mix. You solution of creating "pass through" slots is a way of solving it. However, if you do not need to do the multiple inheritance, I wouldn't do it. Just from the look of things, it seems weird for a PageWidget to derive from both a Widget and a Model. It probably makes more sense to have it contain the model instead.

Resources