// xValue net.addProprety("value", "xValue", object); // net.addSignal("started", object, SIGNAL(started(int, QString))); // net.addFunction("start", object, "method_name");
// net.setProperty("value", 123); // - , QLineEdit net.bindProperty("value", lineEdit, "text"); // net.connect(SIGNAL(started(int, QString)), object, SLOT(onStarted(int, QString))); // ( ) bool ok; QVariant ret = net.call("start", QVariantList() << "str1" << 1, &ok); // ( ) net.call("start", QVariantList() << "str1" << 1, object, SLOT(startCalled(bool, QVariant)));
Class Property { public: Proprety(const QString &name) : m_name(name) {} public slots: void propertyChanged(const QVariant &newValue) { emit mapped(m_name, newValue); } signals: void mapped(const QString &propertyName, const QVariant &newValue); }
PropertyMapper *m1 = new PropertyMapper("p1"); connect(object, SIGNAL(p1Changed(QVariant)), m1, SLOT(propertyChanged(QVariant)); PropertyMapper *m2 = new PropertyMapper("p2"); connect(object, SIGNAL(p2Changed(QVariant)), m2, SLOT(propertyChanged(QVariant));
int Counter::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 1: setValue((*reinterpret_cast< int(*)>(_a[1]))); break; } _id -= 2; } return _id; }
class PropertyMapper : public QObject // Q_OBJECT { public: PropertyMapper(QObject *mapToObject, const char *mapToMethod, QObject *parent = 0); int addProperty(const QString &propertyName, const char *mappingPropertyName, QObject *mappingObject, bool isQuickProperty); void setMappedProperty(const QString &name, const QVariant &value); QVariant mappedProperty(const QString &name) const; int qt_metacall(QMetaObject::Call call, int id, void **arguments); private: QObject *m_mapTo; const char *m_toMethod; QHash<QString, int> m_propertyIndices; typedef struct { QString name; QVariant::Type type; const char *mappingName; QObject *mappingObject; bool isQuickProperty; // need to call mappingObject->property to get value QVariant lastValue; } property_t; QList<property_t> m_properties; };
int PropertyMapper::addProperty(const QString &propertyName, const char *mappingPropertyName, QObject *mappingObject, bool isQuickProperty) { if (m_propertyIndices.contains(propertyName)) { qWarning() << "can't create" << propertyName << "property, already exist!"; return -1; }
int propertyIdx = mappingObject->metaObject()->indexOfProperty(mappingPropertyName); QMetaProperty metaProperty = mappingObject->metaObject()->property(propertyIdx);
int id = m_properties.size(); m_propertyIndices[propertyName] = id; m_properties.push_back({propertyName, metaProperty.type(), mappingPropertyName, mappingObject, isQuickProperty, QVariant()});
int signalId = metaProperty.notifySignalIndex(); if (signalId < 0) { qWarning() << "can't create" << propertyName << "(notify signal doesn't exist)"; return -1; } if (!QMetaObject::connect(mappingObject, signalId, this, id + metaObject()->methodCount())) { qWarning() << "can't connect to notify signal:" << mappingPropertyName; return -1; } return id; }
int PropertyMapper::qt_metacall(QMetaObject::Call call, int id, void **arguments) { // , , , id = QObject::qt_metacall(call, id, arguments); if (id < 0 || call != QMetaObject::InvokeMetaMethod) return id; Q_ASSERT(id < m_properties.size());
property_t &p = m_properties[id];
QVariant value; if (p.isQuickProperty) { value = p.mappingObject->property(p.mappingName); } else { const void *data = arguments[1]; value = QVariant(p.type, data); } if (value != p.lastValue) { p.lastValue = value; QMetaObject::invokeMethod(m_mapTo, m_toMethod, Q_ARG(QString, p.name), Q_ARG(QVariant, value)); } return -1; }
Reciever reciever; PropertyMapper mapper(&reciever, "mapped"); Tester tester; mapper.addProperty("value_m", "value", &tester); mapper.addProperty("name_m", "name", &tester); tester.setName("Button1"); tester.setValue(123);
Q_INVOKABLE void mapped(const QString &propertyName, const QVariant &newValue) { qDebug() << propertyName << newValue; }
"Name_m" QVariant (QString, "Button1")
"Value_m" QVariant (int, 123)
Source: https://habr.com/ru/post/198270/
All Articles