Fix assigning int QFlag-type properties

Ensure they are handled as enumerations in QMetaType.

This is required for handling QFlag-type properties in Qt Designer

Fixes: QTBUG-83689
Change-Id: Ifbfb5c5b5cd34fce462e299505d063e22e725c2e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
bb10
Friedemann Kleint 2020-04-22 08:25:18 +02:00 committed by Fabian Kosmale
parent 1c80d056e4
commit 26a0a89421
2 changed files with 62 additions and 2 deletions

View File

@ -432,7 +432,16 @@ struct ConverterFunctor : public AbstractConverterFunction
struct IsMetaTypePair;
template<typename, typename>
struct MetaTypeSmartPointerHelper;
}
template<typename T>
struct IsQFlags : std::false_type {};
template<typename Enum>
struct IsQFlags<QFlags<Enum>> : std::true_type {};
template<typename T>
struct IsEnumOrFlags : std::disjunction<std::is_enum<T>, IsQFlags<T>> {};
} // namespace QtPrivate
class Q_CORE_EXPORT QMetaType {
public:
@ -1730,7 +1739,7 @@ namespace QtPrivate {
| (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
| (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
| (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
| (IsEnumOrFlags<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
| (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
| (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)

View File

@ -65,6 +65,7 @@ private slots:
void readAndWriteWithLazyRegistration();
void mapProperty();
void conversion();
void enumsFlags();
public:
enum EnumType { EnumType1 };
@ -181,6 +182,33 @@ public:
{}
};
class EnumFlagsTester : public QObject
{
Q_OBJECT
Q_PROPERTY(TestEnum enumProperty READ enumProperty WRITE setEnumProperty)
Q_PROPERTY(TestFlags flagProperty READ flagProperty WRITE setFlagProperty)
public:
enum TestEnum { e1, e2 };
Q_ENUM(TestEnum)
enum TestFlag { flag1 = 0x1, flag2 = 0x2 };
Q_DECLARE_FLAGS(TestFlags, TestFlag)
using QObject::QObject;
TestEnum enumProperty() const { return m_enum; }
void setEnumProperty(TestEnum e) { m_enum = e; }
TestFlags flagProperty() const { return m_flags; }
void setFlagProperty(TestFlags f) { m_flags = f; }
private:
TestEnum m_enum = e1;
TestFlags m_flags;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(EnumFlagsTester::TestFlags)
void tst_QMetaProperty::readAndWriteWithLazyRegistration()
{
QCOMPARE(QMetaType::type("CustomReadObject*"), int(QMetaType::UnknownType));
@ -246,5 +274,28 @@ void tst_QMetaProperty::conversion()
QCOMPARE(value7, QLatin1String("reset"));
}
void tst_QMetaProperty::enumsFlags()
{
// QTBUG-83689, verify that enumerations and flags can be assigned from int,
// which is important for Qt Designer.
EnumFlagsTester t;
auto mo = t.metaObject();
const int enumIndex = mo->indexOfProperty("enumProperty");
QVERIFY(enumIndex >= 0);
auto enumProperty = mo->property(enumIndex);
QVERIFY(enumProperty.metaType().flags().testFlag(QMetaType::IsEnumeration));
QVERIFY(enumProperty.write(&t, QVariant(int(EnumFlagsTester::e2))));
QCOMPARE(t.enumProperty(), EnumFlagsTester::e2);
const int flagsIndex = mo->indexOfProperty("flagProperty");
QVERIFY(flagsIndex >= 0);
auto flagsProperty = mo->property(flagsIndex);
QVERIFY(flagsProperty.metaType().flags().testFlag(QMetaType::IsEnumeration));
QVERIFY(flagsProperty.write(&t, QVariant(int(EnumFlagsTester::flag2))));
QCOMPARE(t.flagProperty(), EnumFlagsTester::flag2);
}
QTEST_MAIN(tst_QMetaProperty)
#include "tst_qmetaproperty.moc"