PDA

View Full Version : QItemEditorFactory and custom enum types.



hickscorp
5th August 2011, 16:33
Hello people :)

i'm playing with QItemEditorFactory and creating editor widgets on-the-fly for a dynamic form i have in my application (The form shows editable values of a QVariantHash).
Regarding to this, i have two questions.

The first one should be rather trivial for those familiar with the GUI classes. When creating an editor widget with QItemEditorFactory::defaultFactory()->createEditor(), the look-and-feel of the widget looks somehow different than other regular widgets: i suspect these generated widgets are made to be displayed on a table rather than a regular form. What would be the right process to have those widgets skinned as normal?

The second question (And most important), is about the QVariant type being passed to the factory when creating the widget... i would like to give it a QVariant crafted from an enum of mine (Registered with Q_ENUMS and everything), and to be able to have a QComboBox displaying possible values. Is it possible to have that "out-of-the-box" like it has been done in QtDesigner, or do i have to introspect the values using the MetaObject system?

Another fast question i have... When registering new editors in QItemEditorFactory, i see i have to pass a QVariant::Type value, as well as at instanciation time. What if the editor i want to register is for a custom type, higher than QVariant::UserType? When i will instanciate the editor, how will i be able to pass a QVariant::Type superior than QVariant::UserType?

Thanks a lot,
Pierre.

wysota
5th August 2011, 16:52
The first one should be rather trivial for those familiar with the GUI classes. When creating an editor widget with QItemEditorFactory::defaultFactory()->createEditor(), the look-and-feel of the widget looks somehow different than other regular widgets: i suspect these generated widgets are made to be displayed on a table rather than a regular form. What would be the right process to have those widgets skinned as normal?
The widgets I get look quite normal.


The second question (And most important), is about the QVariant type being passed to the factory when creating the widget... i would like to give it a QVariant crafted from an enum of mine (Registered with Q_ENUMS and everything), and to be able to have a QComboBox displaying possible values. Is it possible to have that "out-of-the-box" like it has been done in QtDesigner, or do i have to introspect the values using the MetaObject system?
The latter, I think.


Another fast question i have... When registering new editors in QItemEditorFactory, i see i have to pass a QVariant::Type value, as well as at instanciation time. What if the editor i want to register is for a custom type, higher than QVariant::UserType? When i will instanciate the editor, how will i be able to pass a QVariant::Type superior than QVariant::UserType?

Pass the value returned by qRegisterMetaType() for your type. It's likely you forgot to do this step earlier which might have caused your problems described in the other thread.

hickscorp
5th August 2011, 17:33
Thanks Wysota!

1) My widgets look kind of "borderless"...
2) Ok, i have done that for now to test, and it's working pretty good:
for (QVariantHash::const_iterator i=_parameters.constBegin(); i!=_parameters.constEnd(); ++i) {
QString const &name = i.key();
QVariant const &val = i.value();

int const uTp = val.userType();
QWidget *wgt = 0;
if (uTp>=qMetaTypeId<RE::E::Agressivity>() && uTp<=qMetaTypeId<RE::E::DocumentType>()) {
QComboBox *cmbBx = new QComboBox();
QMetaObject const &mo = RE::E::staticMetaObject;
QString mtName = QMetaType::typeName(uTp);
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);
cmbBx->addItem (RE::classNameToNaturalString(key));
}
wgt = cmbBx;
}
else
wgt = QItemEditorFactory::defaultFactory()->createEditor((QVariant::Type)val.userType(), this);
ui.frmMain->addRow (RE::classNameToNaturalString(name), wgt);
This sample piece of code assumes that all the custom enums are registered all after each other, so their metatype id follow each other (Hence the range check at the very begining of the code, to know if a given type ID is an enum or not).
Later i'll subclass the factory to allow creation of the widget more "cleanly" :)

3) No... i did everything required at compile time and at run time to register my types. The solution i have found is to not put my enums directly in my "fake emulated" namespace, but within a class in that namespace.

Thanks for your answers!
Pierre.

wysota
5th August 2011, 21:18
As I said in the other thread, moc treats the "Qt" namespace in a special way. And it's not releated to Q_MOC_RUN (at least that's not enough). There is a clause in moc source code related to the namespace. You can see that in Generator::generateCode() in src/tools/moc/generator.cpp (and likely elsewhere too).

hickscorp
7th August 2011, 16:08
Thank you very much wysota, you just pointed exactly why Trolltech had made the Qt namespace an exception for MOC. It's now obvious to me that the Q_GADGET / Q_MOC_RUN isnt enough. i'll stick to declaring my enums in a class named "RE::E".