-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathQuickPropertyMap.cpp
More file actions
127 lines (105 loc) · 3.28 KB
/
QuickPropertyMap.cpp
File metadata and controls
127 lines (105 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "QuickPropertyMap.h"
#include <private/qmetaobjectbuilder_p.h>
QuickPropertyMap::QuickPropertyMap(QObject* parent) :
QuickPropertyMapBase(parent)
{
buildMetaObject(); // NOTE: build an empty valid QMetaObject
}
QuickPropertyMap::~QuickPropertyMap()
{
free(m_metaObject); // NOTE: because of malloc deep inside QMetaObjectBuilder
}
void QuickPropertyMap::addProperty(const QByteArray& name, const QVariant& value, int type)
{
if (!m_finalized)
m_propertyList.append(DynamicProperty { name, value, type });
}
void QuickPropertyMap::build()
{
if (!m_finalized)
{
m_finalized = true;
buildMetaObject();
}
}
void QuickPropertyMap::insert(int i, const QVariant& value)
{
if (i >= 0 && i < m_propertyList.count())
{
DynamicProperty& p = m_propertyList[i];
if (p.value != value)
{
writeValue(p.value, value);
QMetaObject::activate(this, m_metaObject, i, nullptr);
}
}
}
void QuickPropertyMap::writeValue(QVariant& my, const QVariant& value)
{
if (my.userType() == value.userType())
my = value;
else
my = QVariant(my.type());
}
void QuickPropertyMap::buildMetaObject()
{
free(m_metaObject);
QMetaObjectBuilder builder;
builder.setClassName("QuickPropertyMap");
builder.setSuperClass(&QuickPropertyMapBase::staticMetaObject);
for (const DynamicProperty& dynamicProperty : m_propertyList)
{
QMetaPropertyBuilder propertyBuilder = builder.addProperty(dynamicProperty.name, QMetaType::typeName(dynamicProperty.typeId));
QMetaMethodBuilder signalBuilder = builder.addSignal(dynamicProperty.name + "сhanged()");
propertyBuilder.setWritable(true);
propertyBuilder.setNotifySignal(signalBuilder);
}
m_metaObject = builder.toMetaObject();
// NOTE: build an index cache for faster lookups
for (int i = 0; i != m_propertyList.count(); ++i)
m_propertyIndex.insert(m_propertyList[i].name, i);
}
const QMetaObject* QuickPropertyMap::metaObject() const
{
return m_metaObject;
}
int QuickPropertyMap::my_metacall(QMetaObject::Call call, int id, void** argv)
{
switch (call)
{
case QMetaObject::ReadProperty:
{
const DynamicProperty& property = m_propertyList[id];
QMetaType::construct(property.typeId, argv[0], property.value.data());
}
break;
case QMetaObject::WriteProperty:
{
DynamicProperty& p = m_propertyList[id];
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QVariant value(p.typeId, argv[0]);
#else
QVariant value(QMetaType(p.typeId), argv[0]);
#endif
if (p.value != value)
{
writeValue(p.value, value);
QMetaObject::activate(this, m_metaObject, id, nullptr);
emit valueChanged(p.name, p.value);
}
}
break;
default:
break;
}
return -1;
}
int QuickPropertyMap::qt_metacall(QMetaObject::Call call, int id, void** argv)
{
const int realId = id - m_metaObject->propertyOffset();
return (realId >= 0) ? my_metacall(call, realId, argv) : QuickPropertyMapBase::qt_metacall(call, id, argv);
}
void* QuickPropertyMap::qt_metacast(const char* name)
{
return (strcmp(name, m_metaObject->className()) == 0) ? this : QuickPropertyMapBase::qt_metacast(name);
}