File indexing completed on 2025-02-02 05:08:36
0001 /* 0002 SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "resource.h" 0008 #include "accountwizard_debug.h" 0009 0010 #include <KLocalizedString> 0011 0012 #include <Akonadi/AgentInstanceCreateJob> 0013 #include <Akonadi/AgentManager> 0014 #include <Akonadi/AgentType> 0015 #include <Akonadi/ServerManager> 0016 0017 #include <QDBusInterface> 0018 #include <QDBusReply> 0019 #include <QMetaMethod> 0020 0021 using namespace Akonadi; 0022 0023 static QMetaType::Type argumentType(const QMetaObject *mo, const QString &method) 0024 { 0025 QMetaMethod m; 0026 const int numberOfMethod(mo->methodCount()); 0027 for (int i = 0; i < numberOfMethod; ++i) { 0028 const QString signature = QLatin1StringView(mo->method(i).methodSignature()); 0029 if (signature.contains(method + QLatin1Char('('))) { 0030 m = mo->method(i); 0031 break; 0032 } 0033 } 0034 0035 if (m.methodSignature().isEmpty()) { 0036 qCWarning(ACCOUNTWIZARD_LOG) << "Did not find D-Bus method: " << method << " available methods are:"; 0037 for (int i = 0; i < numberOfMethod; ++i) { 0038 qCWarning(ACCOUNTWIZARD_LOG) << mo->method(i).methodSignature(); 0039 } 0040 return QMetaType::UnknownType; 0041 } 0042 0043 const QList<QByteArray> argTypes = m.parameterTypes(); 0044 if (argTypes.count() != 1) { 0045 return QMetaType::UnknownType; 0046 } 0047 0048 return static_cast<QMetaType::Type>(QMetaType::fromName(argTypes.first().constData()).id()); 0049 } 0050 0051 Resource::Resource(QObject *parent) 0052 : SetupBase{parent} 0053 { 0054 } 0055 0056 Resource::~Resource() = default; 0057 0058 void Resource::createResource() 0059 { 0060 if (!mResourceInfo.isValid()) { 0061 qCWarning(ACCOUNTWIZARD_LOG) << "mResourceInfo is not valid. It's a bug."; 0062 qCWarning(ACCOUNTWIZARD_LOG) << " mResourceInfo " << mResourceInfo; 0063 deleteLater(); 0064 return; 0065 } 0066 const AgentType type = AgentManager::self()->type(mResourceInfo.typeIdentifier); 0067 if (!type.isValid()) { 0068 Q_EMIT error(i18n("Resource type '%1' is not available.", mResourceInfo.typeIdentifier)); 0069 deleteLater(); 0070 return; 0071 } 0072 0073 // By default imap/kolab/pop3 can't be unique. Keep it only for be safe. 0074 // check if unique instance already exists 0075 // qCDebug(ACCOUNTWIZARD_LOG) << type.capabilities(); 0076 if (type.capabilities().contains(QLatin1StringView("Unique"))) { 0077 const Akonadi::AgentInstance::List lstAgent = AgentManager::self()->instances(); 0078 for (const AgentInstance &instance : lstAgent) { 0079 // qCDebug(ACCOUNTWIZARD_LOG) << instance.type().identifier() << (instance.type() == type); 0080 if (instance.type() == type) { 0081 Q_EMIT finished(i18n("Resource '%1' is already set up.", type.name())); 0082 deleteLater(); 0083 return; 0084 } 0085 } 0086 } 0087 0088 Q_EMIT info(i18n("Creating resource instance for '%1'...", type.name())); 0089 auto job = new AgentInstanceCreateJob(type, this); 0090 connect(job, &AgentInstanceCreateJob::result, this, &Resource::instanceCreateResult); 0091 job->start(); 0092 } 0093 0094 void Resource::instanceCreateResult(KJob *job) 0095 { 0096 if (job->error()) { 0097 Q_EMIT error(i18n("Failed to create resource instance: %1", job->errorText())); 0098 deleteLater(); 0099 return; 0100 } 0101 mInstance = qobject_cast<AgentInstanceCreateJob *>(job)->instance(); 0102 0103 if (!mResourceInfo.settings.isEmpty()) { 0104 Q_EMIT info(i18n("Configuring resource instance...")); 0105 const auto service = ServerManager::agentServiceName(ServerManager::Resource, mInstance.identifier()); 0106 QDBusInterface iface(service, QStringLiteral("/Settings")); 0107 if (!iface.isValid()) { 0108 Q_EMIT error(i18n("Unable to configure resource instance.")); 0109 deleteLater(); 0110 return; 0111 } 0112 0113 // configure resource 0114 if (!mResourceInfo.name.isEmpty()) { 0115 mInstance.setName(mResourceInfo.name); 0116 } 0117 QMap<QString, QVariant>::const_iterator end(mResourceInfo.settings.constEnd()); 0118 for (QMap<QString, QVariant>::const_iterator it = mResourceInfo.settings.constBegin(); it != end; ++it) { 0119 qCDebug(ACCOUNTWIZARD_LOG) << "Setting up " << it.key() << " for agent " << mInstance.identifier(); 0120 const QString methodName = QStringLiteral("set%1").arg(it.key()); 0121 const QVariant arg = it.value(); 0122 const QMetaType::Type targetType = argumentType(iface.metaObject(), methodName); 0123 if (arg.metaType().id() != targetType) { 0124 Q_EMIT error(i18n("Could not convert value of setting '%1' to required type %2.", it.key(), QLatin1StringView(QMetaType(targetType).name()))); 0125 0126 qCWarning(ACCOUNTWIZARD_LOG) << "Impossible to convert argument : " << arg 0127 << QStringLiteral("Could not convert value of setting '%1' to required type %2.") 0128 .arg(it.key(), QLatin1StringView(QMetaType(targetType).name())); 0129 return; 0130 } 0131 // arg.convert(targetType); 0132 QDBusReply<void> reply = iface.call(methodName, arg); 0133 if (!reply.isValid()) { 0134 Q_EMIT error(i18n("Could not set setting '%1': %2", it.key(), reply.error().message())); 0135 return; 0136 } 0137 } 0138 QDBusReply<void> reply = iface.call(QStringLiteral("save")); 0139 if (!reply.isValid()) { 0140 Q_EMIT error(i18n("Could not save settings: %1", reply.error().message())); 0141 return; 0142 } 0143 mInstance.reconfigure(); 0144 } 0145 0146 Q_EMIT finished(i18n("Resource setup completed.")); 0147 deleteLater(); 0148 } 0149 0150 Resource::ResourceInfo Resource::resourceInfo() const 0151 { 0152 return mResourceInfo; 0153 } 0154 0155 void Resource::setResourceInfo(const ResourceInfo &newResourceInfo) 0156 { 0157 mResourceInfo = newResourceInfo; 0158 } 0159 0160 QDebug operator<<(QDebug d, const Resource::ResourceInfo &t) 0161 { 0162 d << "name: " << t.name; 0163 d << "typeIdentifier: " << t.typeIdentifier; 0164 d << "settings: " << t.settings; 0165 return d; 0166 } 0167 0168 bool Resource::ResourceInfo::isValid() const 0169 { 0170 return !name.isEmpty() && !typeIdentifier.isEmpty() && !settings.isEmpty(); 0171 } 0172 0173 #include "moc_resource.cpp"