X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;f=src%2Fcommon%2Fsynchronizer.cpp;fp=src%2Fcommon%2Fsynchronizer.cpp;h=0000000000000000000000000000000000000000;hb=a7f5d6a23f7214b11f6db85346a67fd7d02767da;hp=e2bed3342dd9ca4b47f21fe14d3d82b03fe9c55c;hpb=1956aab57bf98ce072ed86f34785e5d7abba35a0;p=quassel.git diff --git a/src/common/synchronizer.cpp b/src/common/synchronizer.cpp deleted file mode 100644 index e2bed334..00000000 --- a/src/common/synchronizer.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005-07 by The Quassel Team * - * devel@quassel-irc.org * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "synchronizer.h" - -#include -#include -#include -#include - -#include "util.h" -#include "signalproxy.h" - -#include -#include - -// ==================== -// Public: -// ==================== -Synchronizer::Synchronizer(QObject *parent, SignalProxy *signalproxy) - : QObject(parent), - _initialized(false), - _signalproxy(signalproxy) -{ - attach(); - if(!getMethodByName("objectNameSet()").isEmpty()) - connect(parent,SIGNAL(objectNameSet()), this, SLOT(parentChangedName())); -} - -bool Synchronizer::initialized() const { - return _initialized; -} - -SignalProxy *Synchronizer::proxy() const { - return _signalproxy; -} - -QVariantMap Synchronizer::initData() const { - QVariantMap properties; - - // we collect data from properties - foreach(QMetaProperty property, parentProperties()) { - QString name = QString(property.name()); - QVariant value = property.read(parent()); - properties[name] = value; - // qDebug() << ">>> SYNC:" << name << value; - } - - // ...as well as methods, which have names starting with "init" - foreach(QMetaMethod method, parentSlots()) { - QString methodname = QString(method.signature()).section("(", 0, 0); - if(methodname.startsWith("initSet") || - !methodname.startsWith("init")) - continue; - - QVariant value = QVariant(QVariant::nameToType(method.typeName())); - QGenericReturnArgument genericvalue = QGenericReturnArgument(method.typeName(), &value); - QMetaObject::invokeMethod(parent(), methodname.toAscii(), genericvalue); - - properties[methodBaseName(method)] = value; - // qDebug() << ">>> SYNC:" << methodBaseName(method) << value; - } - - // properties["Payload"] = QByteArray(10000000, 'a'); // for testing purposes - return properties; -} - -void Synchronizer::setInitData(const QVariantMap &properties) { - if(initialized()) - return; - - const QMetaObject *metaobject = parent()->metaObject(); - QMapIterator iterator(properties); - while(iterator.hasNext()) { - iterator.next(); - QString name = iterator.key(); - int propertyIndex = metaobject->indexOfProperty(name.toAscii()); - if(propertyIndex == -1) { - setInitValue(name, iterator.value()); - } else { - if((metaobject->property(propertyIndex)).isWritable()) - parent()->setProperty(name.toAscii(), iterator.value()); - else - setInitValue(name, iterator.value()); - } - // qDebug() << "<<< SYNC:" << name << iterator.value(); - } - - _initialized = true; - emit initDone(); -} - -// ==================== -// Public Slots -// ==================== -void Synchronizer::synchronizeClients() const { - emit sendInitData(initData()); -} - -void Synchronizer::recvInitData(QVariantMap properties) { - proxy()->detachObject(this); - setInitData(properties); -} - -void Synchronizer::parentChangedName() { - proxy()->detachObject(parent()); - proxy()->detachObject(this); - attach(); -} - -// ==================== -// Private -// ==================== -QString Synchronizer::signalPrefix() const { - return QString(parent()->metaObject()->className()) + "_" + QString(parent()->objectName()) + "_"; -} - -QString Synchronizer::initSignal() const { - return QString(metaObject()->className()) - + "_" + QString(parent()->metaObject()->className()) - + "_" + QString(parent()->objectName()) - + "_" + QString(SIGNAL(sendInitData(QVariantMap))); -} - -QString Synchronizer::requestSyncSignal() const { - return QString(metaObject()->className()) - + "_" + QString(parent()->metaObject()->className()) - + "_" + QString(parent()->objectName()) - + "_" + QString(SIGNAL(requestSync())); -} - -QString Synchronizer::methodBaseName(const QMetaMethod &method) const { - QString methodname = QString(method.signature()).section("(", 0, 0); - - // determine where we have to chop: - if(method.methodType() == QMetaMethod::Slot) { - // we take evertyhing from the first uppercase char if it's slot - methodname = methodname.mid(methodname.indexOf(QRegExp("[A-Z]"))); - } else { - // and if it's a signal we discard everything from the last uppercase char - methodname = methodname.left(methodname.lastIndexOf(QRegExp("[A-Z]"))); - } - - methodname[0] = methodname[0].toUpper(); - - return methodname; -} - -bool Synchronizer::methodsMatch(const QMetaMethod &signal, const QMetaMethod &slot) const { - // if we don't even have the same basename it's a sure NO - if(methodBaseName(signal) != methodBaseName(slot)) - return false; - - const QMetaObject *metaobject = parent()->metaObject(); - - // are the signatures compatible? - if(! metaobject->checkConnectArgs(signal.signature(), slot.signature())) - return false; - - // we take an educated guess if the signals and slots match - QString signalsuffix = QString(signal.signature()).section("(", 0, 0); - signalsuffix = signalsuffix.mid(signalsuffix.lastIndexOf(QRegExp("[A-Z]"))).toLower(); - - QString slotprefix = QString(slot.signature()).section("(", 0, 0); - slotprefix = slotprefix.left(slotprefix.indexOf(QRegExp("[A-Z]"))).toLower(); - - uint sizediff; - if(signalsuffix.size() < slotprefix.size()) - sizediff = slotprefix.size() - signalsuffix.size(); - else - sizediff = signalsuffix.size() - slotprefix.size(); - - int ratio = editingDistance(slotprefix, signalsuffix) - sizediff; - - return (ratio < 2); -} - -QList Synchronizer::parentProperties() const { - QList _properties; - - const QMetaObject *metaobject = parent()->metaObject(); - for(int i = metaobject->propertyOffset(); i < metaobject->propertyCount(); i++) { - _properties << metaobject->property(i); - } - - return _properties; -} - -QList Synchronizer::parentSlots() const { - QList _slots; - - const QMetaObject *metaobject = parent()->metaObject(); - for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) { - QMetaMethod method = metaobject->method(i); - if(method.methodType() == QMetaMethod::Slot) - _slots << method; - } - - return _slots; -} - - -QList Synchronizer::parentSignals() const { - QList _signals; - - const QMetaObject *metaobject = parent()->metaObject(); - for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) { - QMetaMethod method = metaobject->method(i); - if(method.methodType() == QMetaMethod::Signal) - _signals << method; - } - - return _signals; -} - -QList Synchronizer::getMethodByName(const QString &methodname) { - QList _methods; - - const QMetaObject* metaobject = parent()->metaObject(); - for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) { - if(QString(metaobject->method(i).signature()).startsWith(methodname)) - _methods << metaobject->method(i); - } - - return _methods; -} - -void Synchronizer::attach() { - if(proxy()->proxyMode() == SignalProxy::Server) - attachAsMaster(); - else - attachAsSlave(); -} - -void Synchronizer::attachAsSlave() { - QList signals_ = parentSignals(); - - foreach(QMetaMethod slot, parentSlots()) { - if(signals_.empty()) - break; - - for(int i = 0; i < signals_.count(); i++) { - QMetaMethod signal = signals_[i]; - if(!methodsMatch(signal, slot)) - continue; - - // we could simply put a "1" in front of the normalized signature - // but to guarantee future compatibility we construct a dummy signal - // and replace the known the fake signature by ours... - QString dummySlot = QString(SIGNAL(dummy())); - QString proxySignal = signalPrefix() + QString(signal.signature()); - QString slotsignature = dummySlot.replace("dummy()", QString(slot.signature())); - - // qDebug() << "attachSlot:" << proxySignal << slotsignature; - proxy()->attachSlot(proxySignal.toAscii(), parent(), slotsignature.toAscii()); - signals_.removeAt(i); - break; - } - } - - if(!getMethodByName("setInitialized()").isEmpty()) - connect(this, SIGNAL(initDone()), parent(), SLOT(setInitialized())); - - if(!initialized()) { - // and then we connect ourself, so we can receive init data - // qDebug() << "attachSlot:" << initSignal() << "recvInitData(QVariantMap)"; - // qDebug() << "attachSignal:" << "requestSync()" << requestSyncSignal(); - proxy()->attachSlot(initSignal().toAscii(), this, SLOT(recvInitData(QVariantMap))); - proxy()->attachSignal(this, SIGNAL(requestSync()), requestSyncSignal().toAscii()); - - emit requestSync(); - } -} - -void Synchronizer::attachAsMaster() { - QList slots_ = parentSlots(); - - foreach(QMetaMethod signal, parentSignals()) { - if(slots_.isEmpty()) - break; - - // we don't attach all signals, just the ones that have a maching counterpart - for(int i = 0; i < slots_.count(); i++) { - QMetaMethod slot = slots_[i]; - if(!methodsMatch(signal, slot)) - continue; - - // we could simply put a "2" in front of the normalized signature - // but to guarantee future compatibility we construct a dummy signal - // and replace the known the fake signature by ours... - QString dummySignal = QString(SIGNAL(dummy())); - QString proxySignal = signalPrefix() + QString(signal.signature()); - QString signalsignature = dummySignal.replace("dummy()", QString(signal.signature())); - - // qDebug() << "attachSignal:" << signalsignature << proxySignal; - proxy()->attachSignal(parent(), signalsignature.toAscii(), proxySignal.toAscii()); - slots_.removeAt(i); - break; - } - } - - // and then we connect ourself, so we can initialize slaves - // qDebug() << "attachSignal:" << "sendInitData(QVariantMap)" << initSignal(); - // qDebug() << "attachSlot:" << "synchronizeClients()" << requestSyncSignal(); - proxy()->attachSignal(this, SIGNAL(sendInitData(QVariantMap)), initSignal().toAscii()); - proxy()->attachSlot(requestSyncSignal().toAscii(), this, SLOT(synchronizeClients())); -} - -bool Synchronizer::setInitValue(const QString &property, const QVariant &value) { - QString handlername = QString("initSet") + property; - handlername[7] = handlername[7].toUpper(); - - //determine param type - QByteArray paramtype; - foreach(QMetaMethod method, getMethodByName(handlername)) { - if(method.parameterTypes().size() == 1) { - paramtype = method.parameterTypes()[0]; - break; - } - } - - if(paramtype.isNull()) - return false; - - QGenericArgument param = QGenericArgument(paramtype, &value); - return QMetaObject::invokeMethod(parent(), handlername.toAscii(), param); -} - -