Testing the new SyncObjects concept - looking good so far
[quassel.git] / src / common / signalproxy.h
index 584626e..7f2a1dd 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -31,7 +31,6 @@
 #include <QByteArray>
 #include <QTimer>
 
-class SignalRelay;
 class SyncableObject;
 struct QMetaObject;
 
@@ -42,6 +41,8 @@ class SignalProxy : public QObject {
   class IODevicePeer;
   class SignalProxyPeer;
 
+  class SignalRelay;
+
 public:
   enum ProxyMode {
     Server,
@@ -85,13 +86,6 @@ public:
 
   void synchronize(SyncableObject *obj);
 
-//   void setInitialized(SyncableObject *obj);
-//   bool isInitialized(SyncableObject *obj) const;
-  void detachObject(QObject *obj);
-  void detachSignals(QObject *sender);
-  void detachSlots(QObject *receiver);
-  void stopSync(SyncableObject *obj);
-
   //! Writes a QVariant to a device.
   /** The data item is prefixed with the resulting blocksize,
    *  so the corresponding function readDataFromDevice() can check if enough data is available
@@ -106,18 +100,26 @@ public:
   static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed = false);
 
   class ExtendedMetaObject;
-  ExtendedMetaObject *extendedMetaObject(const QObject *obj) const;
-  void createExtendedMetaObject(const QObject *obj);
+  ExtendedMetaObject *extendedMetaObject(const QMetaObject *meta) const;
+  ExtendedMetaObject *createExtendedMetaObject(const QMetaObject *meta);
+  inline ExtendedMetaObject *extendedMetaObject(const QObject *obj) const { return extendedMetaObject(metaObject(obj)); }
+  inline ExtendedMetaObject *createExtendedMetaObject(const QObject *obj) { return createExtendedMetaObject(metaObject(obj)); }
 
   bool isSecure() const { return _secure; }
   void dumpProxyStats();
 
+public slots:
+  void detachObject(QObject *obj);
+  void detachSignals(QObject *sender);
+  void detachSlots(QObject *receiver);
+  void stopSync(QObject *obj);
+
 protected:
   void customEvent(QEvent *event);
+  void syncCall(const SyncableObject *obj, ProxyMode modeType, const char *funcname, va_list ap);
 
 private slots:
   void dataAvailable();
-  void detachSender();
   void removePeerBySender();
   void objectRenamed(const QString &newname, const QString &oldname);
   void objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname);
@@ -178,8 +180,8 @@ private:
   // containg a list of argtypes for fast access
   QHash<const QMetaObject *, ExtendedMetaObject *> _extendedMetaObjects;
 
-  // we use one SignalRelay per QObject
-  QHash<QObject*, SignalRelay *> _relayHash;
+  // SignalRelay for all manually attached signals
+  SignalRelay *_signalRelay;
 
   // RPC function -> (object, slot ID)
   typedef QPair<QObject*, int> MethodId;
@@ -197,6 +199,7 @@ private:
   bool _secure; // determines if all connections are in a secured state (using ssl or internal connections)
 
   friend class SignalRelay;
+  friend class SyncableObject;
 };
 
 
@@ -204,33 +207,55 @@ private:
 //  ExtendedMetaObject
 // ==================================================
 class SignalProxy::ExtendedMetaObject {
+  class MethodDescriptor {
+  public:
+    MethodDescriptor(const QMetaMethod &method);
+    MethodDescriptor() : _returnType(-1), _minArgCount(-1), _receiverMode(SignalProxy::Client) {}
+
+    inline const QByteArray &methodName() const { return _methodName; }
+    inline const QList<int> &argTypes() const { return _argTypes; }
+    inline int returnType() const { return _returnType; }
+    inline int minArgCount() const { return _minArgCount; }
+    inline SignalProxy::ProxyMode receiverMode() const { return _receiverMode; }
+
+  private:
+    QByteArray _methodName;
+    QList<int> _argTypes;
+    int _returnType;
+    int _minArgCount;
+    SignalProxy::ProxyMode _receiverMode; // Only acceptable as a Sync Call if the receiving SignalProxy is in this mode.
+  };
+
 public:
   ExtendedMetaObject(const QMetaObject *meta);
 
-  const QList<int> &argTypes(int methodId);
-  const int &returnType(int methodId);
-  const int &minArgCount(int methodId);
-  const QByteArray &methodName(int methodId);
-  const QHash<QByteArray, int> &syncMap();
+  inline const QByteArray &methodName(int methodId) { return methodDescriptor(methodId).methodName(); }
+  inline const QList<int> &argTypes(int methodId) { return methodDescriptor(methodId).argTypes(); }
+  inline int returnType(int methodId) { return methodDescriptor(methodId).returnType(); }
+  inline int minArgCount(int methodId) { return methodDescriptor(methodId).minArgCount(); }
+  inline SignalProxy::ProxyMode receiverMode(int methodId) { return methodDescriptor(methodId).receiverMode(); }
+
+  inline int methodId(const QByteArray &methodName) { return _methodIds.contains(methodName) ? _methodIds[methodName] : -1; }
+
+  inline int updatedRemotelyId() { return _updatedRemotelyId; }
+  
+  inline const QHash<QByteArray, int> &slotMap() { return _methodIds; }
   const QHash<int, int> &receiveMap();
-  int updatedRemotelyId();
+
+  const QMetaObject *metaObject() const { return _meta; }
 
   static QByteArray methodName(const QMetaMethod &method);
-  static bool methodsMatch(const QMetaMethod &signal, const QMetaMethod &slot);
-  static QString methodBaseName(const QMetaMethod &method);
+  static QString ExtendedMetaObject::methodBaseName(const QMetaMethod &method);
 
 private:
-  typedef QHash<int, QList<int> > ArgHash;
-  typedef QHash<int, QByteArray> MethodNameHash;
+  const MethodDescriptor &methodDescriptor(int methodId);
 
   const QMetaObject *_meta;
-  ArgHash _argTypes;
-  QHash<int, int> _returnType;
-  QHash<int, int> _minArgCount;
-  MethodNameHash _methodNames;
   int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster
-  QHash<QByteArray, int> _syncMap;
-  QHash<int, int> _receiveMap;
+
+  QHash<int, MethodDescriptor> _methods;
+  QHash<QByteArray, int> _methodIds;
+  QHash<int, int> _receiveMap; // if slot x is called then hand over the result to slot y
 };