QMetaType: Allow conversion of derived gadget types to their base types
A derived gadget has an is-a relationship with its base type. It should be convertible. In fact, canConvert() already tells us it is. Change-Id: I71a5ac9afd78e88adb23b4d0e757f34077f63207 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
873a8edff8
commit
657a18c7fa
@ -2181,7 +2181,7 @@ static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool convertQObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
|
||||
static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
|
||||
{
|
||||
// handle QObject conversion
|
||||
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
|
||||
@ -2194,8 +2194,14 @@ static bool convertQObject(QMetaType fromType, const void *from, QMetaType toTyp
|
||||
// if fromObject is null, use static fromType to check if conversion works
|
||||
*static_cast<void **>(to) = nullptr;
|
||||
return fromType.metaObject()->inherits(toType.metaObject());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const QMetaObject *f = fromType.metaObject();
|
||||
const QMetaObject *t = toType.metaObject();
|
||||
if (f && t && f->inherits(t)) {
|
||||
toType.destruct(to);
|
||||
toType.construct(to, from);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -2278,7 +2284,7 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
|
||||
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
|
||||
return convertToAssociativeIterable(fromType, from, to);
|
||||
|
||||
return convertQObject(fromType, from, toType, to);
|
||||
return convertMetaObject(fromType, from, toType, to);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@ -2309,7 +2315,7 @@ bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
|
||||
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
|
||||
return viewAsAssociativeIterable(fromType, from, to);
|
||||
|
||||
return convertQObject(fromType, from, toType, to);
|
||||
return convertMetaObject(fromType, from, toType, to);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -217,6 +217,22 @@ struct CustomEqualsOnlyType
|
||||
static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>);
|
||||
static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>);
|
||||
|
||||
struct BaseGadgetType
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
explicit BaseGadgetType(QVariant foo = QVariant()) : m_foo(std::move(foo)) {}
|
||||
QVariant m_foo;
|
||||
};
|
||||
|
||||
struct DerivedGadgetType : public BaseGadgetType
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
explicit DerivedGadgetType(QVariant foo = QVariant()) : BaseGadgetType(std::move(foo)) {}
|
||||
int bar = 25;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CustomConvertibleType);
|
||||
Q_DECLARE_METATYPE(CustomConvertibleType2);
|
||||
Q_DECLARE_METATYPE(CustomDebugStreamableType);
|
||||
|
@ -164,6 +164,7 @@ void tst_QMetaType::convertCustomType_data()
|
||||
QTest::addColumn<QLineF>("testQLineF");
|
||||
QTest::addColumn<QChar>("testQChar");
|
||||
QTest::addColumn<CustomConvertibleType>("testCustom");
|
||||
QTest::addColumn<DerivedGadgetType>("testDerived");
|
||||
|
||||
QTest::newRow("default") << true
|
||||
<< QString::fromLatin1("string") << true << 15
|
||||
@ -171,14 +172,16 @@ void tst_QMetaType::convertCustomType_data()
|
||||
<< QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34)
|
||||
<< QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8)
|
||||
<< QLine(3, 9, 29, 4) << QLineF(38.9, 28.9, 102.3, 0.0)
|
||||
<< QChar('Q') << CustomConvertibleType(QString::fromLatin1("test"));
|
||||
<< QChar('Q') << CustomConvertibleType(QString::fromLatin1("test"))
|
||||
<< DerivedGadgetType(QString::fromLatin1("test"));
|
||||
QTest::newRow("not ok") << false
|
||||
<< QString::fromLatin1("string") << true << 15
|
||||
<< double(3.14) << float(3.6) << QRect(1, 2, 3, 4)
|
||||
<< QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34)
|
||||
<< QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8)
|
||||
<< QLine(3, 9, 29, 4) << QLineF()
|
||||
<< QChar('Q') << CustomConvertibleType(42);
|
||||
<< QChar('Q') << CustomConvertibleType(42)
|
||||
<< DerivedGadgetType(42);
|
||||
}
|
||||
|
||||
void tst_QMetaType::convertCustomType()
|
||||
@ -276,6 +279,15 @@ void tst_QMetaType::convertCustomType()
|
||||
v = QVariant::fromValue(testCustom);
|
||||
QVERIFY(v.canConvert(::qMetaTypeId<CustomConvertibleType2>()));
|
||||
QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo);
|
||||
|
||||
QFETCH(DerivedGadgetType, testDerived);
|
||||
v = QVariant::fromValue(testDerived);
|
||||
QCOMPARE(v.metaType(), QMetaType::fromType<DerivedGadgetType>());
|
||||
QCOMPARE(v.value<DerivedGadgetType>().m_foo, testDerived.m_foo);
|
||||
QVERIFY(v.canConvert(QMetaType::fromType<BaseGadgetType>()));
|
||||
QVERIFY(v.convert(QMetaType::fromType<BaseGadgetType>()));
|
||||
QCOMPARE(v.metaType(), QMetaType::fromType<BaseGadgetType>());
|
||||
QCOMPARE(v.value<BaseGadgetType>().m_foo, testDerived.m_foo);
|
||||
}
|
||||
|
||||
void tst_QMetaType::convertConstNonConst()
|
||||
|
Loading…
Reference in New Issue
Block a user