File indexing completed on 2025-02-02 05:08:37

0001 /*
0002     SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "resource.h"
0008 
0009 #include <Akonadi/AgentConfigurationDialog>
0010 #include <Akonadi/AgentInstanceCreateJob>
0011 #include <Akonadi/AgentManager>
0012 #include <Akonadi/AgentType>
0013 #include <Akonadi/ServerManager>
0014 
0015 #include "accountwizard_debug.h"
0016 #include <KLocalizedString>
0017 
0018 #include <QDBusInterface>
0019 #include <QDBusReply>
0020 #include <QMetaMethod>
0021 #include <QPointer>
0022 #include <QVariant>
0023 
0024 using namespace Akonadi;
0025 
0026 static QVariant::Type argumentType(const QMetaObject *mo, const QString &method)
0027 {
0028     QMetaMethod m;
0029     const int numberOfMethod(mo->methodCount());
0030     for (int i = 0; i < numberOfMethod; ++i) {
0031         const QString signature = QLatin1StringView(mo->method(i).methodSignature());
0032         if (signature.contains(method + QLatin1Char('('))) {
0033             m = mo->method(i);
0034             break;
0035         }
0036     }
0037 
0038     if (m.methodSignature().isEmpty()) {
0039         qCWarning(ACCOUNTWIZARD_LOG) << "Did not find D-Bus method: " << method << " available methods are:";
0040         for (int i = 0; i < numberOfMethod; ++i) {
0041             qCWarning(ACCOUNTWIZARD_LOG) << mo->method(i).methodSignature();
0042         }
0043         return QVariant::Invalid;
0044     }
0045 
0046     const QList<QByteArray> argTypes = m.parameterTypes();
0047     if (argTypes.count() != 1) {
0048         return QVariant::Invalid;
0049     }
0050 
0051     return QVariant::nameToType(argTypes.first().constData());
0052 }
0053 
0054 Resource::Resource(const QString &type, QObject *parent)
0055     : SetupObject(parent)
0056     , m_typeIdentifier(type)
0057 {
0058 }
0059 
0060 void Resource::setOption(const QString &key, const QVariant &value)
0061 {
0062     m_settings.insert(key, value);
0063 }
0064 
0065 void Resource::setName(const QString &name)
0066 {
0067     m_name = name;
0068 }
0069 
0070 void Resource::create()
0071 {
0072     const AgentType type = AgentManager::self()->type(m_typeIdentifier);
0073     if (!type.isValid()) {
0074         Q_EMIT error(i18n("Resource type '%1' is not available.", m_typeIdentifier));
0075         return;
0076     }
0077 
0078     // check if unique instance already exists
0079     qCDebug(ACCOUNTWIZARD_LOG) << type.capabilities();
0080     if (type.capabilities().contains(QLatin1StringView("Unique"))) {
0081         const Akonadi::AgentInstance::List lstAgent = AgentManager::self()->instances();
0082         for (const AgentInstance &instance : lstAgent) {
0083             qCDebug(ACCOUNTWIZARD_LOG) << instance.type().identifier() << (instance.type() == type);
0084             if (instance.type() == type) {
0085                 if (m_editMode) {
0086                     edit();
0087                 }
0088                 Q_EMIT finished(i18n("Resource '%1' is already set up.", type.name()));
0089                 return;
0090             }
0091         }
0092     }
0093 
0094     Q_EMIT info(i18n("Creating resource instance for '%1'...", type.name()));
0095     auto *job = new AgentInstanceCreateJob(type, this);
0096     connect(job, &AgentInstanceCreateJob::result, this, &Resource::instanceCreateResult);
0097     job->start();
0098 }
0099 
0100 void Resource::instanceCreateResult(KJob *job)
0101 {
0102     if (job->error()) {
0103         Q_EMIT error(i18n("Failed to create resource instance: %1", job->errorText()));
0104         return;
0105     }
0106 
0107     m_instance = qobject_cast<AgentInstanceCreateJob *>(job)->instance();
0108 
0109     if (!m_settings.isEmpty()) {
0110         Q_EMIT info(i18n("Configuring resource instance..."));
0111         const auto service = ServerManager::agentServiceName(ServerManager::Resource, m_instance.identifier());
0112         QDBusInterface iface(service, QStringLiteral("/Settings"));
0113         if (!iface.isValid()) {
0114             Q_EMIT error(i18n("Unable to configure resource instance."));
0115             return;
0116         }
0117 
0118         // configure resource
0119         if (!m_name.isEmpty()) {
0120             m_instance.setName(m_name);
0121         }
0122         QMap<QString, QVariant>::const_iterator end(m_settings.constEnd());
0123         for (QMap<QString, QVariant>::const_iterator it = m_settings.constBegin(); it != end; ++it) {
0124             qCDebug(ACCOUNTWIZARD_LOG) << "Setting up " << it.key() << " for agent " << m_instance.identifier();
0125             const QString methodName = QStringLiteral("set%1").arg(it.key());
0126             QVariant arg = it.value();
0127             const QVariant::Type targetType = argumentType(iface.metaObject(), methodName);
0128             if (!arg.canConvert(targetType)) {
0129                 Q_EMIT error(
0130                     i18n("Could not convert value of setting '%1' to required type %2.", it.key(), QLatin1StringView(QVariant::typeToName(targetType))));
0131                 qCWarning(ACCOUNTWIZARD_LOG) << "Impossible to convert argument : " << arg;
0132                 return;
0133             }
0134             arg.convert(targetType);
0135             QDBusReply<void> reply = iface.call(methodName, arg);
0136             if (!reply.isValid()) {
0137                 Q_EMIT error(i18n("Could not set setting '%1': %2", it.key(), reply.error().message()));
0138                 return;
0139             }
0140         }
0141         QDBusReply<void> reply = iface.call(QStringLiteral("save"));
0142         if (!reply.isValid()) {
0143             Q_EMIT error(i18n("Could not save settings: %1", reply.error().message()));
0144             return;
0145         }
0146         m_instance.reconfigure();
0147     }
0148 
0149     if (m_editMode) {
0150         edit();
0151     }
0152     Q_EMIT finished(i18n("Resource setup completed."));
0153 }
0154 
0155 void Resource::edit()
0156 {
0157     if (m_instance.isValid()) {
0158         QPointer<Akonadi::AgentConfigurationDialog> dlg = new Akonadi::AgentConfigurationDialog(m_instance);
0159         dlg->exec();
0160         delete dlg;
0161     }
0162 }
0163 
0164 void Resource::destroy()
0165 {
0166     if (m_instance.isValid()) {
0167         AgentManager::self()->removeInstance(m_instance);
0168         Q_EMIT info(i18n("Removed resource instance for '%1'.", m_instance.type().name()));
0169     }
0170 }
0171 
0172 QString Resource::identifier()
0173 {
0174     return m_instance.identifier();
0175 }
0176 
0177 void Resource::reconfigure()
0178 {
0179     m_instance.reconfigure();
0180 }
0181 
0182 void Resource::setEditMode(const bool editMode)
0183 {
0184     m_editMode = editMode;
0185 }
0186 
0187 #include "moc_resource.cpp"