Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Understanding QML attributes



  • I am stuck on a problem, I will try to explain it. We have a GUI which was put together by another entity. They gave us a great shell but some alterations need to be made. Currently, I am working on the alphanumeric number pad and here is how it is being instantiated in a script called WizardSectionDisplay.qml:

    onShowKeyboard: {
                    var comp = Qt.createComponent("qrc:/Source//UiControls/WizardPopupKeyboard.qml");
                    comp.createObject(application, {
                                          "title": mod_data.label
                                          ,"objectName":"systemDialog"
                                          , "hint": qsTr("Enter a value between %1 and %2").arg(Math.round(mod_data.minValue)).arg(Math.round(mod_data.maxValue))
                                          , "modelButtons": [qsTr("Cancel"), qsTr("Finished")]
                                          , "primaryIndex": 1
                                          , "controlTarget": minMaxSplitBtn
                                          , "settingValue": mod_data
                                      })
                }
    

    so in other words I am adding some functionality to the WizzardPopupKeyboard.qml file. One of the problems I am addressing has to do with the units being displayed. Here, where the object is being created, they are accessing units like so:

    mod_data.unit
    

    I am trying to do something similar inside of WizzardPopupKeyboard.qml:

    if(mod_Data.unit === "s")
               {
                   entryDisplay.text = settingValue.value
               }
    

    this does work, I am getting the functionality I need but for some reason an error is being reported:

    ReferenceError: mod_Data is not defined
    

    this seems odd to me because its working despite mod_Data not being defined. Here is how mod_Data is being defined inside of the WizardSectionDisplay.qml:

    Loader{
                        id:contentContainer
                        height: parent.height
                        anchors.left: delegateLabel.right
                        anchors.right: parent.right
                        //this is required due to a qml *bug* that will eat the modelData property from the listmodel parent.
                        property variant mod_data: modelData
                        sourceComponent: numberEntry
                    }
    

    As you can see it's based off of modelData but modelData is not defined inside of WizardSectionDisplay.qml, in fact, I can't seem to figure out where its being defined. So my question is how can I go about using mod_data in the WizardPopupKeyboard.qml without getting the error?


  • Moderators

    modelData is a property of all models in QML. See the docs. So I guess that your loader is used as a delegate in some view.

    That might explain why mod_data is not always defined - maybe your onShowKeyboard is called before the model is ready, or before the delegate is created etc. Views can create / destroy delegates at any point in time, too, so it might be unreliable depending on them like that. Hard to say for sure as I don't know how your system works in detail - but maybe these hints will help.



  • So that's why modelData is used all over the place. So modelData is only ever used in WizardSectionDisplay.qml after the keyboard is created but mod_data is used throughout the script. One thing I can't seem to understand. During the creation of the keyboard object mod_data is passed as settingValue:

    , "settingValue": mod_data
    

    however; I can't seem to use it's unit attribute, for instance if I try:

    if(presentationManager.guiSettingsPresenter.model.useUSUnits)
                                    {
                                        if(settingValue.unit === "s")
                                        {
                                            true
                                        }
    
                                        false
                                    }
    

    in WizardPopupKeyboard.qml the above code throws no errors but doesn't work. However, if I import the UiControls then, as I showed in the code from my previous post, I can simply call mod_data.unit directly and the it works but throws the error. I would think that they should both work and that they should both throw an error. I even tried passing the units directly:

    ,  "unit": mod_data.unit
    

    and then calling:

    if(presentationManager.guiSettingsPresenter.model.useUSUnits)
                                    {
                                        if(unit === "s")
                                        {
                                            true
                                        }
    
                                        false
                                    }
    

    however, that did not work either. I dont understand how I can use settingValue.value, or settingValue.label in WizardPopupKeyboard.qml without any errors but I can't use settingValue.unit... seems odd. In my previous code you can see the comment they left behind during the creation of the mod_data property:

    //this is required due to a qml *bug* that will eat the modelData property from the listmodel parent.
    

    perhaps my problem is related?

    EDIT: A bit more confused now. Turns out I can access the settingValue.unit but I can't use it in an if statement like I want? To test and see if I have access to .unit I decided to change the text of the . button to:

    settingValue.unit
    

    and voila it worked:

    PushButton
                            {
                                width: 75
                                height: width
                                text: settingValue.unit //"."
                                enabled:
                                {
                                    if(presentationManager.guiSettingsPresenter.model.useUSUnits)
                                    {
                                        if(settingValue.unit === "s")
                                        {
                                            true
                                        }
    
                                        false
                                    }
                                }
                                onClicked:
                                {
                                    outValue+=".";
                                }
                            }
    

    the keyboard is now showing an s where the period use to be but for some reason the s is still being grayed out... as thought the condition can't be met...



  • Alright, perhaps someone can explain to me why the previous code did not work but this code does:

    PushButton
                           {
                               width: 75
                               height: width
                               text: "."
                               enabled:
                               {
                                   if(presentationManager.guiSettingsPresenter.model.useUSUnits)
                                   {
                                       if(settingValue.unit === "s")
                                       {
                                           true
                                       }
                                       else
                                       {
                                           false
                                       }
                                   }
                                   else
                                   {
                                       true
                                   }
    
                               }
                               onClicked:
                               {
                                   outValue+=".";
                               }
                           }
    

    the logic seems to be the same to me but adding these brackets and a few else clauses has fixed the issue. I was under the impression that as long as my logic was only one line then I didn't need the brackets.



  • @Circuits said in Understanding QML attributes:

    if(mod_Data.unit === "s")

    ReferenceError: mod_Data is not defined
    

    Is this a copy and paste of actual code and is the error code a copy and paste?

    Because the code you pasted before has:

    "settingValue": mod_data
    

    While the if statement has:

    if(mod_Data.unit === "s")
    

    You are mixing variable cases "mod_data" != "mod_Data"



  • @fcarney Yes that was an error on my part. The error message when using mod_data was supposed to be slightly different but I can't remember now what it was.


Log in to reply