I am using Qt6.5.1
and I have created ComboBox
in QML. Following is what I have done.
I have following C++ class.
class MyComboBoxOptions : public QObject {
Q_OBJECT
Q_PROPERTY(QStringList options READ options)
public:
QStringList options() const {
return mComboOptionStrings;
}
private:
const QStringList mComboOptionStrings {
"Option 1",
"Option 2",
"Option 3",
};
};
In main.cpp
I have done the following to register the above class MyComboBoxOptions in QML.
MyComboBoxOptions myComboBoxOptions;
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myComboBoxOptions", &myComboBoxOptions);
Then I have the ComboBox
like below in QML.
ComboBox {
id: comboBox
height: 20
width: 50
model: myComboBoxOptions.options
currentIndex: 0 // default
}
Question:
How can replace the QStringList
returned by MyComboBoxOptions::options
with a Q_ENUM
? Simply returning a Q_ENUM
there does not work.
[REWRITE]
I have a general-purpose EnumInfo
class that can build a model for an enum from any object, including Qt's objects. In the following example, I am accessing PetUtils's Pet
enum and Qt's Image's FillMode
enum:
// PetUtils.h
#ifndef PETUTILS_H
#define PETUTILS_H
#include <QObject>
#include <QQmlEngine>
class PetUtils : public QObject
{
Q_OBJECT
QML_ELEMENT
public:
explicit PetUtils(QObject *parent = nullptr) : QObject(parent) { }
enum Pet
{
Cat,
Dog,
Parrot
};
Q_ENUMS(Pet)
};
#endif // PETUTILS_H
// main.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import QtQuick.Layouts
import QtEnumApp
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ColumnLayout {
Label { text: "Choose a Pet type" }
// "Cat", "Dog", "Parrot"
ComboBox {
model: petEnum.keyValues
textRole: "key"
valueRole: "value"
}
Label { text: "Choose an Image FillMode" }
// "Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Tile", "TileVertically", "TileHorizontally", "Pad"
ComboBox {
model: fillModeEnum.keyValues
textRole: "key"
valueRole: "value"
}
Image {
id: image
}
}
PetUtils { id: petUtils }
EnumInfo { id: petEnum; obj: petUtils; enumName: "Pet" }
EnumInfo { id: fillModeEnum; obj: image; enumName: "FillMode" }
}
The way this works is that the EnumInfo
uses the metaObject to look up any enum from any object you give it and it can extract the enum keys (i.e. strings) and enum values (i.e. integer values).
// EnumInfo.h
#ifndef ENUMINFO_H
#define ENUMINFO_H
#include <QObject>
#include <QQmlEngine>
class EnumInfo : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QVariant obj MEMBER m_var NOTIFY enumChanged)
Q_PROPERTY(QString enumName MEMBER m_enumName NOTIFY enumChanged)
Q_PROPERTY(QVariant keyValues READ keyValues NOTIFY enumChanged)
Q_PROPERTY(QStringList keys READ keys NOTIFY enumChanged)
Q_PROPERTY(QVariant values READ values NOTIFY enumChanged)
public:
explicit EnumInfo(QObject *parent = nullptr) : QObject(parent) { }
Q_INVOKABLE int keyToValue(const QString& key)
{
QMetaEnum metaEnum = getMetaEnum();
if (!metaEnum.isValid()) return -1;
return metaEnum.keyToValue(key.toUtf8());
}
Q_INVOKABLE QString valueToKey(int value)
{
QMetaEnum metaEnum = getMetaEnum();
if (!metaEnum.isValid()) return QString();
return QString::fromUtf8(metaEnum.valueToKey(value));
}
protected:
QVariant keyValues() const
{
QMetaEnum metaEnum = getMetaEnum();
if (!metaEnum.isValid()) return QVariant();
QVariantList list;
for (int i = 0; i < metaEnum.keyCount(); i++)
{
QVariantMap map;
map["key"] = QString::fromUtf8(metaEnum.key(i));
map["value"] = metaEnum.value(i);
list.append(map);
}
return list;
}
QStringList keys() const
{
QMetaEnum metaEnum = getMetaEnum();
if (!metaEnum.isValid()) return QStringList();
QStringList list;
for (int i = 0; i < metaEnum.keyCount(); i++)
list.append(QString::fromUtf8(metaEnum.key(i)));
return list;
}
QVariant values() const
{
QMetaEnum metaEnum = getMetaEnum();
if (!metaEnum.isValid()) return QVariant();
QVariantList list;
for (int i = 0; i < metaEnum.keyCount(); i++)
list.append(metaEnum.value(i));
return list;
}
QMetaEnum getMetaEnum() const
{
if (!m_var.isValid() || m_var.isNull()) return QMetaEnum();
QObject* obj = qvariant_cast<QObject*>(m_var);
if (!obj) return QMetaEnum();
int index = obj->metaObject()->indexOfEnumerator(m_enumName.toUtf8());
if (index == -1) return QMetaEnum();
return obj->metaObject()->enumerator(index);
}
signals:
void enumChanged();
private:
QVariant m_var;
QString m_enumName;
};
#endif // ENUMINFO_H
# CMakeLists.txt
qt_add_qml_module(appQtEnumApp
URI QtEnumApp
VERSION 1.0
QML_FILES Main.qml
SOURCES EnumInfo.h PetUtils.h
)