summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.cpp
diff options
context:
space:
mode:
authorChristoph Schleifenbaum <christoph.schleifenbaum@kdab.com>2013-03-09 15:12:20 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-05-08 06:02:35 +0200
commitf7b313e6d865ac7020c3164c2f6f0232f052eb9b (patch)
tree9afb8af0bf8283db844df7f72540613d1ef51319 /src/corelib/kernel/qvariant.cpp
parent46d80dedb7794c3e494cc818c85e023beb65626e (diff)
Core: Support for converting user defined QVariant types.
This patchs allows the user to convert defined QMetaType types like MyType to be converted by using e.g. QVariant::toString(), mapping to MyType::toString(). Also all the other QVariant::toXYZ() methods are supported so far. The patch adds static methods QMetaType::registerConverter supporting: - implicit convertion - conversion using member method of source type - conversion using unary functor Change-Id: I4f1db83d9c78bcc9df5c42f82f95cce0480cdcc3 Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com> Reviewed-by: Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com> Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
Diffstat (limited to 'src/corelib/kernel/qvariant.cpp')
-rw-r--r--src/corelib/kernel/qvariant.cpp47
1 files changed, 44 insertions, 3 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index bae4a837a0..be83979205 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -262,6 +262,16 @@ inline bool qt_convertToBool(const QVariant::Private *const d)
/*!
\internal
+ Returns the internal data pointer from \a d.
+ */
+
+static const void *constData(const QVariant::Private &d)
+{
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c);
+}
+
+/*!
+ \internal
Converts \a d to type \a t, which is placed in \a result.
*/
@@ -270,6 +280,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
Q_ASSERT(d->type != uint(t));
Q_ASSERT(result);
+ if (d->type >= QMetaType::User || t >= QMetaType::User) {
+ const bool isOk = QMetaType::convert(constData(*d), d->type, result, t);
+ if (ok)
+ *ok = isOk;
+ if (isOk)
+ return true;
+ }
+
bool dummy;
if (!ok)
ok = &dummy;
@@ -842,8 +860,15 @@ static bool customCompare(const QVariant::Private *a, const QVariant::Private *b
return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type));
}
-static bool customConvert(const QVariant::Private *, int, void *, bool *ok)
+static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
{
+ if (d->type >= QMetaType::User || t >= QMetaType::User) {
+ const bool isOk = QMetaType::convert(constData(*d), d->type, result, t);
+ if (ok)
+ *ok = isOk;
+ return isOk;
+ }
+
if (ok)
*ok = false;
return false;
@@ -1933,6 +1958,12 @@ inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &han
return *v_cast<T>(&d);
T ret;
+ if (d.type >= QMetaType::User || targetType >= QMetaType::User) {
+ const void * const from = constData(d);
+ if (QMetaType::convert(from, d.type, &ret, targetType))
+ return ret;
+ }
+
handlerManager[d.type]->convert(&d, targetType, &ret, 0);
return ret;
}
@@ -2349,13 +2380,19 @@ template <typename T>
inline T qNumVariantToHelper(const QVariant::Private &d,
const HandlersManager &handlerManager, bool *ok, const T& val)
{
- uint t = qMetaTypeId<T>();
+ const uint t = qMetaTypeId<T>();
if (ok)
*ok = true;
+
if (d.type == t)
return val;
T ret = 0;
+ if ((d.type >= QMetaType::User || t >= QMetaType::User)
+ && QMetaType::convert(&val, d.type, &ret, t)) {
+ return ret;
+ }
+
if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok)
*ok = false;
return ret;
@@ -2714,6 +2751,11 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
*/
bool QVariant::canConvert(int targetTypeId) const
{
+ if ((d.type >= QMetaType::User || targetTypeId >= QMetaType::User)
+ && QMetaType::hasRegisteredConverterFunction(d.type, targetTypeId)) {
+ return true;
+ }
+
// TODO Reimplement this function, currently it works but it is a historical mess.
uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
@@ -2838,7 +2880,6 @@ bool QVariant::convert(int targetTypeId)
*/
bool QVariant::convert(const int type, void *ptr) const
{
- Q_ASSERT(type < int(QMetaType::User));
return handlerManager[type]->convert(&d, type, ptr, 0);
}