[Interest] Force property's binding to be executed from C++

Jérôme Godbout jerome at bodycad.com
Wed Aug 24 00:19:09 CEST 2016


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 <jerome at 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.
>
> Jerome
>
>
> On Tue, Aug 23, 2016 at 5:36 PM, Xavier Bigand <flamaros.xavier at 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 dependency
>>
>>             return "#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)
>>
>>             else
>>
>>                 return Qt.rgba(145 / 255, 135 / 255, 148 / 255, 255 / 255)
>>
>>         }
>>
>>         else
>>
>>             return "#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 names
>>
>>                    return propertyValues
>>
>>              }
>>
>>
>>             onHomeDesignSkinsPropertiesChanged: {                                     // This signal should be called once after that all properties of homeDesignSkins where reevaluted when the skin changed
>>
>>                    skinManager.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 <jhihn at gmx.com>:
>>
>>> If I understand you correctly, and I probably don't, the skin component
>>>
>>> Skin {
>>> signal skinPropertyChanged();
>>> property color accentucationColor: "red"
>>> onAccentucationColorChanged: skinPropertyChanged()
>>> }
>>>
>>> SkinManager {// exposed C++ class
>>>     id:skinManager
>>>     property var currentSkin: null;
>>>     onCurrrentSkinChanged: updateSkin(); // handle when the skin switches
>>> }
>>>    Connections {
>>>       target: currentSkin
>>>       onSkinPropertyChanged: 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.xavier at gmail.com>
>>> *To:* interest at qt-project.org
>>> *Subject:* [Interest] Force property's binding to be executed from C++
>>> Hi,
>>>
>>> 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();
>>>
>>>
>>>
>>>         // General
>>>
>>>         skinManager->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.
>>>
>>>
>>> --
>>> Xavier
>>> _______________________________________________ Interest mailing list
>>> Interest at qt-project.org http://lists.qt-project.org/ma
>>> ilman/listinfo/interest
>>>
>>
>>
>>
>> --
>> Xavier
>>
>> _______________________________________________
>> Interest mailing list
>> Interest at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/interest
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20160823/e1fdcdd9/attachment.html>


More information about the Interest mailing list