Solved Conversion from QFlags<> to QVariant could be easier
-
Consider the following code snippet from a run-of-the-mill implementation of the
data()
function by a class which inheritsQAbstractItemModel
:QVariant MyModel::data(const QModelIndex &index, int role) const { QVariant retval; // this doesn't compile ... I am told by the compiler: // "error: ‘template<class T> class QFlags’ used without template parameters" // QFlags::Int i = 0; // ...but this does: uint i = 0; if (index.isValid()) { int row = index.row(); int col = index.column(); switch (role) { case Qt::TextAlignmentRole: switch(col) { case 0: // this doesn't compile: // "error: no match for ‘operator=’ // (operand types are ‘QVariant’ and ‘QFlags<Qt::AlignmentFlag>’)": // retval = Qt::AlignLeft | Qt::AlignVCenter; // but this compiles: i = Qt::AlignLeft | Qt::AlignVCenter; retval = i; break; default: i = Qt::AlignHCenter | Qt::AlignVCenter; retval = i; break; } break; case Qt::DisplayRole: // etc.
Since this idiom is used in so many places, I wouldn't think that it would be necessary to store a
QFlags<>
value instantiated with any native Qt types in a temporary variable just so that I can write it to aQVariant
; there should be aQFlags::operator QVariant()
or something.Now I noticed that there is a
typedef QFlags::Int
which is supposed to resolve either to signed or unsignedint
depending on how it is implemented. But I haven't figured out how to use it, so I take my chances withunsigned int
and hope that I never have to compare it with a signed value anywhere.Is there a better way to do this?
(EDIT: OK, I need to define
i
like this, then it will be the correct type:QFlags<Qt::AlignmentFlag>::Int i = 0;
but I am still stuck with an intermediate variable I really shouldn't need...
-
What about
QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter)
? -
@sierdzio : It compiles, but it doesn't seem to work correctly ... everything is left-aligned and vertically top-aligned when I set the return value like this. When I cast it to an integer before setting the
QVariant
return value, it works correctly. I really don't know what is happening; however, I suspect that theQt::AlignmentFlag
just doesn't have any metadata associated with it which might tellQVariant
how to convert it (either directly or by usingQVariant::fromValue()
). The reverse conversion using the templatedQVariant::value<>()
function also fails to convert it correctly. -
If nothing helps why not just write your own toVariant(QFlags<>) - function?
-
Don't assume ints or uints. There's a typedef for that and conversion operators.
It's a bit of a mouthful but the "correct" way to convert flags to and from variant is:Qt::Alignment original = Qt::AlignLeft | Qt::AlignVCenter; QVariant v = static_cast<Qt::Alignment::Int>(original); Qt::Alignment retrieved = static_cast<Qt::Alignment>(v.value<Qt::Alignment::Int>());
so in your case it would look like this in the
data()
method:retval = static_cast<Qt::Alignment::Int>(Qt::AlignLeft | Qt::AlignVCenter);
and then on the receiving end:
Qt::Alignment a = static_cast<Qt::Alignment>(index.data(role).value<Qt::Alignment::Int>());
-
@chris-kawa : Thank you for the detailed explanation. It is a little less typing to write
Qt::Alignment::Int
instead of
QFlags<Qt::AlignmentFlag>::Int
Maybe I will take Christian Ehrlicher's advice and write the
toVariant()
function? It sounds like a good idea. I was just wondering why this isn't already built into theQVariant
class? -
@robert-hairgrove said in Conversion from QFlags<> to QVariant could be easier:
I was just wondering why this isn't already built into the QVariant class?
QFlags
is a template so QVariant would have to support all possible specializations, for all possible enum types, which is unrealistic.
It could be supported on theQFlags
side with something liketoVariant()
andfromVariant()
, but if you take a step back this doesn't scale well, because then why nottoString
,toDouble
,toWhatever
?The best place for this IMO would be outside both
QVariant
andQFlags
, with a function template that would basically do the casts I mentioned. My guess is it's not in Qt because nobody felt like this was big enough of a deal and it wouldn't even be that much shorter either.Anyway, those are basically one-liners, so you can easily provide them yourself if you feel like it.
-
@chris-kawa Thank you.