How to access QML enums from c++
-
I'm working in 6.5 LTS QML with support classes in c++.
I have an application where I am trying to configure the buttons for a QML message dialog from my c++ class.
I would like to generate the value that goes into the buttons property of MessageDialog.
In QML, this is an or of the buttons values in the MessageDialog namespace.buttons: MessageDialog.Ok | MessageDialog.Cancel
In Qt Widgets we have:
enum QDialogButtonBox::StandardButton and
flags QDialogButtonBox::StandardButtonsThose are defined in the header file QDialogButtonBox, which I can't seem to include unless I add Qt widgets to my project configuration. Somehow that doesn't feel right.
What would be the best way to get access to the c++ version of the buttons values like "MessageDialog.Ok"?
-
Someone will probably suggest that coupling the C++ and QML this closely results in brittle code. I might agree.
As for solving the issue, the metaobject system provides access to registered enum keys and values.
If you have a MessageDialog with objectName == "dialog":
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [](QObject *object, const QUrl &url) { QObject *child = object->findChild<QObject *>("dialog"); if (child) { const QMetaObject *meta = child->metaObject(); int index = meta->indexOfEnumerator("StandardButtons"); QMetaEnum metaEnum = meta->enumerator(index); for (int i = 0; i < metaEnum.keyCount(); i++) qDebug() << metaEnum.key(i) << metaEnum.value(i); } });
Output:
NoButton 0 Ok 1024 Save 2048 SaveAll 4096 ...
-
I might be looking at a version of the Qt6 source code that doesn't correspond to the version you mention.
However, when I
grep
through the Qt source code,qtdeclarative
(the code that underpins much of what QML can do) seems to useQPlatformDialogHelper::StandardButtons
for the button constants, and those seem to reside in (be provided by)qtbase
(i.e. not widgets).This makes me think you can rely on
qtbase
(gui? core? I'm using the source repository submodule names and I'm not sure what these map to in CMake).In other words, I think you can rely on something more basic (more core) and avoid relying on QWidgets.
I find them in
QPlatformDialogHelper
(inqtbase
), and the code looks like:class Q_GUI_EXPORT QPlatformDialogHelper : public QObject { Q_OBJECT public: enum StyleHint { DialogIsQtWindow }; enum DialogCode { Rejected, Accepted }; enum StandardButton { // keep this in sync with QDialogButtonBox::StandardButton and QMessageBox::StandardButton NoButton = 0x00000000, Ok = 0x00000400, Save = 0x00000800, SaveAll = 0x00001000, Open = 0x00002000, Yes = 0x00004000, YesToAll = 0x00008000, // .... further code omitted for brevity
-
It's in QtGui. Using the header directly is an option. There are two caveats.
- For the most part QtQuick items don't provide a C++ API, so there's no guarantee that the implementation won't change.
- At the top of qplatformdialoghelper.h:
// W A R N I N G
// -------------
//
// This file is part of the QPA API and is not meant to be used
// in applications. Usage of this API may make your code
// source and binary incompatible with future versions of Qt.As a point of information, widgets, gui, and core are all part of qtbase, despite being linked into separate libraries. Declarative is its own module.
-
@jeremy_k said in How to access QML enums from c++:
Someone will probably suggest that coupling the C++ and QML this closely results in brittle code. I might agree.
I hear you and I agree. However, in this case I am dealing with a legacy API that is handing me an error message and a list of buttons to be displayed with that error.
I suppose I could pass the API's button enum into the qml code and do the conversion there, but I'd rather have the logic on the c++ side.