DBus-1-TQt  1.0
tqdbusintegrator.cpp
Go to the documentation of this file.
00001 /* qdbusintegrator.cpp TQT_DBusConnection private implementation
00002  *
00003  * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
00004  * Copyright (C) 2005 Kevin Krammer <kevin.krammer@gmx.at>
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021  * USA.
00022  *
00023  */
00024 
00025 #include <tqapplication.h>
00026 #include <tqevent.h>
00027 #include <tqmetaobject.h>
00028 #include <tqsocketnotifier.h>
00029 #include <tqtimer.h>
00030 
00031 #include "tqdbusconnection_p.h"
00032 #include "tqdbusmessage.h"
00033 
00034 Atomic::Atomic(int value) : m_value(value)
00035 {
00036 }
00037 
00038 void Atomic::ref()
00039 {
00040     m_value++;
00041 }
00042 
00043 bool Atomic::deref()
00044 {
00045     m_value--;
00046     return m_value > 0;
00047 }
00048 
00049 int TQT_DBusConnectionPrivate::messageMetaType = 0;
00050 
00051 static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
00052 {
00053     Q_ASSERT(timeout);
00054     Q_ASSERT(data);
00055 
00056   //  tqDebug("addTimeout %d", dbus_timeout_get_interval(timeout));
00057 
00058     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00059 
00060     if (!dbus_timeout_get_enabled(timeout))
00061         return true;
00062 
00063     if (!tqApp) {
00064         d->pendingTimeouts.append(timeout);
00065         return true;
00066     }
00067     int timerId = d->startTimer(dbus_timeout_get_interval(timeout));
00068     if (!timerId)
00069         return false;
00070 
00071     d->timeouts[timerId] = timeout;
00072     return true;
00073 }
00074 
00075 static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data)
00076 {
00077     Q_ASSERT(timeout);
00078     Q_ASSERT(data);
00079 
00080   //  tqDebug("removeTimeout");
00081 
00082     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00083     for (TQValueList<DBusTimeout*>::iterator it = d->pendingTimeouts.begin();
00084          it != d->pendingTimeouts.end();) {
00085         if ((*it) == timeout) {
00086             it = d->pendingTimeouts.erase(it);
00087         }
00088       else
00089         ++it;
00090     }
00091 
00092     TQT_DBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin();
00093     while (it != d->timeouts.end()) {
00094         if (it.data() == timeout) {
00095             d->killTimer(it.key());
00096             TQT_DBusConnectionPrivate::TimeoutHash::iterator copyIt = it;
00097             ++it;
00098             d->timeouts.erase(copyIt);
00099         } else {
00100             ++it;
00101         }
00102     }
00103 }
00104 
00105 static void qDBusToggleTimeout(DBusTimeout *timeout, void *data)
00106 {
00107     Q_ASSERT(timeout);
00108     Q_ASSERT(data);
00109 
00110     //tqDebug("ToggleTimeout");
00111 
00112     qDBusRemoveTimeout(timeout, data);
00113     qDBusAddTimeout(timeout, data);
00114 }
00115 
00116 static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
00117 {
00118     Q_ASSERT(watch);
00119     Q_ASSERT(data);
00120 
00121     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00122 
00123     int flags = dbus_watch_get_flags(watch);
00124     int fd = dbus_watch_get_unix_fd(watch);
00125 
00126     TQT_DBusConnectionPrivate::Watcher watcher;
00127     if (flags & DBUS_WATCH_READABLE) {
00128         bool enabled = dbus_watch_get_enabled(watch);
00129         //tqDebug("addReadWatch %d %s", fd, (enabled ? "enabled" : "disabled"));
00130         watcher.watch = watch;
00131         if (tqApp) {
00132             watcher.read = new TQSocketNotifier(fd, TQSocketNotifier::Read, d);
00133             if (!enabled) watcher.read->setEnabled(false);
00134             d->connect(watcher.read, TQT_SIGNAL(activated(int)), TQT_SLOT(socketRead(int)));
00135         }
00136     }
00137     if (flags & DBUS_WATCH_WRITABLE) {
00138         bool enabled = dbus_watch_get_enabled(watch);
00139         //tqDebug("addWriteWatch %d %s", fd, (enabled ? "enabled" : "disabled"));
00140         watcher.watch = watch;
00141         if (tqApp) {
00142             watcher.write = new TQSocketNotifier(fd, TQSocketNotifier::Write, d);
00143             if (!enabled) watcher.write->setEnabled(false);
00144             d->connect(watcher.write, TQT_SIGNAL(activated(int)), TQT_SLOT(socketWrite(int)));
00145         }
00146     }
00147     // FIXME-QT4 d->watchers.insertMulti(fd, watcher);
00148     TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00149     if (it == d->watchers.end())
00150     {
00151         it = d->watchers.insert(fd, TQT_DBusConnectionPrivate::WatcherList());
00152     }
00153     it.data().append(watcher);
00154 
00155     return true;
00156 }
00157 
00158 static void qDBusRemoveWatch(DBusWatch *watch, void *data)
00159 {
00160     Q_ASSERT(watch);
00161     Q_ASSERT(data);
00162 
00163     //tqDebug("remove watch");
00164 
00165     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00166     int fd = dbus_watch_get_unix_fd(watch);
00167 
00168     TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00169     if (it != d->watchers.end())
00170     {
00171         TQT_DBusConnectionPrivate::WatcherList& list = *it;
00172         for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin();
00173              wit != list.end(); ++wit)
00174         {
00175             if ((*wit).watch == watch)
00176             {
00177                 // migth be called from a function triggered by a socket listener
00178                 // so just disconnect them and schedule their delayed deletion.
00179 
00180                 d->removedWatches.append(*wit);
00181                 if ((*wit).read)
00182                 {
00183                     (*wit).read->disconnect(d);
00184                     (*wit).read = 0;
00185                 }
00186                 if ((*wit).write)
00187                 {
00188                     (*wit).write->disconnect(d);
00189                     (*wit).write = 0;
00190                 }
00191                 (*wit).watch = 0;
00192             }
00193         }
00194     }
00195 
00196     if (d->removedWatches.count() > 0)
00197         TQTimer::singleShot(0, d, TQT_SLOT(purgeRemovedWatches()));
00198 }
00199 
00200 static void qDBusToggleWatch(DBusWatch *watch, void *data)
00201 {
00202     Q_ASSERT(watch);
00203     Q_ASSERT(data);
00204 
00205     //tqDebug("toggle watch");
00206 
00207     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00208     int fd = dbus_watch_get_unix_fd(watch);
00209 
00210     TQT_DBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
00211     if (it != d->watchers.end()) {
00212         TQT_DBusConnectionPrivate::WatcherList& list = *it;
00213         for (TQT_DBusConnectionPrivate::WatcherList::iterator wit = list.begin(); wit != list.end();
00214              ++wit)
00215         {
00216             if ((*wit).watch == watch) {
00217                 bool enabled = dbus_watch_get_enabled(watch);
00218                 int flags = dbus_watch_get_flags(watch);
00219 
00220 //                 tqDebug("toggle watch %d to %d (write: %d, read: %d)",
00221 //                         dbus_watch_get_unix_fd(watch), enabled,
00222 //                         flags & DBUS_WATCH_WRITABLE, flags & DBUS_WATCH_READABLE);
00223 
00224                 if (flags & DBUS_WATCH_READABLE && (*wit).read)
00225                     (*wit).read->setEnabled(enabled);
00226                 if (flags & DBUS_WATCH_WRITABLE && (*wit).write)
00227                     (*wit).write->setEnabled(enabled);
00228                 return;
00229             }
00230         }
00231     }
00232 }
00233 
00234 static void qDBusNewConnection(DBusServer *server, DBusConnection *c, void *data)
00235 {
00236     Q_ASSERT(data); Q_ASSERT(server); Q_ASSERT(c);
00237 
00238     tqDebug("SERVER: GOT A NEW CONNECTION"); // TODO
00239 }
00240 
00241 static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection,
00242                                            DBusMessage *message, void *data)
00243 {
00244     Q_ASSERT(data);
00245     Q_UNUSED(connection);
00246 
00247     TQT_DBusConnectionPrivate *d = static_cast<TQT_DBusConnectionPrivate *>(data);
00248     if (d->mode == TQT_DBusConnectionPrivate::InvalidMode)
00249         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00250 
00251     int msgType = dbus_message_get_type(message);
00252     bool handled = false;
00253 
00254     //TQT_DBusMessage amsg = TQT_DBusMessage::fromDBusMessage(message);
00255     //tqDebug() << "got message: " << dbus_message_get_type(message) << amsg;
00256 
00257     if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) {
00258         handled = d->handleSignal(message);
00259     } else if (msgType == DBUS_MESSAGE_TYPE_METHOD_CALL) {
00260         handled = d->handleObjectCall(message);
00261     }
00262 
00263     return handled ? DBUS_HANDLER_RESULT_HANDLED :
00264             DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00265 }
00266 
00267 int TQT_DBusConnectionPrivate::registerMessageMetaType()
00268 {
00269     // FIXME-QT4 int tp = messageMetaType = qRegisterMetaType<TQT_DBusMessage>("TQT_DBusMessage");
00270     int tp = 0;
00271     return tp;
00272 }
00273 
00274 TQT_DBusConnectionPrivate::TQT_DBusConnectionPrivate(TQObject *parent)
00275     : TQObject(parent), ref(1), mode(InvalidMode), connection(0), server(0),
00276       dispatcher(0), inDispatch(false)
00277 {
00278     static const int msgType = registerMessageMetaType();
00279     Q_UNUSED(msgType);
00280 
00281     dbus_error_init(&error);
00282 
00283     dispatcher = new TQTimer(this);
00284     TQObject::connect(dispatcher, TQT_SIGNAL(timeout()), this, TQT_SLOT(dispatch()));
00285 
00286     m_resultEmissionQueueTimer = new TQTimer(this);
00287     TQObject::connect(m_resultEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitResultEmissionQueue()));
00288     m_messageEmissionQueueTimer = new TQTimer(this);
00289     TQObject::connect(m_messageEmissionQueueTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(transmitMessageEmissionQueue()));
00290 }
00291 
00292 TQT_DBusConnectionPrivate::~TQT_DBusConnectionPrivate()
00293 {
00294     for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();)
00295     {
00296         PendingCallMap::iterator copyIt = it;
00297         ++it;
00298         dbus_pending_call_cancel(copyIt.key());
00299         dbus_pending_call_unref(copyIt.key());
00300         delete copyIt.data();
00301         pendingCalls.erase(copyIt);
00302     }
00303 
00304     if (dbus_error_is_set(&error))
00305         dbus_error_free(&error);
00306 
00307     closeConnection();
00308 }
00309 
00310 void TQT_DBusConnectionPrivate::closeConnection()
00311 {
00312     ConnectionMode oldMode = mode;
00313     mode = InvalidMode; // prevent reentrancy
00314     if (oldMode == ServerMode) {
00315         if (server) {
00316             dbus_server_disconnect(server);
00317             dbus_server_unref(server);
00318             server = 0;
00319         }
00320     } else if (oldMode == ClientMode) {
00321         if (connection) {
00322             // closing shared connections is forbidden
00323 #if 0
00324             dbus_connection_close(connection);
00325             // send the "close" message
00326             while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
00327 #endif
00328             dbus_connection_unref(connection);
00329             connection = 0;
00330         }
00331     }
00332 }
00333 
00334 bool TQT_DBusConnectionPrivate::handleError()
00335 {
00336     lastError = TQT_DBusError(&error);
00337     if (dbus_error_is_set(&error))
00338         dbus_error_free(&error);
00339     return lastError.isValid();
00340 }
00341 
00342 void TQT_DBusConnectionPrivate::emitPendingCallReply(const TQT_DBusMessage& message)
00343 {
00344     emit dbusPendingCallReply(message);
00345 }
00346 
00347 void TQT_DBusConnectionPrivate::bindToApplication()
00348 {
00349     // Yay, now that we have an application we are in business
00350     // Re-add all watchers
00351     WatcherHash oldWatchers = watchers;
00352     watchers.clear();
00353     // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(oldWatchers);
00354     for (WatcherHash::const_iterator it = oldWatchers.begin(); it != oldWatchers.end(); ++it)
00355     {
00356         const WatcherList& list = *it;
00357         for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit)
00358         {
00359             if (!(*wit).read && !(*wit).write) {
00360                 qDBusAddWatch((*wit).watch, this);
00361             }
00362         }
00363     }
00364 
00365     // Re-add all timeouts
00366     while (!pendingTimeouts.isEmpty()) {
00367        qDBusAddTimeout(pendingTimeouts.first(), this);
00368        pendingTimeouts.pop_front();
00369     }
00370 }
00371 
00372 void TQT_DBusConnectionPrivate::socketRead(int fd)
00373 {
00374     // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(watchers);
00375     WatcherHash::const_iterator it = watchers.find(fd);
00376     if (it != watchers.end()) {
00377         const WatcherList& list = *it;
00378         for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
00379             if ((*wit).read && (*wit).read->isEnabled()) {
00380                 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_READABLE))
00381                     tqDebug("OUT OF MEM");
00382             }
00383         }
00384     }
00385     if (mode == ClientMode)
00386         scheduleDispatch();
00387 }
00388 
00389 void TQT_DBusConnectionPrivate::socketWrite(int fd)
00390 {
00391     // FIXME-QT4 TQHashIterator<int, TQT_DBusConnectionPrivate::Watcher> it(watchers);
00392     WatcherHash::const_iterator it = watchers.find(fd);
00393     if (it != watchers.end()) {
00394         const WatcherList& list = *it;
00395         for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
00396             if ((*wit).write && (*wit).write->isEnabled()) {
00397                 if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_WRITABLE))
00398                     tqDebug("OUT OF MEM");
00399             }
00400         }
00401     }
00402 }
00403 
00404 void TQT_DBusConnectionPrivate::objectDestroyed(TQObject* object)
00405 {
00406     //tqDebug("Object destroyed");
00407     for (PendingCallMap::iterator it = pendingCalls.begin(); it != pendingCalls.end();)
00408     {
00409         TQObject* receiver = (TQObject*) it.data()->receiver;
00410         if (receiver == object || receiver == 0)
00411         {
00412             PendingCallMap::iterator copyIt = it;
00413             ++it;
00414 
00415             dbus_pending_call_cancel(copyIt.key());
00416             dbus_pending_call_unref(copyIt.key());
00417             delete copyIt.data();
00418             pendingCalls.erase(copyIt);
00419         }
00420         else
00421             ++it;
00422     }
00423 }
00424 
00425 void TQT_DBusConnectionPrivate::purgeRemovedWatches()
00426 {
00427     if (removedWatches.isEmpty()) return;
00428 
00429     WatcherList::iterator listIt = removedWatches.begin();
00430     for (; listIt != removedWatches.end(); ++listIt)
00431     {
00432         delete (*listIt).read;
00433         delete (*listIt).write;
00434     }
00435     removedWatches.clear();
00436 
00437     uint count = 0;
00438     WatcherHash::iterator it = watchers.begin();
00439     while (it != watchers.end())
00440     {
00441         WatcherList& list = *it;
00442         listIt = list.begin();
00443         while (listIt != list.end())
00444         {
00445             if (!((*listIt).read) && !((*listIt).write))
00446             {
00447                 listIt = list.erase(listIt);
00448                 ++count;
00449             }
00450         }
00451 
00452         if (list.isEmpty())
00453         {
00454             WatcherHash::iterator copyIt = it;
00455             ++it;
00456             watchers.erase(copyIt);
00457         }
00458         else
00459             ++it;
00460     }
00461 }
00462 
00463 void TQT_DBusConnectionPrivate::scheduleDispatch()
00464 {
00465     dispatcher->start(0);
00466 }
00467 
00468 void TQT_DBusConnectionPrivate::dispatch()
00469 {
00470     // dbus_connection_dispatch will hang if called recursively
00471     if (inDispatch) {
00472         printf("[dbus-1-tqt] WARNING: Attempt to call dispatch() recursively was silently ignored to prevent lockup!\n\r"); fflush(stdout);
00473         return;
00474     }
00475     inDispatch = true;
00476 
00477     if (mode == ClientMode)
00478     {
00479         if (dbus_connection_dispatch(connection) != DBUS_DISPATCH_DATA_REMAINS)
00480         {
00481             // stop dispatch timer
00482             dispatcher->stop();
00483         }
00484     }
00485 
00486     inDispatch = false;
00487 }
00488 
00489 void TQT_DBusConnectionPrivate::transmitMessageEmissionQueue()
00490 {
00491     TQT_DBusConnectionPrivate::PendingMessagesForEmit::iterator pmfe;
00492     pmfe = pendingMessages.begin();
00493     while (pmfe != pendingMessages.end()) {
00494         TQT_DBusMessage msg = *pmfe;
00495         pmfe = pendingMessages.remove(pmfe);
00496         dbusSignal(msg);
00497     }
00498 }
00499 
00500 bool TQT_DBusConnectionPrivate::handleObjectCall(DBusMessage *message)
00501 {
00502     TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message);
00503 
00504     ObjectMap::iterator it = registeredObjects.find(msg.path());
00505     if (it == registeredObjects.end())
00506         return false;
00507 
00508     return it.data()->handleMethodCall(msg);
00509 }
00510 
00511 bool TQT_DBusConnectionPrivate::handleSignal(DBusMessage *message)
00512 {
00513     TQT_DBusMessage msg = TQT_DBusMessage::fromDBusMessage(message);
00514 
00515     // yes, it is a single "|" below...
00516     // FIXME-QT4
00517     //return handleSignal(TQString(), msg) | handleSignal(msg.path(), msg);
00518 
00519     // If dbusSignal(msg) were called here, it could easily cause a lockup as it would enter the TQt3 event loop,
00520     // which could result in arbitrary methods being called while still inside dbus_connection_dispatch.
00521     // Instead, I enqueue the messages here for TQt3 event loop transmission after dbus_connection_dispatch is finished.
00522     pendingMessages.append(msg);
00523     if (!m_messageEmissionQueueTimer->isActive()) m_messageEmissionQueueTimer->start(0, TRUE);
00524 
00525     return true;
00526 }
00527 
00528 static dbus_int32_t server_slot = -1;
00529 
00530 void TQT_DBusConnectionPrivate::setServer(DBusServer *s)
00531 {
00532     if (!server) {
00533         handleError();
00534         return;
00535     }
00536 
00537     server = s;
00538     mode = ServerMode;
00539 
00540     dbus_server_allocate_data_slot(&server_slot);
00541     if (server_slot < 0)
00542         return;
00543 
00544     dbus_server_set_watch_functions(server, qDBusAddWatch, qDBusRemoveWatch,
00545                                     qDBusToggleWatch, this, 0); // ### check return type?
00546     dbus_server_set_timeout_functions(server, qDBusAddTimeout, qDBusRemoveTimeout,
00547                                       qDBusToggleTimeout, this, 0);
00548     dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);
00549 
00550     dbus_server_set_data(server, server_slot, this, 0);
00551 }
00552 
00553 void TQT_DBusConnectionPrivate::setConnection(DBusConnection *dbc)
00554 {
00555     if (!dbc) {
00556         handleError();
00557         return;
00558     }
00559 
00560     connection = dbc;
00561     mode = ClientMode;
00562 
00563     dbus_connection_set_exit_on_disconnect(connection, false);
00564     dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
00565                                         qDBusToggleWatch, this, 0);
00566     dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout,
00567                                           qDBusToggleTimeout, this, 0);
00568 //    dbus_bus_add_match(connection, "type='signal',interface='com.trolltech.dbus.Signal'", &error);
00569 //    dbus_bus_add_match(connection, "type='signal'", &error);
00570 
00571     dbus_bus_add_match(connection, "type='signal'", &error);
00572     if (handleError()) {
00573         closeConnection();
00574         return;
00575     }
00576 
00577     const char *service = dbus_bus_get_unique_name(connection);
00578     if (service) {
00579         TQCString filter;
00580         filter += "destination='";
00581         filter += service;
00582         filter += "\'";
00583 
00584         dbus_bus_add_match(connection, filter.data(), &error);
00585         if (handleError()) {
00586             closeConnection();
00587             return;
00588         }
00589     } else {
00590         tqWarning("TQT_DBusConnectionPrivate::SetConnection: Unable to get unique name");
00591     }
00592 
00593     dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);
00594 
00595     //tqDebug("unique name: %s", service);
00596 }
00597 
00598 static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
00599 {
00600     //tqDebug("Pending Call Result received");
00601     TQT_DBusConnectionPrivate* d = reinterpret_cast<TQT_DBusConnectionPrivate*>(user_data);
00602     TQT_DBusConnectionPrivate::PendingCallMap::iterator it = d->pendingCalls.find(pending);
00603 
00604     DBusMessage *dbusReply = dbus_pending_call_steal_reply(pending);
00605 
00606     dbus_set_error_from_message(&d->error, dbusReply);
00607     d->handleError();
00608 
00609     if (it != d->pendingCalls.end())
00610     {
00611         TQT_DBusMessage reply = TQT_DBusMessage::fromDBusMessage(dbusReply);
00612 
00613         TQT_DBusResultInfo dbusResult;
00614         dbusResult.message = reply;
00615         dbusResult.receiver = it.data()->receiver;
00616         dbusResult.method = it.data()->method.data();
00617         d->m_resultEmissionQueue.append(dbusResult);
00618         d->newMethodInResultEmissionQueue();
00619     }
00620 
00621     dbus_message_unref(dbusReply);
00622     dbus_pending_call_unref(pending);
00623     delete it.data();
00624 
00625     d->pendingCalls.erase(it);
00626 }
00627 
00628 int TQT_DBusConnectionPrivate::sendWithReplyAsync(const TQT_DBusMessage &message, TQObject *receiver,
00629         const char *method)
00630 {
00631     if (!receiver || !method)
00632         return 0;
00633 
00634     if (!TQObject::connect(receiver, TQT_SIGNAL(destroyed(TQObject*)),
00635                           this, TQT_SLOT(objectDestroyed(TQObject*))))
00636         return false;
00637 
00638     DBusMessage *msg = message.toDBusMessage();
00639     if (!msg)
00640         return 0;
00641 
00642     int msg_serial = 0;
00643     DBusPendingCall *pending = 0;
00644     if (dbus_connection_send_with_reply(connection, msg, &pending, message.timeout())) {
00645         TQT_DBusPendingCall *pcall = new TQT_DBusPendingCall;
00646         pcall->receiver = receiver;
00647         pcall->method = method;
00648         pcall->pending = pending;
00649         pendingCalls.insert(pcall->pending, pcall);
00650 
00651         dbus_pending_call_set_notify(pending, qDBusResultReceived, this, 0);
00652 
00653         msg_serial = dbus_message_get_serial(msg);
00654     }
00655 
00656     dbus_message_unref(msg);
00657     return msg_serial;
00658 }
00659 
00660 void TQT_DBusConnectionPrivate::flush()
00661 {
00662     if (!connection) return;
00663 
00664     dbus_connection_flush(connection);
00665 }
00666 
00667 void TQT_DBusConnectionPrivate::newMethodInResultEmissionQueue()
00668 {
00669     if (!m_resultEmissionQueueTimer->isActive()) m_resultEmissionQueueTimer->start(0, TRUE);
00670 }
00671 
00672 void TQT_DBusConnectionPrivate::transmitResultEmissionQueue()
00673 {
00674     if (!m_resultEmissionQueue.isEmpty()) {
00675         TQT_DBusResultInfoList::Iterator it;
00676         it = m_resultEmissionQueue.begin();
00677         while (it != m_resultEmissionQueue.end()) {
00678             TQT_DBusResultInfo dbusResult = (*it);
00679             m_resultEmissionQueue.remove(it);
00680             it = m_resultEmissionQueue.begin();
00681 
00682             TQObject::connect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data());
00683             emitPendingCallReply(dbusResult.message);
00684             TQObject::disconnect(this, TQT_SIGNAL(dbusPendingCallReply(const TQT_DBusMessage&)), dbusResult.receiver, dbusResult.method.data());
00685         }
00686     }
00687 }
00688 
00689 #include "tqdbusconnection_p.moc"
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines