File indexing completed on 2024-11-10 04:40:25

0001 /*
0002     SPDX-FileCopyrightText: 2010 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "agentserver.h"
0008 #include "agentthread.h"
0009 #include "akonadiagentserver_debug.h"
0010 
0011 #include "private/dbus_p.h"
0012 
0013 #include <QCoreApplication>
0014 #include <QDBusConnection>
0015 #include <QPluginLoader>
0016 #include <QTimer>
0017 
0018 using namespace Akonadi;
0019 using namespace std::chrono_literals;
0020 AgentServer::AgentServer(QObject *parent)
0021     : QObject(parent)
0022 {
0023     QDBusConnection::sessionBus().registerObject(QStringLiteral(AKONADI_DBUS_AGENTSERVER_PATH), this, QDBusConnection::ExportScriptableSlots);
0024 }
0025 
0026 AgentServer::~AgentServer()
0027 {
0028     qCDebug(AKONADIAGENTSERVER_LOG) << Q_FUNC_INFO;
0029     if (!m_quiting) {
0030         quit();
0031     }
0032 }
0033 
0034 void AgentServer::agentInstanceConfigure(const QString &identifier, qlonglong windowId)
0035 {
0036     m_configureQueue.enqueue(ConfigureInfo(identifier, windowId));
0037     if (!m_processingConfigureRequests) { // Start processing the requests if needed.
0038         QTimer::singleShot(0s, this, &AgentServer::processConfigureRequest);
0039     }
0040 }
0041 
0042 bool AgentServer::started(const QString &identifier) const
0043 {
0044     return m_agents.contains(identifier);
0045 }
0046 
0047 void AgentServer::startAgent(const QString &identifier, const QString &typeIdentifier, const QString &fileName)
0048 {
0049     qCDebug(AKONADIAGENTSERVER_LOG) << "Starting agent" << identifier << "of type" << typeIdentifier << "(file:" << fileName << ")";
0050 
0051     // First try to load it statically
0052     const QObjectList objList = QPluginLoader::staticInstances();
0053     for (QObject *plugin : objList) {
0054         if (plugin->objectName() == fileName) {
0055             auto thread = new AgentThread(identifier, plugin, this);
0056             m_agents.insert(identifier, thread);
0057             thread->start();
0058             return;
0059         }
0060     }
0061 
0062     QPluginLoader *loader = m_agentLoader.load(fileName);
0063     if (!loader) {
0064         return; // No plugin found, debug output in AgentLoader.
0065     }
0066 
0067     Q_ASSERT(loader->isLoaded());
0068 
0069     auto thread = new AgentThread(identifier, loader->instance(), this);
0070     m_agents.insert(identifier, thread);
0071     thread->start();
0072 }
0073 
0074 void AgentServer::stopAgent(const QString &identifier)
0075 {
0076     AgentThread *thread = m_agents.take(identifier);
0077     if (thread) {
0078         thread->quit();
0079         thread->wait();
0080         delete thread;
0081     }
0082 }
0083 
0084 void AgentServer::quit()
0085 {
0086     Q_ASSERT(!m_quiting);
0087     m_quiting = true;
0088 
0089     QMutableHashIterator<QString, AgentThread *> it(m_agents);
0090     while (it.hasNext()) {
0091         stopAgent(it.next().key());
0092     }
0093 
0094     QCoreApplication::instance()->quit();
0095 }
0096 
0097 void AgentServer::processConfigureRequest()
0098 {
0099     if (m_processingConfigureRequests) {
0100         return; // Protect against reentrancy
0101     }
0102 
0103     m_processingConfigureRequests = true;
0104 
0105     while (!m_configureQueue.empty()) {
0106         const ConfigureInfo info = m_configureQueue.dequeue();
0107         // call configure on the agent with id info.first for windowId info.second.
0108         Q_ASSERT(m_agents.contains(info.first));
0109         AgentThread *thread = m_agents.value(info.first);
0110         thread->configure(info.second);
0111     }
0112 
0113     m_processingConfigureRequests = false;
0114 }
0115 
0116 #include "moc_agentserver.cpp"