Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to access QML enums from c++
Forum Updated to NodeBB v4.3 + New Features

How to access QML enums from c++

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
5 Posts 3 Posters 515 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    preiter
    wrote on last edited by
    #1

    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::StandardButtons

    Those 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"?

    1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      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
      ...
      

      Asking a question about code? http://eel.is/iso-c++/testcase/

      P 1 Reply Last reply
      1
      • KH-219DesignK Offline
        KH-219DesignK Offline
        KH-219Design
        wrote on last edited by
        #3

        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 use QPlatformDialogHelper::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 (in qtbase), 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
        

        www.219design.com
        Software | Electrical | Mechanical | Product Design

        1 Reply Last reply
        0
        • jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by jeremy_k
          #4

          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.

          Asking a question about code? http://eel.is/iso-c++/testcase/

          1 Reply Last reply
          2
          • jeremy_kJ jeremy_k

            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
            ...
            
            P Offline
            P Offline
            preiter
            wrote on last edited by
            #5

            @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.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved