File indexing completed on 2025-01-05 04:46:26

0001 /*
0002     SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "agentinstance.h"
0008 #include "akonadicontrol_debug.h"
0009 
0010 #include "agentmanager.h"
0011 
0012 AgentInstance::AgentInstance(AgentManager &manager)
0013     : mManager(manager)
0014 {
0015 }
0016 
0017 AgentInstance::~AgentInstance() = default;
0018 
0019 void AgentInstance::quit()
0020 {
0021     if (mAgentControlInterface && mAgentControlInterface->isValid()) {
0022         mAgentControlInterface->quit();
0023     } else {
0024         mPendingQuit = true;
0025     }
0026 }
0027 
0028 void AgentInstance::cleanup()
0029 {
0030     if (mAgentControlInterface && mAgentControlInterface->isValid()) {
0031         mAgentControlInterface->cleanup();
0032     }
0033 }
0034 
0035 bool AgentInstance::obtainAgentInterface()
0036 {
0037     mAgentControlInterface = findInterface<org::freedesktop::Akonadi::Agent::Control>(Akonadi::DBus::Agent, "/");
0038     mAgentStatusInterface = findInterface<org::freedesktop::Akonadi::Agent::Status>(Akonadi::DBus::Agent, "/");
0039 
0040     if (mPendingQuit && mAgentControlInterface && mAgentControlInterface->isValid()) {
0041         mAgentControlInterface->quit();
0042         mPendingQuit = false;
0043     }
0044 
0045     if (!mAgentControlInterface || !mAgentStatusInterface) {
0046         return false;
0047     }
0048 
0049     mSearchInterface = findInterface<org::freedesktop::Akonadi::Agent::Search>(Akonadi::DBus::Agent, "/Search");
0050 
0051     connect(mAgentStatusInterface.get(),
0052             qOverload<int, const QString &>(&OrgFreedesktopAkonadiAgentStatusInterface::status),
0053             this,
0054             &AgentInstance::statusChanged);
0055     connect(mAgentStatusInterface.get(), &OrgFreedesktopAkonadiAgentStatusInterface::advancedStatus, this, &AgentInstance::advancedStatusChanged);
0056     connect(mAgentStatusInterface.get(), &OrgFreedesktopAkonadiAgentStatusInterface::percent, this, &AgentInstance::percentChanged);
0057     connect(mAgentStatusInterface.get(), &OrgFreedesktopAkonadiAgentStatusInterface::warning, this, &AgentInstance::warning);
0058     connect(mAgentStatusInterface.get(), &OrgFreedesktopAkonadiAgentStatusInterface::error, this, &AgentInstance::error);
0059     connect(mAgentStatusInterface.get(), &OrgFreedesktopAkonadiAgentStatusInterface::onlineChanged, this, &AgentInstance::onlineChanged);
0060 
0061     refreshAgentStatus();
0062     return true;
0063 }
0064 
0065 bool AgentInstance::obtainResourceInterface()
0066 {
0067     mResourceInterface = findInterface<org::freedesktop::Akonadi::Resource>(Akonadi::DBus::Resource, "/");
0068 
0069     if (!mResourceInterface) {
0070         return false;
0071     }
0072 
0073     connect(mResourceInterface.get(), &OrgFreedesktopAkonadiResourceInterface::nameChanged, this, &AgentInstance::resourceNameChanged);
0074     refreshResourceStatus();
0075     return true;
0076 }
0077 
0078 bool AgentInstance::obtainPreprocessorInterface()
0079 {
0080     mPreprocessorInterface = findInterface<org::freedesktop::Akonadi::Preprocessor>(Akonadi::DBus::Preprocessor, "/");
0081     return mPreprocessorInterface != nullptr;
0082 }
0083 
0084 void AgentInstance::statusChanged(int status, const QString &statusMsg)
0085 {
0086     if (mStatus == status && mStatusMessage == statusMsg) {
0087         return;
0088     }
0089     mStatus = status;
0090     mStatusMessage = statusMsg;
0091     Q_EMIT mManager.agentInstanceStatusChanged(mIdentifier, mStatus, mStatusMessage);
0092 }
0093 
0094 void AgentInstance::advancedStatusChanged(const QVariantMap &status)
0095 {
0096     Q_EMIT mManager.agentInstanceAdvancedStatusChanged(mIdentifier, status);
0097 }
0098 
0099 void AgentInstance::statusStateChanged(int status)
0100 {
0101     statusChanged(status, mStatusMessage);
0102 }
0103 
0104 void AgentInstance::statusMessageChanged(const QString &msg)
0105 {
0106     statusChanged(mStatus, msg);
0107 }
0108 
0109 void AgentInstance::percentChanged(int percent)
0110 {
0111     if (mPercent == percent) {
0112         return;
0113     }
0114     mPercent = percent;
0115     Q_EMIT mManager.agentInstanceProgressChanged(mIdentifier, mPercent, QString());
0116 }
0117 
0118 void AgentInstance::warning(const QString &msg)
0119 {
0120     Q_EMIT mManager.agentInstanceWarning(mIdentifier, msg);
0121 }
0122 
0123 void AgentInstance::error(const QString &msg)
0124 {
0125     Q_EMIT mManager.agentInstanceError(mIdentifier, msg);
0126 }
0127 
0128 void AgentInstance::onlineChanged(bool state)
0129 {
0130     if (mOnline == state) {
0131         return;
0132     }
0133     mOnline = state;
0134     Q_EMIT mManager.agentInstanceOnlineChanged(mIdentifier, state);
0135 }
0136 
0137 void AgentInstance::resourceNameChanged(const QString &name)
0138 {
0139     if (name == mResourceName) {
0140         return;
0141     }
0142     mResourceName = name;
0143     Q_EMIT mManager.agentInstanceNameChanged(mIdentifier, name);
0144 }
0145 
0146 void AgentInstance::refreshAgentStatus()
0147 {
0148     if (!hasAgentInterface()) {
0149         return;
0150     }
0151 
0152     // async calls so we are not blocked by misbehaving agents
0153     mAgentStatusInterface->callWithCallback(QStringLiteral("status"), QList<QVariant>(), this, SLOT(statusStateChanged(int)), SLOT(errorHandler(QDBusError)));
0154     mAgentStatusInterface->callWithCallback(QStringLiteral("statusMessage"),
0155                                             QList<QVariant>(),
0156                                             this,
0157                                             SLOT(statusMessageChanged(QString)),
0158                                             SLOT(errorHandler(QDBusError)));
0159     mAgentStatusInterface->callWithCallback(QStringLiteral("progress"), QList<QVariant>(), this, SLOT(percentChanged(int)), SLOT(errorHandler(QDBusError)));
0160     mAgentStatusInterface->callWithCallback(QStringLiteral("isOnline"), QList<QVariant>(), this, SLOT(onlineChanged(bool)), SLOT(errorHandler(QDBusError)));
0161 }
0162 
0163 void AgentInstance::refreshResourceStatus()
0164 {
0165     if (!hasResourceInterface()) {
0166         return;
0167     }
0168 
0169     // async call so we are not blocked by misbehaving resources
0170     mResourceInterface->callWithCallback(QStringLiteral("name"), QList<QVariant>(), this, SLOT(resourceNameChanged(QString)), SLOT(errorHandler(QDBusError)));
0171 }
0172 
0173 void AgentInstance::errorHandler(const QDBusError &error)
0174 {
0175     // avoid using the server tracer, can result in D-BUS lockups
0176     qCCritical(AKONADICONTROL_LOG) << QStringLiteral("D-Bus communication error '%1': '%2'").arg(error.name(), error.message());
0177     // TODO try again after some time, esp. on timeout errors
0178 }
0179 
0180 template<typename T>
0181 std::unique_ptr<T> AgentInstance::findInterface(Akonadi::DBus::AgentType agentType, const char *path)
0182 {
0183     auto iface = std::make_unique<T>(Akonadi::DBus::agentServiceName(mIdentifier, agentType), QLatin1StringView(path), QDBusConnection::sessionBus(), this);
0184 
0185     if (!iface || !iface->isValid()) {
0186         qCCritical(AKONADICONTROL_LOG) << Q_FUNC_INFO << "Cannot connect to agent instance with identifier" << mIdentifier
0187                                        << ", error message:" << (iface ? iface->lastError().message() : QString());
0188         return {};
0189     }
0190     return iface;
0191 }
0192 
0193 #include "moc_agentinstance.cpp"