As as aside, you may want to look into using a QTreeModel for your XML, then you can use the model/view/delegate stuff in C++ and QML.
Sent: Tuesday, August 23, 2016 at 7:24 PM
From: "Xavier Bigand" <flamaros.xav...@gmail.com>
To: "Jérôme Godbout" <jer...@bodycad.com>
Cc: "Jason H" <jh...@gmx.com>, "Interests Qt" <interest@qt-project.org>
Subject: Re: [Interest] Force property's binding to be executed from C++
From: "Xavier Bigand" <flamaros.xav...@gmail.com>
To: "Jérôme Godbout" <jer...@bodycad.com>
Cc: "Jason H" <jh...@gmx.com>, "Interests Qt" <interest@qt-project.org>
Subject: Re: [Interest] Force property's binding to be executed from C++
Thank you Jerome, I just found QQmlProperty::connectNotifySignal method. QQmlProperty seems much simpler to use instead of meta info (it is why it was added according to the documentation)
I made a simple try and it's called just after the qml binding was updated, so it seems to do just what I want.
And I will be able to connect all my properties on the same slot or on a dedicated one if it is too slow (I doubt about that because our changes are lazy).
For the rest it is already the case, our skin properties are in a singleton component (to optimize memory usage), and we do hot reloading of our qml files with a file watcher during the development ;-)
Thank you too Jason, before we were using a separated xml file (one per skin/product for our 3D elements), and it is much more easier for us to use bindings instead of separating values by skins.
Have a good day both.
2016-08-24 0:19 GMT+02:00 Jérôme Godbout <jer...@bodycad.com>:
For the second part, you should expose those value into properties where the skin object refer too (most likely a map of properties where it can fetch those skin values). and emit Changed on that map when you data changed.I think you allow dynamic skinning that can be set from the outside and those value are filled at run time (like a debugger or user can give live property setting to an object). If this is the case, you need to connect yourself to any changed on that input.I strongly recommend making a Component that set the colors based on the current skin and perform a Singleton with a Loader that load the Component and bind yourself to that loaded part (make sure you have a default Component to provide when none are available by the loader). This way you could make a simple Component file that can inherite from each other but can override any skin value and you can create as many as you want, make a folder file observer and can even detected them and add them to the GUI theme selection (this is what I do for my apps and it work like a charm).On Tue, Aug 23, 2016 at 6:11 PM, Jérôme Godbout <jer...@bodycad.com> wrote:Hi,You can retreive the properties changed from meta information of those properties on you object.I'm not sure I understand your use case but here's some info that may help.auto meta_obj = target_object_->metaObject();for(int i = 0; i < meta_obj.propertyCount(); ++i){auto meta_property = meta_obj.property();auto method_signal = meta_property.notifySignal();connect(target_object_, method_signal, myHandler, handle_slot_name);}You may want to keep a list of object connections if they don't get deleted when swaping to disconnected them.So you can now handle those property changed from C++ without writting Qml binding directly. This also work with signal and slots.Most likely, you want to bind on any changed properties of the skin and revaluate the whole skin manager update sequence I guess.JeromeOn Tue, Aug 23, 2016 at 5:36 PM, Xavier Bigand <flamaros.xav...@gmail.com> wrote:That the problem, I can easily call my SkinManager::updateSkin when the skin changed, because it's a cpp attribut too (the selected skin). But I have to call it when the QmlEngine have reevaluated the properties values not before.
Getting property values directly from cpp code doesn't execute bindings (as much as I know), so I am trying to call this slot (SkinManager::updateSkin) from Qml where it should be easier to fix this calling order issue.If I create a property that depends of all others it be reevaluated after the others, then I will be able to invoke my cpp slot from his onChanged signal.
The difficulty is to create this property.
My QML component looks like to this :
HomeDesignSkins.qml :
Item {id: homeDesignSkins
readonly property color accentucationColor: { // In cpp SkinManager::updateSkin() method can be invoked before the execution of this binding,if (application.product === Product.ProductOutdoor) // the better way to solve this issue is to create a binding dependencyreturn "#45a785"else if (application.product === Product.ProductMyDreamHome){if (settings.skin === "MyDreamHomeThemeCanson")return Qt.rgba(235 / 255, 130 / 255, 122 / 255, 255 / 255)else if (settings.skin === "MyDreamHomeThemeMilli")return Qt.rgba(242 / 255, 118 / 255, 82 / 255, 255 / 255)elsereturn Qt.rgba(145 / 255, 135 / 255, 148 / 255, 255 / 255)}elsereturn "#8da7c0"}...// Here we have numerous properties used to describe our GUI skin (some are shared with the cpp code for our 3D rendering)Object {property string homeDesignSkinsProperties: {
var propertyValues
for (var propertyName in homeDesignSkins)propertyValues += propertyName + " " // How retrieving the property values by their namesreturn propertyValues}
onHomeDesignSkinsPropertiesChanged: { // This signal should be called once after that all properties of homeDesignSkins where reevaluted when the skin changedskinManager.updateSkin() // skinManager is the instance of the cpp SkinManager singleton, updateSkin is an Q_INVOKABLE method
}
}}
--2016-08-23 21:29 GMT+02:00 Jason H <jh...@gmx.com>:If I understand you correctly, and I probably don't, the skin componentSkin {signal skinPropertyChanged();property color accentucationColor: "red"onAccentucationColorChanged: skinPropertyChanged()}SkinManager {// exposed C++ classid:skinManagerproperty var currentSkin: null;onCurrrentSkinChanged: updateSkin(); // handle when the skin switches}Connections {target: currentSkinonSkinPropertyChanged: id:skinManager.updateSkin() // handle when propterties of the skin change.}Will that work?Sent: Tuesday, August 23, 2016 at 1:12 PM
From: "Xavier Bigand" <flamaros.xav...@gmail.com>
To: interest@qt-project.org
Subject: [Interest] Force property's binding to be executed from C++_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interestHi,To skin our GUI we have a dedicated qml component instanced once that contains all necessary values under properties.I am able to access to those properties from C++ code but they aren't correctly synchronized with the selected skin.Here is my cpp code :void SkinManagerWrapper::updateSkin() const
{QObject* skinItem = mRootObject->findChild<QObject*>("hdGUI", Qt::FindDirectChildrenOnly);
core::SkinManager* skinManager = core::SkinManager::singleton();// GeneralskinManager->accentuationColor = convert(skinItem->property("accentuationColor").value<QColor>()); // skinManager->accentuationColor is actually a cpp property ;-)
}The property method return the previous value before the execution of the binding, because in the qml binding the value is depending of the selected skin.As workaround I am trying to create a qml property that depend of all properties of our skin component ("HomeDesignSkins"), but If it is possible to retrieve dynamically properties names of the component, I can't figure out retrieving values of properties by string names.The Idea is to be able to use the onChanged signal of this property to invoke my cpp updateSkin method, this should resolve dependency order issue.Maybe their is an other way to do it, else I am searching to way to retrieve property values in qml from their names.--XavierXavier
_______________________________________________
Interest mailing list
Interest@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest
Xavier
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest