PDA

View Full Version : Enums to QVariants and comparing those after the conversion.



hickscorp
7th August 2011, 17:20
Hello,

i am registering enums to the Qt meta-object system. i have double checked that all of those have a meta-type ID, and everything looks perfect. But i have some kind of unresolved issue with the comparison of those.

Let's consider this code for populating a combobox:
WgtEnumItemEditor::WgtEnumItemEditor (QVariant::Type t, QWidget *p)
: QComboBox(p) {
QMetaObject const &mo = staticMetaObject;
QString mtName = QMetaType::typeName(t);
mtName = mtName.mid(mtName.lastIndexOf(':')+1);
qint32 const iEnum = mo.indexOfEnumerator(mtName.toLatin1());
QMetaEnum const &en = mo.enumerator(iEnum);
quint32 const cEnum = en.keyCount();
for (quint32 i=0; i<cEnum; i++) {
const char *key = en.key(i);
uint const val = en.value(i);
QVariant const var (t, &val);
addItem (classNameToNaturalString(key), var);
qDebug() << var;
}
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(this_currentIndexChanged(int)));
}
It works good, my list gets populated with human readable texts for my enums.

Now, i'm trying to set the initial value displayed by the list with a QVariant itself containing a value for the enum:
void WgtEnumItemEditor::setValue (const QVariant &v) {
for (quint32 i=0; i<count(); i++) {
if (itemData(i)==v.data) {
setCurrentIndex(i);
break;
}
}
}This piece of code doesn't work. i have to replace the test by:
*(uint*)itemData(i).data()==*(uint*)v.data()This way it works.

Can anyone explain me how to enable comparison of my custom enums in QVariants? Or am i doing something wrong while creating the QVariant being used as userdata for the list maybe?

Also, if i try to qDebug() the QVariants created in loop for populating the list, i get outputs like this:
QVariant(ReadingDirection, )
QVariant(ReadingDirection, )
QVariant(ReadingDirection, )
QVariant(ReadingDirection, )
QVariant(ReadingDirection, )
QVariant(BarcodeStandard, )
QVariant(BarcodeStandard, )
QVariant(BarcodeStandard, )As you can see, the value isn't outputed correctly... Can you please help me find why?

Thanks,
Pierre.



Thank you,
Pierre.

MarekR22
8th August 2011, 09:38
Where is defined QVariant::data (http://doc.qt.nokia.com/latest/qvariant.html#data)? I don't see it in documentation!
I understand that you are assuming that nums are not flag kind (QMetaEnum::isFlag (http://doc.qt.nokia.com/latest/qmetaenum.html#isFlag))!

Every enum can be treated as int value! So you should compare enums as ints:

bool ok = flase;
if (itemData(i).toInt() ==v.toInt(&ok))
if (ok) {

}


Why did you chose QVariant::Type as constructor parameter? Why not QVariant, enum name (const char *) or QMetaEnum?

hickscorp
8th August 2011, 13:36
Where is defined QVariant::data (http://doc.qt.nokia.com/latest/qvariant.html#data)?
In the QVariant exposed C++ API. However its a public method defined from the exposed header of QVariant. It allows me to construct a QVariant by giving it a pointer of my value which is internally copied. That's the only way i have to construct a QVariant which type will be my usertype.
You were right MarekR22, i made a typo when posting my snippets... the code should have read:
itemData(i)==vMy bad!


I don't see it in documentation!
Aren't the public methods exposed in a header file the best documentation for a class?


I understand that you are assuming that nums are not flag kind (QMetaEnum::isFlag (http://doc.qt.nokia.com/latest/qmetaenum.html#isFlag))!
Every enum can be treated as int value! So you should compare enums as ints:
[CODE]bool ok = false;
if (itemData(i).toInt() ==v.toInt(&ok))

The conversion isnt working. QVariant::toInt when storing enum values always return 0. i have no idea why. It seems that when constructing a QVariant from a usertype, i won't be able to convert them later.


Why did you chose QVariant::Type as constructor parameter?
As i said: That's the only way my QVariant will then carry the right type...


Why not QVariant, enum name (const char *) or QMetaEnum?
Your first suggestion constructs a QVariant based on QString, the problem is that the typing information is lost when doing that. Your second suggestion is a no-do. QMetaEnum is not actually carying the value of the enum, just its typing information...


To summarize what i need: QVariant can carry both the typing and the value of things... i need to use both, i.e. to be able to first look at QVariant types (To know if they are storing enum values from the same enum), and them compare them.

Any other idea please? An actual working sample code would greatly help...
Pierre.

mentalmushroom
8th August 2011, 15:00
Not sure I understand correctly what you need, but take a look at these functions:



Type QVariant::type () const
int QVariant::userType () const
const char * QVariant::typeName () const
const char * QVariant::typeToName ( Type typ ) [static]

nightghost
8th August 2011, 16:18
...
for (quint32 i=0; i<cEnum; i++) {
const char *key = en.key(i);
uint const val = en.value(i);
QVariant const var (t, &val);
addItem (classNameToNaturalString(key), var);
qDebug() << var;
...
}


the address to the uint gets invalid after the foreach block.

hickscorp
8th August 2011, 20:41
@nightghost: And i don't see the problem. When constructing the QVariant this way, the *pointer* isnt stored. Instead, the data it points to is copied. My thing is working, im asking for something else.

Added after 6 minutes:


Not sure I understand correctly what you need, but take a look at these functions:

Type QVariant::type () const
int QVariant::userType () const
const char * QVariant::typeName () const
const char * QVariant::typeToName ( Type typ ) [static]

Sorry but i really don't see how it can be helpfull to me.

Thread simplified and moved here: http://www.qtcentre.org/threads/43756-Simplified-problem-about-enums-and-QVariants.