2

When using Qt, many functions take an argument like the flag Qt::LeftDockWidgetArea.

Even though I looked through the Qt sources I could not understand how to achieve this naming behaviour. Is it general C++ or Qt specific?

Assume I have a class MyClass:

class MyClass {
    public:
        MyClass();
        void setFlag(???);
};

I want to call the setFlag method like this:

MyClass mc;
mc.setFlag(MyClass::flag1 | MyClass::flag2)

flag1 and flag2 should just be 0x01 & 0x02, is this an enum? Where do I have to declare that? And what is the argument of the method?

I'm sorry if this is obvious, but I don't get it.

SOLUTION (from the answers)

Very good. From reading the answers below I added this: (note that I didn't really needed flags, just the numbers from an enum, this simplified it a lot)

namespace MyNames {
    typedef enum {
        FA = 0,
        FB = 1
    } Field;
}

class MyClass
{
    public:
        MyClass();
        char getField(MyNames::Field f) const;
};

This indeed allows the following calls (not):

mc.getField(MyNames::FA) //OK
mc.getField(1)           //not OK
HWende
  • 1,705
  • 4
  • 18
  • 30
  • Your solution, however, does not have the flag behavior of the Qt flags. It solves an entirely different problem. – hc_ Apr 26 '12 at 08:19
  • True. I'm really sorry for that. That was my mistake when writing the question for flags. I would happily expand the solution to include binary operators for the enums. (Their value can easily be changed to 0x01, 0x02, 0x04...) – HWende Apr 26 '12 at 08:33
  • But your input argument type can no longer be simply MyNames::Field if you want to allow OR-combinations of MyNames::Field enum values, even though you can re-define their values easily. E.g. mc.getField(MyNames::FA | MyNames::FB); will fail if you only re-define FA = 0x01 and FB = 0x02. – ksming Apr 26 '12 at 10:17
  • If you know how to do it, I would be happy if you could explain it in an answer - we could improve the solution then. – HWende Apr 26 '12 at 11:30

3 Answers3

6

Have a look at the definition of Qt::LeftDockWidgetArea:

enum DockWidgetArea {
    LeftDockWidgetArea = 0x1,
    RightDockWidgetArea = 0x2,
    TopDockWidgetArea = 0x4,
    BottomDockWidgetArea = 0x8,

    DockWidgetArea_Mask = 0xf,
    AllDockWidgetAreas = DockWidgetArea_Mask,
    NoDockWidgetArea = 0
};

Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)

Note the Q_DECLARE_FLAGS macro which, by creating a QFlags typedef achieves the behavior you are asking about. See http://qt-project.org/doc/qt-4.8/qflags.html#Q_DECLARE_FLAGS.

hc_
  • 2,628
  • 1
  • 18
  • 19
  • Note that C++ is strongly typed and doesn't automatically overload `operator|` for enums. `LeftDockWidgetArea | RightDockWidgetArea` requires an `DockWidgetArea operator|(DockWidgetArea, DockWidgetArea)` – MSalters Apr 26 '12 at 07:39
  • 1
    MSalters: enum Foo { Hello }; enum Bar { World }; ... int x = Hello|World; works just fine. – Frank Osterfeld Apr 26 '12 at 07:57
  • 1
    Just in case someone is wondering: The operator MSalters talks about, can easily be declared via Q_DECLARE_OPERATORS_FOR_FLAGS(MyFlags) – DerManu Apr 27 '12 at 01:10
2

If you look at the Qt documentation carefully ( http://doc.qt.io/archives/qt-4.7/qt.html#DockWidgetArea-enum for your particular case), you will see that Qt uses a templated QFlags class to store OR-combinations of enum values in a type-safe manner.

EDIT: Looks like there are two kinds of answers because your question is not very clear. Upon reading your question carefully, I think the following is what you want.

class MyClass {
    public:
        enum Flags{
            Flag1 = 0x01,
            Flag2 = 0x02
        }
        MyClass();
        void setFlag(int Flags);//Not type-safe but works.
        void setFlag(Flags<MyClass::Flags> Flags);//Type-safe but you have to create a Flags class yourself
};

More explanation can be found in an old question here: How to use enums as flags in C++?

Community
  • 1
  • 1
ksming
  • 1,422
  • 1
  • 16
  • 26
  • There's no need to create a custom class manually. See Q_DECLARE_FLAGS in hc_'s answer. – Frank Osterfeld Apr 26 '12 at 07:55
  • Yes, you are right, provided he is actually using Qt library in his project and not just trying to emulate Qt library code with his own code. – ksming Apr 26 '12 at 07:59
  • I indeed want to emulate it in pure C++. I edited my question to include your enum, now how to make the method typesafe? – HWende Apr 26 '12 at 08:05
  • HWende: Sorry. I'm no expert in templates and such so I cannot give a solid answer to this. I was simply suggesting that you try to do the same as in the Qt library by referring to their source code. – ksming Apr 26 '12 at 10:15
1

You will find this (or something similar) in src\corelib\global\qnamespace.h:

#ifndef Q_MOC_RUN
namespace
#else
class Q_CORE_EXPORT
#endif
Qt {

This usually becomes simply

namespace Qt {

To refer to a name declared inside this Qt namespace (such as LeftDockWidgetArea), you precede it with Qt::.

TonyK
  • 16,761
  • 4
  • 37
  • 72