2017-01-08 11 views
0

Я хочу написать соединитель свойств для подключения свойств в C++ Qt способом QML. Это может быть как это:Получить свойство изменено уведомитель от метаобъекта

new PropConnector (receiver, "propName", sender, "propName"); 

Класс propConnector представляет собой небольшой класс QObject, который использует в качестве родителя отправителя, прослушивает сигнал изменения свойства и устанавливает соответствующее свойство приемника. Как это:

class PropConnector : public QObject 
{ 
    Q_OBJECT 
private: 
    QObject *_sender; 
    QObject *_receiver; 
    QString _senderProp; 
    QString _receiverProp; 
public: 
    PropConnector(QObject *sender, QObject *receiver, QString senderProp, QString receiverProp) : 
     QObject(sender) 
     ,_sender(sender) 
     ,_receiver(receiver) 
     ,_senderProp(senderProp) 
     ,_receiverProp(receiverProp) 
    { 
     // Is it possible to get the proper property-changed notifier signal? 
     //connect(sender, SIGNAL(on<PROPERTY>Changed()), this, SLOT(forward)); 
    } 

private slots: 
    void forward() 
    { 
     _receiver->setProperty(receiverProp, _sender->property(senderProp)); 
    } 
}; 

Единственная проблема в том, как я могу открыть собственное имя сигнала для имени свойства Я хочу, чтобы слушать? Я думаю, это возможно, но я до сих пор не узнал, прочитав метаобъектную документацию.

Редактировать: С предложением Кевина я смог реализовать класс.

propconnector.h

#ifndef PROPCONNECTOR_H 
#define PROPCONNECTOR_H 

#include <QObject> 
#include <QString> 

class PropConnector : public QObject 
{ 
    Q_OBJECT 
private: 
    QObject *_sender; 
    QObject *_receiver; 
    QString _senderProperty; 
    QString _receiverProperty; 
public: 
    PropConnector(QObject *sender, QString senderProperty, QObject *receiver, QString receiverProperty); 

private slots: 
    void forward(); 
}; 

#endif // PROPCONNECTOR_H 

propconnector.cpp

#include "propconnector.h" 
#include <QMetaObject> 
#include <QMetaProperty> 

PropConnector::PropConnector(QObject *sender, QString senderProperty, QObject *receiver, QString receiverProperty) : 
    QObject(sender) 
    ,_sender(sender) 
    ,_receiver(receiver) 
    ,_senderProperty(senderProperty) 
    ,_receiverProperty(receiverProperty) 
{ 
    const QMetaObject *senderMeta = sender->metaObject(); 
    const int index = senderMeta->indexOfProperty(senderProperty.toUtf8().constData()); 
    if (index != -1) { 
     const QMetaProperty p = senderMeta->property(index); 
     if (p.hasNotifySignal()) { 
      const QMetaMethod s = p.notifySignal(); 

      QString sig = QString("2%1").arg(s.signature()); 
      const char *ssig = SLOT(forward()); 
      bool ok = connect(sender, sig.toStdString().c_str() , this, SLOT(forward())); 
      int i=0; 
      i++; 
     } 
    }  
} 

void PropConnector::forward() 
{ 
    _receiver->setProperty(_receiverProperty.toStdString().c_str(), _sender->property(_senderProperty.toStdString().c_str())); 
} 

ответ

2

Вы можете получить эту информацию от QMetaProperty

QMetaObject *senderMeta = sender->metaObject(); 
const int index = senderMeta->indexOfProperty(senderProperty.toUtf8().constData()); 
if (index != -1) { 
    const QMetaProperty property = senderMeta->property(index); 
    if (property.hasNotifySignal) { 
     const QMetaMethod notifySignal = property.notifySignal(); 

     connect(sender, notifySignal, receiver, metaMethodOfSlot);  
    } 
} 

Непроверено, не может скомпилировать. metaMethodOfSlot будет QMetaMethod для слота приемника, получите это аналогичным образом.

+0

Прохладный, это помогло. Сигнал приемника не важен, так как соединение имеет только одно направление. Сигнал запускается из самого класса соединителя. Я разместил код в вопросе-редактировании. –