PDA

View Full Version : Meta Types and QVariant



kroenecker
25th February 2007, 08:01
I'm trying to implement my own model/delegate where the model returns pointers to a QHash<QString, QString> *. I've called Q_DECLARE_METATYPE in order to register the new type and have also called qRegisterMetaType<MyType>("MyType"). Unfortunately, when I try to convert the call to index.data(Qt::DisplayType) into <QHash<QString, QString> *, all I seem to get back is a null pointer...



typedef QHash<QString, QString>* MyType;
Q_DECLARE_METATYPE(MyType)

class MyDelegate : public QItemDelegate
{
Q_OBJECT

public:
MyDelegate(QWidget *parent = 0);

virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};



So the declaration above helped me get the code to compile.



MyDelegate::MyDelegate(QWidget *parent)
:QItemDelegate(parent)
{
qRegisterMetaType<MyType>("MyType");
}

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QRect rect = option.rect;

QHash<QString, QString> * t = 0;
t = qVariantValue<QHash<QString, QString>*>(index.data(Qt::DisplayRole));
if(t != 0)
{
std::cout << "T size: " << t->size() << std::endl;
}

if(option.state & QStyle::State_Selected)
{
painter->fillRect(rect, option.palette.highlight());
}
else
{
QItemDelegate::paint(painter, option, index);
}
}



Now something is going wrong on lines 12 and 13. Perhaps something about my data declaration below is incorrect? Of course I'm expecting that I should now have a handle on that index in the model. If I did, then I would proceed to format everything in the paint call.



QVariant CustomModel::data(const QModelIndex &index, int role)const
{
if(!index.isValid())
{
return QVariant();
}
if(role == Qt::TextAlignmentRole)
{
return int(Qt::AlignRight | Qt::AlignVCenter);
}
else if (role == Qt::DisplayRole)
{
//Returning a pointer to the QHash<QString, QString> so just
//cast back and then use the data in the view.
return tableData.at(index.row());
}
return QVariant();
}



Thanks for taking your time :D

kroenecker
25th February 2007, 22:00
Ok I have it working now. I don't know that anyone else really tries to do this sort of thing, but I finally have it working. Signals and slots might cause me some problems, but I have yet to get that far in the design.

Anyway this is what I did:

1) I changed the MetaType definition so that it is no longer a pointer.
2) I moved the Q_DECLARE_METATYPE to a header file that I can include in any header files that need to access the type.
3) After a bit of difficulty I found that the only way that I can return my special typedef as a QVariant is to use QVariant::setValue(const T &value).

As a side note, I'm storing several hashtables in a QList (tableData).



#ifndef MYTYPEDEF_H
#define MYTYPEDEF_H

typedef QHash<QString, QString> MyType;
Q_DECLARE_METATYPE(MyType)

#endif


The header with the typedef.



QVariant CustomModel::data(const QModelIndex &index, int role)const
{
if(!index.isValid())
{
return QVariant();
}
if(role == Qt::TextAlignmentRole)
{
return int(Qt::AlignRight | Qt::AlignVCenter);
}
else if (role == Qt::DisplayRole)
{
//Return the QHash as a QVariant:
const QHash<QString, QString> temp(tableData.at(index.row()));
QVariant var;
var.setValue(temp);
return var;
}
return QVariant();
}



Returning the QVariant, which contains the QHash<QString, QString>. As I understand it, this is only possible by using Q_DECLARE_METATYPE.

wysota
25th February 2007, 22:45
Maybe you could have substituted the hash with a map? Then you could have used QVariantMap which fits into QVariant by default.

kroenecker
26th February 2007, 03:29
Wysota,

Thanks for the suggestion. I didn't notice QVariantMap.

Out of curiosity and only if you have the time, how long have you been a programmer? Are you a professional or is this just a hobby?

wysota
26th February 2007, 08:48
Hmm... let's see... Depends what you mean by a "programmer".
I wrote my first program probably about 16 years ago, it must have been written in BASIC for an Atari microcomputer, but it was just playing around.

I started some "real" programming probably about 12 years ago when I started learning Pascal and C. Then came other languages, my software eng. (and telecom) studies and currently I'm a PhD student at Warsaw University of Technology. I have a professional education, but obviously it's also my hobby. I wouldn't be sitting all day here otherwise regarded that nobody is paying me to do it :)


Some of it is mentioned here: http://www.linkedin.com/in/wysota

Oh, I started playing with Qt during my studies, about 3 years ago. Just look at my registration date at QtForum.org, it was just about then. Oh... and my first Qt application was a complete failure :) It was my university project from operating systems course that used threads and tried to manipulate widgets from non-gui threads. Furthermore I needed to paint rectangles, but I didn't know how to do it so I used QLabels instead. As I said - complete failure, it was hanging all the time and I didn't know why.