KConfig XT: Is it possible to access a parameter range from QML?

As in EasyEffects we used gsettings in the move to QT using KConfig XT was the natural thing to do. So far the transition has been smooth. But I wonder if there is an easy way to access from the QML side the parameter range that was defined in the xml used to create the configuration class.

I’ve noticed in the documentation that I can set ItemAccessors = true and that seems to provide a way to get the ranges from C++. But as far as I could see the generated class does not expose the new objects to QML. The place where they would be a lot more useful. EasyEffects has to deal with a huge amount of spinboxes and having to set the minimum and maximum values in each widget code as well as in the corresponding parameter xml is not only error prone but a little tedious. This is a problem for which I could never find a good solution in gsettings and that seems doable in KConfig XT as a c++ class is generated.

Does anyone know if it is already possible to access the range from QML?

Best regards,
Wellington

Hi if the info is not accessible directly via the generated class or if you need to attach additional info by either making the generated class inherit from some base class or what would fit your case inheriting from the generated class to expose additional things.

Hi @davidre! I think I saw in the documentation that the generated class could inherit from something but probably missed the part where we could inherit from it. Interesting. But I wonder if it is possible to solve my probably through inheritance entirely in an automated way. Let’s consider a xml that has something like

<entry name="inputGain" type="Double">
    <label></label>
    <min>-36</min>
    <max>36</max>
    <default>0</default>
</entry>

What I would like to do is to automatically generate a way to access the min and max values and pass them to the from and to properties of a spinbox just like it can be done to the value property. The setting ItemAccessors = true almost makes this possible. But even if I configure the ItemAccessors to be public instead of private I can only use them on C++ because the necessary code to expose them to QML is not added. And no property is generated for them. I wonder if a custom inheritance can somehow help with this.

My idea was like would be to do something like having
ClassName=SettingsBase and then expose a class

class Settings : public SettingsBase
{
Q_OBJECT
Q_PROPERTY(int inputGainMax  READ inputGainMax CONSTANT)

int inputGainMax() const 
{
   return inputGainItem()->max()
}
}

Maybe a bit tedious but could all hidden inside a macro perhaps if you have multiple instances to do that.

Actually another option could also be to define these magic numbers not in kcfg file but somewhere else and reference them in the kcfg. Like

<kcfg [...]>
  <include>mycoolconstants.h</include>
   [....]
  <entry name="inputGain" type="Double">
    <label></label>
    <min code="true">minimumInputGain</min>
    <max code="true">maximimUnputGain()</max>
    <default>0</default>
</entry>

these could be defines or functions or any valid code basically

Hum… I will think a little about it. Some of the audio plugins really have an huge amount of parameters completely different from each other. So a macro probably won’t be of much help. It feels like both approaches will require a huge amount of effort. The first needs a custom base class where each parameter would probably have to be defined by hand individually.

And the second would require the ranges of each parameter to be redefined in a new file. And the corresponding structure or similar object to be exposed to qml. It would not feel so bad if I were starting the project today. But with all the xml files we already have because of gsettings the amount of work feels doubled. Each xml file will have the range of each parameter manually edited and the corresponding header with the constants created. Hum…

What is sad is that the problem is almost solved as kconfig already is. Looking at the genereated class when ItemAccessors = true I see things like

KConfigCompilerSignallingItem *inputGainItem()
{
  return mInputGainItem;
}

. I would probably get what I want if I were able to insert a Q_INVOKABLE in from of these methods declarations.

Maybe it is possible to edit the generated files with cmake before it starts to compile the code that depends on the kconfig classes.

Although it is possible and Q_INVOKABLE makes the itemAccessors available on qml in the end it is not useful because the itemAccessors do not have any property or member function available on qml :laughing:. That is probably the reason why these objects were not exposed to qml. Well… I guess it is either doing the brute force approach or manually adding each range value both in the xml and the qml files like I’ve been doing =/

Sorry to hear that. But it points to something where we can improve kconfig compiler. Having it generate min/max properties or methods sounds like a very nice feature to add.

1 Like

It would be nice to have this. If it weren’t for the fact that there are still lots of things to be done to move EasyEffects from gtk to qt I would take a look at KConfig code to see how hard it is to make it add getters for the min and max values.

As gsettings has the same limitation I am used to it. It is not the end of the world. But half of the utility the min/max values set in the xml could have is lost if we can’t use them in the app widgets.

@davidre There is a way. I found it just when I was about to give up :smile:. The only concern is that it relies a little bit on knowledge about how the kconfig class is generated. After looking at the class code I’ve noticed lots of lines like

addItem( mInputGainItem, QStringLiteral( "inputGain" ) );

So I thought what if I create a base class that wraps findItem in a qml invokable member function? It works! For reference the base class member is defined as

QVariant KConfigBaseEE::getMinValue(const QString& itemName) {
  if (itemName.isEmpty()) {
    return {};
  }

  if (auto item = findItem(itemName); item != nullptr) {
    return item->minValue();
  }

  return {};
}

As far as I could see the name of the property we set in the xml file is used as item name. That is the part where the solution relies on information about the implementation. But it does not seem likely that there will be a reason to change this. So I am tempted to go ahead with this solution.

Yeah that seems good! I agree that the name is unlikely to change, I would say even it has to match otherwise the findItem API is kinda useless

It makes sense. I will go ahead with this solution. Thanks for the suggestions! :slight_smile: