Make SignalProxy detach QObjects automatically upon their destruction.
[quassel.git] / src / common / signalproxy.cpp
index bd12b15..763daf6 100644 (file)
@@ -31,6 +31,7 @@ SignalProxy::SignalProxy(ProxyType _type, QIODevice *dev, QObject *parent) : QOb
 }
 
 SignalProxy::~SignalProxy() {
+  //qDebug() << "peers:" << peers.count();
   foreach(Connection conn, peers) {
     conn.peer->deleteLater(); conn.device->deleteLater();
   }
@@ -44,6 +45,7 @@ void SignalProxy::addPeer(QIODevice *dev) {
   Connection conn;
   conn.device = dev;
   conn.peer = new QxtRPCPeer(dev, QxtRPCPeer::Peer, this);
+  connect(conn.peer, SIGNAL(peerDisconnected()), this, SLOT(socketDisconnected()));
 
   foreach(SlotDesc slot, attachedSlots) {
     conn.peer->attachSlot(slot.rpcFunction, slot.recv, slot.slot);
@@ -55,15 +57,34 @@ void SignalProxy::addPeer(QIODevice *dev) {
 
 }
 
+void SignalProxy::socketDisconnected() {
+  for(int i = 0; i < peers.count(); i++) {
+    Connection conn = peers[i];
+    QAbstractSocket *sock = qobject_cast<QAbstractSocket*>(conn.device);
+    if(!sock) continue;
+    if(sock->state() == QAbstractSocket::UnconnectedState) {
+      peers[i].peer->deleteLater(); peers[i].device->deleteLater();
+      peers.removeAt(i);
+      emit peerDisconnected();
+      i--;
+    }
+  }
+}
+
 void SignalProxy::attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction) {
+  disconnect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+  connect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+
   foreach(Connection conn, peers) {
     conn.peer->attachSignal(sender, signal, rpcFunction);
   }
   attachedSignals.append(SignalDesc(sender, signal, rpcFunction));
-
 }
 
 void SignalProxy::attachSlot(const QByteArray& rpcFunction, QObject* recv, const char* slot) {
+  disconnect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+  connect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+
   foreach(Connection conn, peers) {
     conn.peer->attachSlot(rpcFunction, recv, slot);
   }
@@ -71,11 +92,26 @@ void SignalProxy::attachSlot(const QByteArray& rpcFunction, QObject* recv, const
 }
 
 void SignalProxy::detachObject(QObject* obj) {
-  Q_ASSERT(false); // not done yet
+  //Q_ASSERT(false); // not done yet
   foreach(Connection conn, peers) {
     conn.peer->detachObject(obj);
   }
-  // FIXME: delete attached signal/slot info
+  QList<SignalDesc> sigs;
+  foreach(SignalDesc desc, attachedSignals) {
+    if(desc.sender != obj) sigs << desc;
+  }
+  attachedSignals = sigs;
+  QList<SlotDesc> slot;
+  foreach(SlotDesc desc, attachedSlots) {
+    if(desc.recv != obj) slot << desc;
+  }
+  attachedSlots = slot;
+  // FIXME: test this!
+}
 
+void SignalProxy::sendSignal(const char *signal, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) {
+  foreach(Connection conn, peers) {
+    conn.peer->call(signal, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+  }
 }