| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 | /* *  ctkEventDispatcher.cpp *  ctkEventBus * *  Created by Paolo Quadrani on 27/03/09. *  Copyright 2009 B3C. All rights reserved. * *  See Licence at: http://tiny.cc/QXJ4D * */#include "ctkEventDispatcher.h"#include "ctkBusEvent.h"#define CALLBACK_SIGNATURE "1"#define SIGNAL_SIGNATURE   "2"using namespace ctkEventBus;ctkEventDispatcher::ctkEventDispatcher() {}ctkEventDispatcher::~ctkEventDispatcher() {}bool ctkEventDispatcher::isLocalSignalPresent(const QString topic) const {    return m_SignalsHash.values(topic).size() != 0;}void ctkEventDispatcher::resetHashes() {    // delete all lists present into the hash.    QHash<QString, ctkBusEvent *>::iterator i;    for (i = m_CallbacksHash.begin(); i != m_CallbacksHash.end(); ++i) {        delete i.value();    }    m_CallbacksHash.clear();    for (i = m_SignalsHash.begin(); i != m_SignalsHash.end(); ++i) {        delete i.value();    }    m_SignalsHash.clear();}void ctkEventDispatcher::initializeGlobalEvents() {    ctkBusEvent *remote_done = new ctkBusEvent("ctk/local/eventBus/remoteCommunicationDone",ctkEventTypeLocal,ctkSignatureTypeSignal,this,"remoteCommunicationDone()");    /*QString eventId = "ctk/local/eventBus/remoteCommunicationDone";    (*remote_done)[TOPIC] = eventId;    (*remote_done)[TYPE] = ctkEventTypeLocal;    (*remote_done)[SIGTYPE] = mafSignatureTypeSignal;    QVariant var;    var.setValue((QObject*)this);    (*remote_done)[OBJECT] = var;    (*remote_done)[SIGNATURE] = "remoteCommunicationDone()";*/    this->registerSignal(*remote_done);    ctkBusEvent *remote_failed = new ctkBusEvent("ctk/local/eventBus/remoteCommunicationFailed",ctkEventTypeLocal,ctkSignatureTypeSignal,this, "remoteCommunicationFailed()");    /*(*remote_failed)[TOPIC] = "ctk/local/eventBus/remoteCommunicationFailed";    (*remote_failed)[TYPE] = ctkEventTypeLocal;    (*remote_failed)[SIGTYPE] = mafSignatureTypeSignal;    var.setValue((QObject*)this);    (*remote_failed)[OBJECT] = var;    (*remote_failed)[SIGNATURE] = "remoteCommunicationFailed()";*/    this->registerSignal(*remote_failed);}bool ctkEventDispatcher::isSignaturePresent(ctkBusEvent &props) const {    QString topic = props[TOPIC].toString();    ctkEventItemListType itemEventPropList;    ctkBusEvent *itemEventProp;    if(props[SIGTYPE].toInt() == ctkSignatureTypeCallback) {        itemEventPropList = m_CallbacksHash.values(topic);    } else {        itemEventPropList = m_SignalsHash.values(topic);    }    QObject *objParameter = props[OBJECT].value<QObject *>();    foreach(itemEventProp, itemEventPropList) {        QObject *objInList = (*itemEventProp)[OBJECT].value<QObject *>();        if(objInList == objParameter && (*itemEventProp)[SIGNATURE].toString() == props[SIGNATURE].toString()) {            return true;        }    }    return false;}bool ctkEventDispatcher::disconnectSignal(ctkBusEvent &props) {    QObject *obj_signal = props[OBJECT].value<QObject*>();    QString sig = props[SIGNATURE].toString();    QString event_sig = SIGNAL_SIGNATURE;    event_sig.append(sig);    bool result = obj_signal->disconnect(obj_signal, event_sig.toAscii(), 0, 0);    return result;}bool ctkEventDispatcher::disconnectCallback(ctkBusEvent &props) {    //need to disconnect observer from the signal    QString observer_sig = CALLBACK_SIGNATURE;    observer_sig.append(props[SIGNATURE].toString());    ctkBusEvent *itemSignal = m_SignalsHash.value(props[TOPIC].toString());    QString event_sig = SIGNAL_SIGNATURE;    event_sig.append((*itemSignal)[SIGNATURE].toString());    QObject *objSignal = (*itemSignal)[OBJECT].value<QObject *>();    QObject *objSlot = props[OBJECT].value<QObject *>();    return disconnect(objSignal, event_sig.toAscii(), objSlot, observer_sig.toAscii());}bool ctkEventDispatcher::removeEventItem(ctkBusEvent &props) {    bool isDisconnected = false;    bool isPresent = isSignaturePresent(props);    if(isPresent == true) {        //ctkEventItemListType itemEventPropList;        if(props[SIGTYPE].toInt() == ctkSignatureTypeCallback) {            isDisconnected = disconnectCallback(props);            //iterator for erasing hash entry            ctkEventsHashType::iterator i = m_CallbacksHash.find(props[TOPIC].toString());            while (i != m_CallbacksHash.end() && i.key() == props[TOPIC]) {                QObject *obj = (*(i.value()))[OBJECT].value<QObject *>();                QObject *objCheck = props[OBJECT].value<QObject *>();                if (obj == objCheck && (*(i.value()))[SIGNATURE].toString() == props[SIGNATURE].toString()) {                    delete i.value();                    i = m_CallbacksHash.erase(i);                } else {                    ++i;                }            }        } else {            //itemEventPropList = m_SignalsHash.values();            isDisconnected = disconnectSignal(props);            ctkEventsHashType::iterator i = m_CallbacksHash.find(props[TOPIC].toString());            while (i != m_CallbacksHash.end() && i.key() == props[TOPIC].toString()) {                delete i.value();                i++;            }            i = m_SignalsHash.find(props[TOPIC].toString());            while (i != m_SignalsHash.end() && i.key() == props[TOPIC].toString()) {                delete i.value();                i++;            }            m_SignalsHash.remove(props[TOPIC].toString()); //in signal hash the id is unique            m_CallbacksHash.remove(props[TOPIC].toString()); //remove also all the id associated in callback        }        //itemEventPropList.removeAt(idx);    }    return isDisconnected;}bool ctkEventDispatcher::addObserver(ctkBusEvent &props) {    QString topic = props[TOPIC].toString();    // check if the object has been already registered with the same signature to avoid duplicates.    if(m_CallbacksHash.contains(topic) && this->isSignaturePresent(props) == true) {        return false;    }    QVariant sigVariant = props[SIGNATURE];    QString sig = sigVariant.toString();    QObject *objSlot = props[OBJECT].value<QObject *>();    if(sig.length() > 0 && objSlot != NULL) {        ctkBusEvent *itemEventProp;        //bool testRes = this->isLocalSignalPresent(topic);        itemEventProp = m_SignalsHash.value(topic);        if(itemEventProp == NULL) {            qDebug() << tr("Signal not present for topic %1, create only the entry in CallbacksHash").arg(topic);            ctkBusEvent *dict = const_cast<ctkBusEvent *>(&props);            this->m_CallbacksHash.insertMulti(topic, dict);            return true;        }        QString observer_sig = CALLBACK_SIGNATURE;        observer_sig.append(props[SIGNATURE].toString());                QString event_sig = SIGNAL_SIGNATURE;        event_sig.append((*itemEventProp)[SIGNATURE].toString());                // Add the new observer to the Hash.        ctkBusEvent *dict = const_cast<ctkBusEvent *>(&props);        this->m_CallbacksHash.insertMulti(topic, dict);        QObject *objSignal = (*itemEventProp)[OBJECT].value<QObject *>();        return connect(objSignal, event_sig.toAscii(), objSlot, observer_sig.toAscii());    }        qDebug() << tr("Signal not valid for topic: %1").arg(topic);    QString objValid = objSlot ? "YES":"NO";    qDebug() << tr("Object valid Address: %1").arg(objValid);    qDebug() << tr("Signature: %1").arg(sig);    return false;}bool ctkEventDispatcher::removeObserver(const QObject *obj, const QString topic, bool qt_disconnect) {    if(obj == NULL) {        return false;    }    return removeFromHash(&m_CallbacksHash, obj, topic, qt_disconnect);}bool ctkEventDispatcher::removeSignal(const QObject *obj, const QString topic, bool qt_disconnect) {    if(obj == NULL) {        return false;    }    return removeFromHash(&m_SignalsHash, obj, topic, qt_disconnect);}bool ctkEventDispatcher::removeFromHash(ctkEventsHashType *hash, const QObject *obj, const QString topic, bool qt_disconnect) {    bool disconnectItem = true;    if(topic.length() > 0 && hash->contains(topic)) {        // Remove the observer from the given topic.        ctkEventsHashType::iterator i = hash->find(topic);        while(i != hash->end() && i.key() == topic) {            QObject *item = (*(i.value()))[OBJECT].value<QObject *>();            if(item == obj) {                ctkBusEvent *prop = i.value();                bool currentDisconnetFlag = false;                if(qt_disconnect) {                    if(*hash == m_CallbacksHash) {                        currentDisconnetFlag = disconnectCallback(*prop);                    } else {                        currentDisconnetFlag = disconnectSignal(*prop);                    }                } else {                    currentDisconnetFlag = true;                }                disconnectItem = disconnectItem && currentDisconnetFlag;                if(currentDisconnetFlag) {                    delete i.value();                    i = hash->erase(i);                } else {                    qDebug() << tr("Unable to disconnect object %1 on topic %2").arg(obj->objectName(), topic);                    ++i;                }            } else {                ++i;            }        }        return disconnectItem;    }    if(topic.isEmpty()) {        ctkEventsHashType::iterator i = hash->begin();        while(i != hash->end()) {            QObject *item = (*(i.value()))[OBJECT].value<QObject *>();            if(item == obj) {                ctkBusEvent *prop = i.value();                bool currentDisconnetFlag = false;                if(qt_disconnect) {                    if(*hash == m_CallbacksHash) {                        currentDisconnetFlag = disconnectCallback(*prop);                    } else {                        currentDisconnetFlag = disconnectSignal(*prop);                    }                } else {                    currentDisconnetFlag = true;                }                disconnectItem = disconnectItem && currentDisconnetFlag;                if(currentDisconnetFlag) {                    delete i.value();                    i = hash->erase(i);                } else {                    qDebug() << tr("Unable to disconnect object %1 from topic %2").arg(obj->objectName(), (*prop)[TOPIC].toString());                    ++i;                }            } else {                ++i;            }        }        return disconnectItem;    }    return false; //need to enter in one of the conditions}bool ctkEventDispatcher::removeObserver(ctkBusEvent &props) {    return removeEventItem(props);}bool ctkEventDispatcher::registerSignal(ctkBusEvent &props) {    // check if the object has been already registered with the same signature to avoid duplicates.    if(props["Signature"].toString().length() == 0) {        QVariant var;        var.setValue((QObject *)this);        props[OBJECT] = var;        props[SIGNATURE] = "notifyDefaultEvent()";    }    QString topic = props[TOPIC].toString();    // Check if a signal (corresponding to a mafID) already is present.    if(m_SignalsHash.contains(topic)) {// && (this->isSignaturePresent(signal_props) == true)) {        // Only one signal for a given id can be registered!!        QObject *obj = props[OBJECT].value<QObject *>();        if(obj != NULL) {            qWarning("%s", tr("Object %1 is trying to register a signal with Topic '%2' that has been already registered!!").arg(obj->metaObject()->className(), topic).toAscii().data());        } else {            qWarning("%s", tr("NULL is trying to register a signal with Topic '%2' that has been already registered!!").arg(topic).toAscii().data());        }        return false;    }    ctkEventItemListType itemEventPropList;    itemEventPropList = m_CallbacksHash.values(topic);    if(itemEventPropList.count() == 0) {        qDebug() << tr("Callbacks not present for topic %1, create only the entry in SignalsHash").arg(topic);        // Add the new signal to the Hash.        ctkBusEvent *dict = const_cast<ctkBusEvent *>(&props);        this->m_SignalsHash.insert(topic, dict);        return true;    }    QObject *objSignal = props[OBJECT].value<QObject *>();    QVariant sigVariant = props[SIGNATURE];    QString sig = sigVariant.toString();    ctkBusEvent *currentEvent;    bool cumulativeConnect = true;     if(sig.length() > 0 && objSignal != NULL) {         foreach(currentEvent, itemEventPropList) {             QString observer_sig = CALLBACK_SIGNATURE;             observer_sig.append((*currentEvent)[SIGNATURE].toString());             QString event_sig = SIGNAL_SIGNATURE;             event_sig.append(sig);             QObject *objSlot = (*currentEvent)[OBJECT].value<QObject *>();             cumulativeConnect = cumulativeConnect && connect(objSignal, event_sig.toAscii(), objSlot, observer_sig.toAscii());         }         ctkBusEvent *dict = const_cast<ctkBusEvent *>(&props);         this->m_SignalsHash.insert(topic, dict);    }    return cumulativeConnect;}bool ctkEventDispatcher::removeSignal(ctkBusEvent &props) {    return removeEventItem(props);}void ctkEventDispatcher::notifyEvent(ctkBusEvent &event_dictionary, ctkEventArgumentsList *argList, ctkGenericReturnArgument *returnArg) const {    Q_UNUSED(event_dictionary);    Q_UNUSED(argList);    Q_UNUSED(returnArg);}
 |