Can I somehow use QVariant::isNull()
with a custom Q_DECLARE_METATYPE()
type?
For example, if I define such a wrapper class for an integer (why should I, but this should be a minimal example). Defining a bool isNull() const
member function doesn't help:
#include <QVariant>
#include <QDebug>
class Integer {
bool null;
int x;
public:
Integer() : null(true), x(0) {}
Integer(int x) : null(false), x(x) {}
int value() const {
return x;
}
bool isNull() const {
return null;
}
};
Q_DECLARE_METATYPE(Integer)
int main()
{
Integer x(42);
Integer y(0);
Integer z;
qDebug() << x.isNull() << QVariant::fromValue(x).isNull();
qDebug() << y.isNull() << QVariant::fromValue(y).isNull();
qDebug() << z.isNull() << QVariant::fromValue(z).isNull(); // Not as expected!
}
Output:
false false
false false
true false // Not as expected!
Unfortunately you can't. The QVariant::isNull
code is the following:
static bool isNull(const QVariant::Private *d)
{
switch(d->type) {
case QVariant::String:
return v_cast<QString>(d)->isNull();
case QVariant::Char:
return v_cast<QChar>(d)->isNull();
case QVariant::Date:
return v_cast<QDate>(d)->isNull();
case QVariant::Time:
return v_cast<QTime>(d)->isNull();
...
}
return d->is_null;
}
As you can see it explicitely uses the isNull()
function of some common variable types and by default it returns the d->is_null
value.
The d->is_null
is a class member of the D pointer of the QVariant
class which is initialized to true
but every time you assign a value to the QVariant
it becomes false
:
inline void qVariantSetValue(QVariant &v, const T &t)
{
...
d.is_null = false;
...
}
So for custom types it will always return false
.
One possibility (which I do not recommend) would be to subclass QVariant
and reimplement the isNull
function. In this function you could check if the type is custom and in this case you can return the return value of the isNull
function of your custom class, otherwise you should return the return value of the QVariant::isNull
function.
bool MyQVariant::isNull() const
{
if (QString(typeName()) == "MyCustomClass")
return value<MyCustomClass>().isNull();
return QVariant::isNull();
}
EDIT
Your example code using the subclassed QVariant:
#include <QVariant>
#include <QDebug>
class Integer {
bool null;
int x;
public:
Integer() : null(true), x(0) {}
Integer(int x) : null(false), x(x) {}
int value() const {
return x;
}
bool isNull() const {
return null;
}
};
Q_DECLARE_METATYPE(Integer)
class MyQVariant : public QVariant
{
public:
MyQVariant(QVariant v) :
QVariant(v) {}
bool isNull() const
{
if (QString(typeName()) == "Integer")
return value<Integer>().isNull();
return QVariant::isNull();
}
};
int main(int argc, char *argv[])
{
Integer x(42);
Integer y(0);
Integer z;
qRegisterMetaType<Integer>("Integer");
MyQVariant v1(QVariant::fromValue(x));
MyQVariant v2(QVariant::fromValue(y));
MyQVariant v3(QVariant::fromValue(z));
qDebug() << x.isNull() << v1.isNull();
qDebug() << y.isNull() << v2.isNull();
qDebug() << z.isNull() << v3.isNull();
}
Output:
false false
false false
true true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With