-void SignalProxy::dataAvailable() {
- QIODevice* ioDev = qobject_cast<QIODevice* >(sender());
- Q_ASSERT(ioDev);
- if(!_peerByteCount.contains(ioDev)) {
- qWarning() << "SignalProxy: Unrecognized client object connected to dataAvailable";
- return;
- } else {
- QVariant var;
- while(readDataFromDevice(ioDev, _peerByteCount[ioDev], var))
- receivePeerSignal(var);
- }
-}
-
-void SignalProxy::writeDataToDevice(QIODevice *dev, const QVariant &item) {
- QAbstractSocket* sock = qobject_cast<QAbstractSocket*>(dev);
- if(!dev->isOpen() || (sock && sock->state()!=QAbstractSocket::ConnectedState)) {
- qWarning("SignalProxy: Can't call on a closed device");
- return;
- }
- QByteArray block;
- QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_2);
- out << (quint32)0 << item;
- out.device()->seek(0);
- out << (quint32)(block.size() - sizeof(quint32));
- dev->write(block);
-}
-
-bool SignalProxy::readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item) {
- QDataStream in(dev);
- in.setVersion(QDataStream::Qt_4_2);
-
- if(blockSize == 0) {
- if(dev->bytesAvailable() < (int)sizeof(quint32)) return false;
- in >> blockSize;
- }
-
- if(dev->bytesAvailable() < blockSize)
- return false;
- in >> item;
- blockSize = 0;
- return true;
+void SignalProxy::restrictTargetPeers(QSet<Peer*> peers, std::function<void()> closure)
+{
+ auto previousRestrictMessageTarget = _restrictMessageTarget;
+ auto previousRestrictedTargets = _restrictedTargets;
+ _restrictMessageTarget = true;
+ _restrictedTargets = peers;
+
+ closure();
+
+ _restrictMessageTarget = previousRestrictMessageTarget;
+ _restrictedTargets = previousRestrictedTargets;
+}
+
+Peer* SignalProxy::sourcePeer()
+{
+ return _sourcePeer;
+}
+
+void SignalProxy::setSourcePeer(Peer* sourcePeer)
+{
+ _sourcePeer = sourcePeer;
+}
+
+Peer* SignalProxy::targetPeer()
+{
+ return _targetPeer;
+}
+
+void SignalProxy::setTargetPeer(Peer* targetPeer)
+{
+ _targetPeer = targetPeer;
+}
+
+// ---- SlotObjectBase ---------------------------------------------------------------------------------------------------------------------
+
+SignalProxy::SlotObjectBase::SlotObjectBase(const QObject* context)
+ : _context{context}
+{}
+
+const QObject* SignalProxy::SlotObjectBase::context() const
+{
+ return _context;
+}
+
+// ---- ExtendedMetaObject ----------------------------------------------------------------------------------------------------------------
+
+SignalProxy::ExtendedMetaObject::ExtendedMetaObject(const QMetaObject* meta, bool checkConflicts)
+ : _meta(meta)
+ , _updatedRemotelyId(_meta->indexOfSignal("updatedRemotely()"))
+{
+ for (int i = 0; i < _meta->methodCount(); i++) {
+ if (_meta->method(i).methodType() != QMetaMethod::Slot)
+ continue;
+
+ if (_meta->method(i).methodSignature().contains('*'))
+ continue; // skip methods with ptr params
+
+ QByteArray method = methodName(_meta->method(i));
+ if (method.startsWith("init"))
+ continue; // skip initializers
+
+ if (_methodIds.contains(method)) {
+ /* funny... moc creates for methods containing default parameters multiple metaMethod with separate methodIds.
+ we don't care... we just need the full fledged version
+ */
+ const QMetaMethod& current = _meta->method(_methodIds[method]);
+ const QMetaMethod& candidate = _meta->method(i);
+ if (current.parameterTypes().count() > candidate.parameterTypes().count()) {
+ int minCount = candidate.parameterTypes().count();
+ QList<QByteArray> commonParams = current.parameterTypes().mid(0, minCount);
+ if (commonParams == candidate.parameterTypes())
+ continue; // we already got the full featured version
+ }
+ else {
+ int minCount = current.parameterTypes().count();
+ QList<QByteArray> commonParams = candidate.parameterTypes().mid(0, minCount);
+ if (commonParams == current.parameterTypes()) {
+ _methodIds[method] = i; // use the new one
+ continue;
+ }
+ }
+ if (checkConflicts) {
+ qWarning() << "class" << meta->className() << "contains overloaded methods which is currently not supported!";
+ qWarning() << " - " << _meta->method(i).methodSignature() << "conflicts with"
+ << _meta->method(_methodIds[method]).methodSignature();
+ }
+ continue;
+ }
+ _methodIds[method] = i;
+ }
+}
+
+const SignalProxy::ExtendedMetaObject::MethodDescriptor& SignalProxy::ExtendedMetaObject::methodDescriptor(int methodId)
+{
+ if (!_methods.contains(methodId)) {
+ _methods[methodId] = MethodDescriptor(_meta->method(methodId));
+ }
+ return _methods[methodId];
+}
+
+const QHash<int, int>& SignalProxy::ExtendedMetaObject::receiveMap()
+{
+ if (_receiveMap.isEmpty()) {
+ QHash<int, int> receiveMap;
+
+ QMetaMethod requestSlot;
+ QByteArray returnTypeName;
+ QByteArray signature;
+ QByteArray methodName;
+ QByteArray params;
+ int paramsPos;
+ int receiverId;
+ const int methodCount = _meta->methodCount();
+ for (int i = 0; i < methodCount; i++) {
+ requestSlot = _meta->method(i);
+ if (requestSlot.methodType() != QMetaMethod::Slot)
+ continue;
+
+ returnTypeName = requestSlot.typeName();
+ if (QMetaType::Void == (QMetaType::Type)returnType(i))
+ continue;
+
+ signature = requestSlot.methodSignature();
+ if (!signature.startsWith("request"))
+ continue;
+
+ paramsPos = signature.indexOf('(');
+ if (paramsPos == -1)
+ continue;
+
+ methodName = signature.left(paramsPos);
+ params = signature.mid(paramsPos);
+
+ methodName = methodName.replace("request", "receive");
+ params = params.left(params.count() - 1) + ", " + returnTypeName + ")";
+
+ signature = QMetaObject::normalizedSignature(methodName + params);
+ receiverId = _meta->indexOfSlot(signature);
+
+ if (receiverId == -1) {
+ signature = QMetaObject::normalizedSignature(methodName + "(" + returnTypeName + ")");
+ receiverId = _meta->indexOfSlot(signature);
+ }
+
+ if (receiverId != -1) {
+ receiveMap[i] = receiverId;
+ }
+ }
+ _receiveMap = receiveMap;
+ }
+ return _receiveMap;
+}
+
+QByteArray SignalProxy::ExtendedMetaObject::methodName(const QMetaMethod& method)
+{
+ QByteArray sig(method.methodSignature());
+ return sig.left(sig.indexOf("("));
+}
+
+QString SignalProxy::ExtendedMetaObject::methodBaseName(const QMetaMethod& method)
+{
+ QString methodname = QString(method.methodSignature()).section("(", 0, 0);
+
+ // determine where we have to chop:
+ int upperCharPos;
+ if (method.methodType() == QMetaMethod::Slot) {
+ // we take evertyhing from the first uppercase char if it's slot
+ upperCharPos = methodname.indexOf(QRegExp("[A-Z]"));
+ if (upperCharPos == -1)
+ return QString();
+ methodname = methodname.mid(upperCharPos);
+ }
+ else {
+ // and if it's a signal we discard everything from the last uppercase char
+ upperCharPos = methodname.lastIndexOf(QRegExp("[A-Z]"));
+ if (upperCharPos == -1)
+ return QString();
+ methodname = methodname.left(upperCharPos);
+ }
+
+ methodname[0] = methodname[0].toUpper();
+
+ return methodname;
+}
+
+SignalProxy::ExtendedMetaObject::MethodDescriptor::MethodDescriptor(const QMetaMethod& method)
+ : _methodName(SignalProxy::ExtendedMetaObject::methodName(method))
+ , _returnType(QMetaType::type(method.typeName()))
+{
+ // determine argTypes
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<int> argTypes;
+ for (int i = 0; i < paramTypes.count(); i++) {
+ argTypes.append(QMetaType::type(paramTypes[i]));
+ }
+ _argTypes = argTypes;
+
+ // determine minArgCount
+ QString signature(method.methodSignature());
+ _minArgCount = method.parameterTypes().count() - signature.count("=");
+
+ _receiverMode = (_methodName.startsWith("request")) ? SignalProxy::Server : SignalProxy::Client;