1 | /* |
2 | Copyright (c) 2008 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "agentinstancecreatejob.h" |
21 | |
22 | #include "agentinstance.h" |
23 | #include "agentmanager.h" |
24 | #include "agentmanager_p.h" |
25 | #include "controlinterface.h" |
26 | #include "dbusconnectionpool.h" |
27 | #include "kjobprivatebase_p.h" |
28 | #include "servermanager.h" |
29 | |
30 | #include <kdebug.h> |
31 | #include <klocalizedstring.h> |
32 | |
33 | #include <QtCore/QTimer> |
34 | |
35 | #ifdef Q_OS_UNIX |
36 | #include <sys/types.h> |
37 | #include <signal.h> |
38 | #endif |
39 | |
40 | using namespace Akonadi; |
41 | |
42 | #if defined(Q_WS_MAEMO_5) |
43 | static const int safetyTimeout = 60000; // ms |
44 | #else |
45 | static const int safetyTimeout = 10000; // ms |
46 | #endif |
47 | |
48 | namespace Akonadi { |
49 | /** |
50 | * @internal |
51 | */ |
52 | class AgentInstanceCreateJobPrivate : public KJobPrivateBase |
53 | { |
54 | public: |
55 | AgentInstanceCreateJobPrivate(AgentInstanceCreateJob *parent) |
56 | : q(parent) |
57 | , parentWidget(0) |
58 | , safetyTimer(new QTimer(parent)) |
59 | , doConfig(false) |
60 | , tooLate(false) |
61 | { |
62 | QObject::connect(AgentManager::self(), SIGNAL(instanceAdded(Akonadi::AgentInstance)), |
63 | q, SLOT(agentInstanceAdded(Akonadi::AgentInstance))); |
64 | QObject::connect(safetyTimer, SIGNAL(timeout()), q, SLOT(timeout())); |
65 | } |
66 | |
67 | void agentInstanceAdded(const AgentInstance &instance) |
68 | { |
69 | if (agentInstance == instance && !tooLate) { |
70 | safetyTimer->stop(); |
71 | if (doConfig) { |
72 | // return from dbus call first before doing the next one |
73 | QTimer::singleShot(0, q, SLOT(doConfigure())); |
74 | } else { |
75 | q->emitResult(); |
76 | } |
77 | } |
78 | } |
79 | |
80 | void doConfigure() |
81 | { |
82 | org::freedesktop::Akonadi::Agent::Control *agentControlIface = |
83 | new org::freedesktop::Akonadi::Agent::Control(ServerManager::agentServiceName(ServerManager::Agent, agentInstance.identifier()), |
84 | QLatin1String("/" ), DBusConnectionPool::threadConnection(), q); |
85 | if (!agentControlIface || !agentControlIface->isValid()) { |
86 | delete agentControlIface; |
87 | |
88 | q->setError(KJob::UserDefinedError); |
89 | q->setErrorText(i18n("Unable to access D-Bus interface of created agent." )); |
90 | q->emitResult(); |
91 | return; |
92 | } |
93 | |
94 | q->connect(agentControlIface, SIGNAL(configurationDialogAccepted()), |
95 | q, SLOT(configurationDialogAccepted())); |
96 | q->connect(agentControlIface, SIGNAL(configurationDialogRejected()), |
97 | q, SLOT(configurationDialogRejected())); |
98 | |
99 | agentInstance.configure(parentWidget); |
100 | } |
101 | |
102 | void configurationDialogAccepted() |
103 | { |
104 | // The user clicked 'Ok' in the initial configuration dialog, so we assume |
105 | // he wants to keep the resource and the job is done. |
106 | q->emitResult(); |
107 | } |
108 | |
109 | void configurationDialogRejected() |
110 | { |
111 | // The user clicked 'Cancel' in the initial configuration dialog, so we assume |
112 | // he wants to abort the 'create new resource' job and the new resource will be |
113 | // removed again. |
114 | AgentManager::self()->removeInstance(agentInstance); |
115 | |
116 | q->emitResult(); |
117 | } |
118 | |
119 | void timeout() |
120 | { |
121 | tooLate = true; |
122 | q->setError(KJob::UserDefinedError); |
123 | q->setErrorText(i18n("Agent instance creation timed out." )); |
124 | q->emitResult(); |
125 | } |
126 | |
127 | void emitResult() |
128 | { |
129 | q->emitResult(); |
130 | } |
131 | |
132 | void doStart(); |
133 | |
134 | AgentInstanceCreateJob *q; |
135 | AgentType agentType; |
136 | QString agentTypeId; |
137 | AgentInstance agentInstance; |
138 | QWidget *parentWidget; |
139 | QTimer *safetyTimer; |
140 | bool doConfig; |
141 | bool tooLate; |
142 | }; |
143 | |
144 | } |
145 | |
146 | AgentInstanceCreateJob::AgentInstanceCreateJob(const AgentType &agentType, QObject *parent) |
147 | : KJob(parent) |
148 | , d(new AgentInstanceCreateJobPrivate(this)) |
149 | { |
150 | d->agentType = agentType; |
151 | } |
152 | |
153 | AgentInstanceCreateJob::AgentInstanceCreateJob(const QString &typeId, QObject *parent) |
154 | : KJob(parent) |
155 | , d(new AgentInstanceCreateJobPrivate(this)) |
156 | { |
157 | d->agentTypeId = typeId; |
158 | } |
159 | |
160 | AgentInstanceCreateJob::~ AgentInstanceCreateJob() |
161 | { |
162 | delete d; |
163 | } |
164 | |
165 | void AgentInstanceCreateJob::configure(QWidget *parent) |
166 | { |
167 | d->parentWidget = parent; |
168 | d->doConfig = true; |
169 | } |
170 | |
171 | AgentInstance AgentInstanceCreateJob::instance() const |
172 | { |
173 | return d->agentInstance; |
174 | } |
175 | |
176 | void AgentInstanceCreateJob::start() |
177 | { |
178 | d->start(); |
179 | } |
180 | |
181 | void AgentInstanceCreateJobPrivate::doStart() |
182 | { |
183 | if (!agentType.isValid() && !agentTypeId.isEmpty()) { |
184 | agentType = AgentManager::self()->type(agentTypeId); |
185 | } |
186 | |
187 | if (!agentType.isValid()) { |
188 | q->setError(KJob::UserDefinedError); |
189 | q->setErrorText(i18n("Unable to obtain agent type '%1'." , agentTypeId)); |
190 | QTimer::singleShot(0, q, SLOT(emitResult())); |
191 | return; |
192 | } |
193 | |
194 | agentInstance = AgentManager::self()->d->createInstance(agentType); |
195 | if (!agentInstance.isValid()) { |
196 | q->setError(KJob::UserDefinedError); |
197 | q->setErrorText(i18n("Unable to create agent instance." )); |
198 | QTimer::singleShot(0, q, SLOT(emitResult())); |
199 | } else { |
200 | int timeout = safetyTimeout; |
201 | #ifdef Q_OS_UNIX |
202 | // Increate the timeout when valgrinding the agent, because that slows down things a log. |
203 | QString agentValgrind = QString::fromLocal8Bit(qgetenv("AKONADI_VALGRIND" )); |
204 | if (!agentValgrind.isEmpty() && agentType.identifier().contains(agentValgrind)) { |
205 | timeout *= 15; |
206 | } |
207 | |
208 | // change the timeout when debugging the agent, because we need time to start the debugger |
209 | const QString agentDebugging = QString::fromLocal8Bit(qgetenv("AKONADI_DEBUG_WAIT" )); |
210 | if (!agentDebugging.isEmpty()) { |
211 | // we are debugging |
212 | const QString agentDebuggingTimeout = QString::fromLocal8Bit(qgetenv("AKONADI_DEBUG_TIMEOUT" )); |
213 | if (agentDebuggingTimeout.isEmpty()) { |
214 | // use default value of 150 seconds (the same as "valgrinding", this has to be checked) |
215 | timeout = 15 * safetyTimeout; |
216 | } else { |
217 | // use own value |
218 | timeout = agentDebuggingTimeout.toInt(); |
219 | } |
220 | } |
221 | #endif |
222 | safetyTimer->start(timeout); |
223 | } |
224 | } |
225 | |
226 | #include "moc_agentinstancecreatejob.cpp" |
227 | |