/* !
    Constructs a new QCop channel monitor for \a channel and
    attaches it to \a parent.

    If \a channel is already registered by one of the clients in the
    system, then the registered() signal will be emitted after this
    constructor exits and control returns to the event loop.

    If the channel is not already registered, then the unregistered()
    signal will be emitted instead.

    The state() will be Unknown until the initial registration
    status has been determined.

    \sa registered(), unregistered(), state()
*/
QCopChannelMonitor::QCopChannelMonitor(const QString& channel, QObject *parent)
    : QObject(parent)
{
    d = new QCopChannelMonitorPrivate(this, channel);
    d->ref.ref();

    QCopThreadData *td = QCopThreadData::instance();

    // Do we need a new monitor list for this channel name?
    QCopClientMonitorMap::Iterator it = td->clientMonitorMap.find(channel);
    if (it != td->clientMonitorMap.end()) {
        it.value().append(QCopChannelMonitorPrivatePointer(d));

        // Copy the state from the previous object on this channel.
        // Either the state is already known, or a request is
        // in transit from the previous object and we will get the
        // update at the same time.
        const QCopChannelMonitorPrivate *prev = it.value()[0].constData();
        d->state = prev->state;
        if (d->state == QCopChannelMonitor::Registered)
            QTimer::singleShot(0, this, SIGNAL(registered()));
        else if (d->state == QCopChannelMonitor::Unregistered)
            QTimer::singleShot(0, this, SIGNAL(unregistered()));
        return;
    }

    it = td->clientMonitorMap.insert
        (channel, QList<QCopChannelMonitorPrivatePointer>());
    it.value().append(QCopChannelMonitorPrivatePointer(d));

    // Inform the server about this channel
    td->clientConnection()->sendChannelCommand(QCopCmd_RegisterMonitor, channel);
}
Example #2
0
// Handle messages that were forwarded on QPE/Application/* channels.
void QCopServerPrivate::forwarded
        (const QString& msg, const QByteArray &data, const QString& channel)
{
    QCopThreadData *td = QCopThreadData::instance();
    QCopServerAppInfo *info;

    // Do we already know about this application?
    QString appName = channel.mid(16);
    QMap<QString, QCopServerAppInfo *>::ConstIterator it;
    it = applications.find(appName);
    if (it != applications.constEnd()) {
        info = it.value();
    } else {
        // We haven't seen this application before, so try to start it.
        qint64 pid = td->server->activateApplication(appName);
        if (pid == -1)
            return;
        info = new QCopServerAppInfo();
        info->pidChannelAvailable = false;
        info->pid = pid;
        info->pidChannel = QLatin1String("QPE/Pid/") + QString::number(pid);
        info->monitor = new QCopChannelMonitor(info->pidChannel);
        connect(info->monitor, SIGNAL(registered()), this, SLOT(registered()));
        connect(info->monitor, SIGNAL(unregistered()), this, SLOT(unregistered()));
        applications.insert(appName, info);
        pidChannels.insert(info->pidChannel, info);
    }

    // Add the message to the application's saved message queue.
    QCopServerSavedMessage saved;
    saved.message = msg;
    saved.data = data;
    info->queue.append(saved);

    // If the application is already running, then pass it on.
    if (info->pidChannelAvailable) {
        // XXX - not right, should use answer()
        td->clientConnection()->send
            (info->pidChannel, msg, data, QCopCmd_SendRequestAck);
    }
}
/* !
    Destroys this QCop channel monitor.
*/
QCopChannelMonitor::~QCopChannelMonitor()
{
    QCopThreadData *td = QCopThreadData::instance();

    QCopClientMonitorMap::Iterator it = td->clientMonitorMap.find(d->channel);
    Q_ASSERT(it != td->clientMonitorMap.end());
    it.value().removeAll(QCopChannelMonitorPrivatePointer(d));
    // Still any monitors connected locally?
    if (it.value().isEmpty()) {
        if (td->hasClientConnection()) {
            td->clientConnection()->sendChannelCommand
                (QCopCmd_DetachMonitor, d->channel);
        }
        td->clientMonitorMap.remove(d->channel);
    }

    // Dereference the private data structure.  It may stay around
    // for a little while longer if it is in use by handleRegistered()
    // or handleUnregistered().
    d->object = 0;
    if (!d->ref.deref())
        delete d;
}