00001 /*
00002 Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
00003
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00018 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00019 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00020 */
00021
00022 #include <dcopserver.h>
00023 #include <dcopsignals.h>
00024
00025 template class QPtrList<DCOPSignalConnection>;
00026
00027 DCOPSignals::DCOPSignals()
00028 {
00029 connections.setAutoDelete(true);
00030 }
00031
00037 void
00038 DCOPSignals::emitSignal( DCOPConnection *conn, const QCString &_fun, const QByteArray &data, bool excludeSelf)
00039 {
00040 QCString senderObj;
00041 QCString fun = _fun;
00042 int i = fun.find('#');
00043 if (i > -1)
00044 {
00045 senderObj = fun.left(i);
00046 fun = fun.mid(i+1);
00047 }
00048
00049 DCOPSignalConnectionList *list = connections.find(fun);
00050 if (!list) return;
00051 for(DCOPSignalConnection *current = list->first(); current; current = list->next())
00052 {
00053 bool doSend = false;
00054 if (current->senderConn)
00055 {
00056 if (current->senderConn == conn)
00057 doSend = true;
00058 }
00059 else if (!current->sender.isEmpty())
00060 {
00061 if ((conn && current->sender == conn->appId) || (current->sender == "DCOPServer"))
00062 doSend = true;
00063 }
00064 else
00065 {
00066 doSend = true;
00067 }
00068
00069 if (!current->senderObj.isEmpty() &&
00070 (current->senderObj != senderObj))
00071 {
00072 doSend = false;
00073 }
00074
00075 if (excludeSelf && (conn == current->recvConn))
00076 doSend = false;
00077 if (doSend)
00078 {
00079 the_server->sendMessage(current->recvConn, conn ? conn->appId : QCString("DCOPServer"),
00080 current->recvConn->appId, current->recvObj,
00081 current->slot, data);
00082 }
00083 }
00084 }
00085
00096 bool
00097 DCOPSignals::connectSignal( const QCString &sender, const QCString &senderObj,
00098 const QCString &signal,
00099 DCOPConnection *conn, const QCString &receiverObj,
00100 const QCString &slot, bool Volatile)
00101 {
00102 // TODO: Check if signal and slot match
00103 QCString signalArgs, slotArgs;
00104 int i,j;
00105 i = signal.find('(');
00106 if (i < 0) return false;
00107 signalArgs = signal.mid(i+1);
00108 j = signalArgs.find(')');
00109 if (j < 0) return false;
00110 signalArgs.truncate(j);
00111 i = slot.find('(');
00112 if (i < 0) return false;
00113 slotArgs = slot.mid(i+1);
00114 j = slotArgs.find(')');
00115 if (j < 0) return false;
00116 slotArgs.truncate(j);
00117
00118 if(signalArgs != slotArgs)
00119 {
00120 // Maybe the signal has more arguments than the slot...
00121 if (signalArgs.length() <= slotArgs.length())
00122 return false;
00123 if ((slotArgs.length() > 0) && (signalArgs[slotArgs.length()] != ','))
00124 return false;
00125 if (signalArgs.left(slotArgs.length()) != slotArgs)
00126 return false;
00127 }
00128
00129 DCOPConnection *senderConn = 0;
00130 if (Volatile)
00131 {
00132 senderConn = the_server->findApp(sender);
00133 if (!senderConn)
00134 return false; // Sender does not exist.
00135 }
00136 DCOPSignalConnection *current = new DCOPSignalConnection;
00137 current->sender = sender;
00138 current->senderObj = senderObj;
00139 current->senderConn = senderConn;
00140 current->signal = signal;
00141 current->recvConn = conn;
00142 current->recvObj = receiverObj;
00143 current->slot = slot;
00144
00145 DCOPSignalConnectionList *list = connections.find(signal);
00146 if (!list)
00147 {
00148 list = new DCOPSignalConnectionList;
00149 connections.insert(signal, list);
00150 }
00151
00152 list->append( current );
00153 conn->signalConnectionList()->append(current);
00154 if (senderConn && senderConn != conn)
00155 senderConn->signalConnectionList()->append(current);
00156 return true;
00157 }
00158
00168 bool
00169 DCOPSignals::disconnectSignal( const QCString &sender, const QCString &senderObj,
00170 const QCString &signal,
00171 DCOPConnection *conn, const QCString &receiverObj,
00172 const QCString &slot)
00173 {
00174 if (sender.isEmpty() && signal.isEmpty())
00175 {
00176 removeConnections(conn, receiverObj);
00177 return true;
00178 }
00179
00180 DCOPSignalConnectionList *list = connections.find(signal);
00181 if (!list)
00182 return false; // Not found...
00183
00184 DCOPSignalConnection *next = 0;
00185 bool result = false;
00186
00187 for(DCOPSignalConnection *current = list->first(); current; current = next)
00188 {
00189 next = list->next();
00190
00191 if (current->recvConn != conn)
00192 continue;
00193
00194 if (current->senderConn)
00195 {
00196 if (current->senderConn->appId != sender)
00197 continue;
00198 }
00199 else if (current->sender != sender)
00200 continue;
00201
00202 if (!senderObj.isEmpty() &&
00203 (current->senderObj != senderObj))
00204 continue;
00205
00206 if (!receiverObj.isEmpty() &&
00207 (current->recvObj != receiverObj))
00208 continue;
00209
00210 if (!slot.isEmpty() &&
00211 (current->slot != slot))
00212 continue;
00213
00214 result = true;
00215 list->removeRef(current);
00216 conn->signalConnectionList()->removeRef(current);
00217 if (current->senderConn)
00218 current->senderConn->signalConnectionList()->removeRef(current);
00219 delete current;
00220 }
00221 return result;
00222 }
00223
00230 void
00231 DCOPSignals::removeConnections(DCOPConnection *conn, const QCString &obj)
00232 {
00233 DCOPSignalConnectionList *list = conn->_signalConnectionList;
00234 if (!list)
00235 return; // Nothing to do...
00236
00237 DCOPSignalConnection *next = 0;
00238
00239 for(DCOPSignalConnection *current = list->first(); current; current = next)
00240 {
00241 next = list->next();
00242
00243 if (!obj.isEmpty())
00244 {
00245 if ((current->senderConn == conn) && (current->senderObj != obj))
00246 continue;
00247
00248 if ((current->recvConn == conn) && (current->recvObj != obj))
00249 continue;
00250 }
00251
00252 if (current->senderConn && (current->senderConn != conn))
00253 current->senderConn->signalConnectionList()->removeRef(current);
00254
00255 if (current->recvConn != conn)
00256 current->recvConn->signalConnectionList()->removeRef(current);
00257
00258 DCOPSignalConnectionList *signalList = connections.find(current->signal);
00259 if (signalList)
00260 {
00261 signalList->removeRef(current);
00262 if (signalList->isEmpty())
00263 connections.remove(current->signal);
00264 }
00265 else
00266 {
00267 qDebug("Error: Signal Connection was not in signalList!\n");
00268 }
00269 list->removeRef(current);
00270 delete current;
00271 }
00272 }
00273
00274