Question

I am migrating a project from Qt 4.x to 5, and there is a class that contains an attribute that goes:

Qt::PenStyle penStyle;

and its respective get function:

Qt::PenStyle getPenStyle() {return penStyle;}

I get a compilation error saying that

error: 'QVariant::QVariant(Qt::PenStyle)' is private
     QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE;
     ^
..\marssies\painterbar.cpp:217:88: error: within this context
         lineStyle -> setCurrentIndex(lineStyle -> findData(graphicObject->getPenStyle()));
                                                                                        ^

Doing some research I found this:

QVariant:
*Inconsistent constructor taking Qt::GlobalColor and producing QVariant(QColor) instance was removed. Code constructing such variants can be migrated by explicitly calling QColor constructor. For example from “QVariant(Qt::red)” to “QVariant(QColor(Qt::red))

*Similarly, implicit creation of QVariants from enum values Qt::BrushStyle, Qt::PenStyle, and Qt::CursorShape have been removed. Create objects explicitly or use static_cast(Qt::SolidLine) to create a QVariant of type int with the same value as the enum.

The question is, how should I declare the attribute/function if I cant do Qt::PenStyle just like that? What does it mean by with creating objects explicitly? I've tried doing something like the quote says but I didnt manage to solve it. I did manage to solve other similar errors but none of them were declarations of attributes or functions.

Full error:

In file included from ..\..\..\..\..\Qt5\5.2.1\mingw48_32\include\QtCore/qsettings.h:46:0,
                 from ..\..\..\..\..\Qt5\5.2.1\mingw48_32\include\QtCore/QSettings:1,
                 from ..\marssies\appcommon.h:10,
                 from ..\marssies\painterbar.h:5,
                 from ..\marssies\painterbar.cpp:1:
..\..\..\..\..\Qt5\5.2.1\mingw48_32\include/QtCore/qvariant.h: In member function 'void PainterBar::setGraphicObject(GraphicsPrimitive*, PainterBar::FinishMode)':
..\..\..\..\..\Qt5\5.2.1\mingw48_32\include/QtCore/qvariant.h:482:5: error: 'QVariant::QVariant(Qt::PenStyle)' is private
     QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE;
     ^
..\marssies\painterbar.cpp:217:88: error: within this context
         lineStyle -> setCurrentIndex(lineStyle -> findData(graphicObject->getPenStyle()));
                                                                                        ^
Was it helpful?

Solution

The problem is that enums are a bit of a tricky type and Qt 5 seems to have removed some specific magic for these enums in question. The base template constructor for QVariant is defined as private as to enforce that QVariants can only be constructed with types they really can handle.

The first solution proposed in the docs is to instantiate an object because it is easier to hold a "normal" type in a QVariant than an enum. QColor, QPen etc. are all QObjects so the general logic to hold them in a QVariant works for them; it doesn't work for Qt::PenStyle.

The second solution then is the typical C-style solution people use when dealing with enums. As an enum is stored as an int, you can always explicitely cast to int (and C sometimes also does this implicitely, where C++ doesn't, afaik). So what is effectively stored in the QVariant is an int and you, the programmer are the only one that knows in reality it is a Qt::PenStyle.

While the first solution is slightly less efficient (thinking of storing thousands of QPen objects instead of QPenStyles/ints), it might be the cleaner one, as the semantics (the QVariant holds a pen you can draw with) are preserved.

If this doesn't work for you:

int getPenStyle() {return (int)penStyle;}

or

QPen getPenStyle() {return QPen(penStyle);}

then please go ahead and post a self-contained example so we can further discuss.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top