File indexing completed on 2024-11-10 04:40:28
0001 /* 0002 SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "agentinstancecreatejob.h" 0008 0009 #include "agentinstance.h" 0010 #include "agentmanager.h" 0011 #include "agentmanager_p.h" 0012 #include "controlinterface.h" 0013 #include "kjobprivatebase_p.h" 0014 #include <QDBusConnection> 0015 0016 #include <KLocalizedString> 0017 0018 #include <QTimer> 0019 0020 #ifdef Q_OS_UNIX 0021 #include <signal.h> 0022 #include <sys/types.h> 0023 #endif 0024 0025 using namespace Akonadi; 0026 0027 static const int safetyTimeout = 10000; // ms 0028 0029 namespace Akonadi 0030 { 0031 /** 0032 * @internal 0033 */ 0034 class AgentInstanceCreateJobPrivate : public KJobPrivateBase 0035 { 0036 Q_OBJECT 0037 public: 0038 explicit AgentInstanceCreateJobPrivate(AgentInstanceCreateJob *parent) 0039 : q(parent) 0040 , safetyTimer(new QTimer(parent)) 0041 { 0042 connect(AgentManager::self(), &AgentManager::instanceAdded, this, &AgentInstanceCreateJobPrivate::agentInstanceAdded); 0043 connect(safetyTimer, &QTimer::timeout, this, &AgentInstanceCreateJobPrivate::timeout); 0044 } 0045 0046 void agentInstanceAdded(const AgentInstance &instance) const 0047 { 0048 if (agentInstance == instance && !tooLate) { 0049 safetyTimer->stop(); 0050 if (doConfig) { 0051 // return from dbus call first before doing the next one 0052 QTimer::singleShot(0, this, &AgentInstanceCreateJobPrivate::doConfigure); 0053 } else { 0054 q->emitResult(); 0055 } 0056 } 0057 } 0058 0059 void doConfigure() 0060 { 0061 auto agentControlIface = 0062 new org::freedesktop::Akonadi::Agent::Control(ServerManager::agentServiceName(ServerManager::Agent, agentInstance.identifier()), 0063 QStringLiteral("/"), 0064 QDBusConnection::sessionBus(), 0065 q); 0066 if (!agentControlIface || !agentControlIface->isValid()) { 0067 delete agentControlIface; 0068 0069 q->setError(KJob::UserDefinedError); 0070 q->setErrorText(i18n("Unable to access D-Bus interface of created agent.")); 0071 q->emitResult(); 0072 return; 0073 } 0074 0075 connect(agentControlIface, &org::freedesktop::Akonadi::Agent::Control::configurationDialogAccepted, this, [agentControlIface, this]() { 0076 agentControlIface->deleteLater(); 0077 q->emitResult(); 0078 }); 0079 connect(agentControlIface, &org::freedesktop::Akonadi::Agent::Control::configurationDialogRejected, this, [agentControlIface, this]() { 0080 agentControlIface->deleteLater(); 0081 AgentManager::self()->removeInstance(agentInstance); 0082 q->emitResult(); 0083 }); 0084 0085 agentInstance.configure(parentWidget); 0086 } 0087 0088 void timeout() 0089 { 0090 tooLate = true; 0091 q->setError(KJob::UserDefinedError); 0092 q->setErrorText(i18n("Agent instance creation timed out.")); 0093 q->emitResult(); 0094 } 0095 0096 void doStart() override; 0097 0098 AgentInstanceCreateJob *const q; 0099 AgentType agentType; 0100 QString agentTypeId; 0101 AgentInstance agentInstance; 0102 QWidget *parentWidget = nullptr; 0103 QTimer *const safetyTimer; 0104 bool doConfig = false; 0105 bool tooLate = false; 0106 }; 0107 0108 } // namespace Akonadi 0109 0110 AgentInstanceCreateJob::AgentInstanceCreateJob(const AgentType &agentType, QObject *parent) 0111 : KJob(parent) 0112 , d(new AgentInstanceCreateJobPrivate(this)) 0113 { 0114 d->agentType = agentType; 0115 } 0116 0117 AgentInstanceCreateJob::AgentInstanceCreateJob(const QString &typeId, QObject *parent) 0118 : KJob(parent) 0119 , d(new AgentInstanceCreateJobPrivate(this)) 0120 { 0121 d->agentTypeId = typeId; 0122 } 0123 0124 AgentInstanceCreateJob::~AgentInstanceCreateJob() = default; 0125 0126 void AgentInstanceCreateJob::configure(QWidget *parent) 0127 { 0128 d->parentWidget = parent; 0129 d->doConfig = true; 0130 } 0131 0132 AgentInstance AgentInstanceCreateJob::instance() const 0133 { 0134 return d->agentInstance; 0135 } 0136 0137 void AgentInstanceCreateJob::start() 0138 { 0139 d->start(); 0140 } 0141 0142 void AgentInstanceCreateJobPrivate::doStart() 0143 { 0144 if (!agentType.isValid() && !agentTypeId.isEmpty()) { 0145 agentType = AgentManager::self()->type(agentTypeId); 0146 } 0147 0148 if (!agentType.isValid()) { 0149 q->setError(KJob::UserDefinedError); 0150 q->setErrorText(i18n("Unable to obtain agent type '%1'.", agentTypeId)); 0151 QTimer::singleShot(0, q, &AgentInstanceCreateJob::emitResult); 0152 return; 0153 } 0154 0155 agentInstance = AgentManager::self()->d->createInstance(agentType); 0156 if (!agentInstance.isValid()) { 0157 q->setError(KJob::UserDefinedError); 0158 q->setErrorText(i18n("Unable to create agent instance.")); 0159 QTimer::singleShot(0, q, &AgentInstanceCreateJob::emitResult); 0160 } else { 0161 int timeout = safetyTimeout; 0162 #ifdef Q_OS_UNIX 0163 // Increate the timeout when valgrinding the agent, because that slows down things a log. 0164 const QString agentValgrind = QString::fromLocal8Bit(qgetenv("AKONADI_VALGRIND")); 0165 if (!agentValgrind.isEmpty() && agentType.identifier().contains(agentValgrind)) { 0166 timeout *= 15; 0167 } 0168 #endif 0169 // change the timeout when debugging the agent, because we need time to start the debugger 0170 const QString agentDebugging = QString::fromLocal8Bit(qgetenv("AKONADI_DEBUG_WAIT")); 0171 if (!agentDebugging.isEmpty()) { 0172 // we are debugging 0173 const QString agentDebuggingTimeout = QString::fromLocal8Bit(qgetenv("AKONADI_DEBUG_TIMEOUT")); 0174 if (agentDebuggingTimeout.isEmpty()) { 0175 // use default value of 150 seconds (the same as "valgrinding", this has to be checked) 0176 timeout = 15 * safetyTimeout; 0177 } else { 0178 // use own value 0179 timeout = agentDebuggingTimeout.toInt(); 0180 } 0181 } 0182 safetyTimer->start(timeout); 0183 } 0184 } 0185 0186 #include "agentinstancecreatejob.moc" 0187 0188 #include "moc_agentinstancecreatejob.cpp"