fa__
fa__

Reputation: 327

Q_ENUMS with enum in header file

I want to use the elements of an enum as items in a QComboBox. I can do so if the enum is defined in the same class but I would like to use an enum defined in a header file. My goal is to use the enum directly from the header file, without altering the header file. Moreover, I would like my code to adapt to a changing enum, both in the name of the elements and in the number of them.

I have found this answer and this link that have helped me understand how to populate a QComboBox with an enum. The solution in the answer works for me but only if the enum is defined in the class.

The basic code I would like to implement looks like:

definitions.h

#ifndef _DEFINITIONS_H_
#define _DEFINITIONS_H_

typedef enum
{
     FIRST = 0,
     SECOND,
     THIRD
} elements;

#endif

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "definitions.h"

 class MainWindow : public QMainWindow
 {
   Q_OBJECT
   Q_ENUMS(elements);

 public:
   explicit MainWindow(QWidget *parent = 0);
   QComboBox *comboBox;

 };

 #endif 

mainwindow.cc

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
 QMainWindow(parent),
{
  int index = metaObject()->indexOfEnumerator("elements");
  QMetaEnum metaEnum = metaObject()->enumerator(index);

  for (int i = 0; i < metaEnum.keyCount(); i++)
      comboBox->addItem(metaEnum.valueToKey(i));
 }

This code does not encounter any issue at compilation on runtime but has no effect at all. Defining the enum in MainWindow class works like a charm.

It does not look like a visibility issue because I can use the elements of the enum in my code and I have not encountered any compilation problem.

I have tried redefining my enum in mainwindow.h with typedef without success:

typedef elements new_elements

I have also tried replacing Q_ENUMS with Q_ENUM as suggested by the answer below but the result is the same.

Is it possible to use Q_ENUMS/Q_ENUM with an enum defined in a header file? What should I do different?

Upvotes: 1

Views: 2859

Answers (2)

mohabouje
mohabouje

Reputation: 4050

You can't do that. Q_ENUMS need a meta object provided either by the QObject class or the Q_GADGET macro, that's why it works when the enum is declared in a class derived from a QObject.

Since Qt 5.8, a new macro was introduced Q_ENUM_NS that makes this possible:

This macro registers an enum type with the meta-object system. It must be placed after the enum declaration in a namespace that has the Q_NAMESPACE macro. It is the same as Q_ENUM but in a namespace.

You can do something like that:

namespace MyNamespace {

    Q_NAMESPACE

    enum elements {
     FIRST = 0,
     SECOND,
     THIRD
    };

    Q_ENUM_NS(elements)
}

See this post for more information.

Updates

Regarding the last comment, you can create a new enumeration and associate each element with the value of the new one.

 class MainWindow : public QMainWindow {
   Q_OBJECT
 public:   
     enum elements {
         FIRST = ::elements::FIRST,
         SECOND = ::elements::SECOND,
         THIRD = ::elements::THIRD,
     };
     Q_ENUM(elements);
}

Then, for a function like:

void use_enum(elements e);

// Call it with the original one
use_enum(elements::FIRST);
// Call it with the new one, you just created
use_enum(MainWindow::elements::FIRST);

Upvotes: 1

Gasteizko
Gasteizko

Reputation: 208

Check the Q_ENUM that registers automatically as metatype as it is said in the documentation What's New in Qt 5.5:

Added Q_ENUM to replace Q_ENUMS, which allows to get a QMetaEnum at compile time using QMetaEnum::fromType. Such enums are now automatically registered as metatypes, and can be converted to strings within QVariant, or printed as string by qDebug().

Upvotes: 0

Related Questions