24#include "dbusconnectionpool.h"
26#include "imapparser_p.h"
31#include <klocalizedstring.h>
33#include <QtCore/QEventLoop>
34#include <QtCore/QTimer>
35#include <QtCore/QTextStream>
36#include <QtDBus/QDBusInterface>
37#include <QtDBus/QDBusConnectionInterface>
41static QDBusAbstractInterface *s_jobtracker = 0;
44void JobPrivate::handleResponse(
const QByteArray &tag,
const QByteArray &data)
49 mCurrentSubJob->d_ptr->handleResponse(
tag, data);
54 if (data.startsWith(
"NO ") || data.startsWith(
"BAD ")) {
55 QString msg = QString::fromUtf8(data);
57 msg.remove(0, msg.startsWith(QLatin1String(
"NO ")) ? 3 : 4);
59 if (msg.endsWith(QLatin1String(
"\r\n"))) {
67 }
else if (data.startsWith(
"OK")) {
74 QTimer::singleShot(0, q, SLOT(delayedEmitResult()));
79 q->doHandleResponse(
tag, data);
82void JobPrivate::init(QObject *parent)
86 mParentJob =
dynamic_cast<Job *
>(parent);
87 mSession =
dynamic_cast<Session *
>(parent);
93 mSession = mParentJob->d_ptr->mSession;
98 mSession->d->addJob(q);
107 static QTime s_lastTime;
108 if (s_lastTime.isNull() || s_lastTime.elapsed() > 3000) {
109 if (s_lastTime.isNull()) {
112 if (DBusConnectionPool::threadConnection().interface()->isServiceRegistered(QLatin1String(
"org.kde.akonadiconsole"))) {
113 s_jobtracker =
new QDBusInterface(QLatin1String(
"org.kde.akonadiconsole"),
114 QLatin1String(
"/jobtracker"),
115 QLatin1String(
"org.freedesktop.Akonadi.JobTracker"),
116 DBusConnectionPool::threadConnection(), 0);
118 s_lastTime.restart();
124 QMetaObject::invokeMethod(q,
"signalCreationToJobTracker", Qt::QueuedConnection);
127void JobPrivate::signalCreationToJobTracker()
135 QList<QVariant> argumentList;
136 argumentList << QLatin1String(mSession->
sessionId())
137 << QString::number(
reinterpret_cast<quintptr
>(q), 16)
138 << (mParentJob ? QString::number(
reinterpret_cast<quintptr
>(mParentJob), 16) : QString())
139 << QString::fromLatin1(q->metaObject()->className())
140 << jobDebuggingString();
141 s_jobtracker->callWithArgumentList(QDBus::NoBlock, QLatin1String(
"jobCreated"), argumentList);
145void JobPrivate::signalStartedToJobTracker()
150 QList<QVariant> argumentList;
151 argumentList << QString::number(reinterpret_cast<quintptr>(q), 16);
152 s_jobtracker->callWithArgumentList(QDBus::NoBlock, QLatin1String(
"jobStarted"), argumentList);
161void JobPrivate::delayedEmitResult()
168void JobPrivate::startQueued()
173 emit q->aboutToStart(q);
175 QTimer::singleShot(0, q, SLOT(startNext()));
176 QMetaObject::invokeMethod(q,
"signalStartedToJobTracker", Qt::QueuedConnection);
179void JobPrivate::lostConnection()
183 if (mCurrentSubJob) {
184 mCurrentSubJob->d_ptr->lostConnection();
191void JobPrivate::slotSubJobAboutToStart(
Job *job)
193 Q_ASSERT(mCurrentSubJob == 0);
194 mCurrentSubJob = job;
197void JobPrivate::startNext()
201 if (mStarted && !mCurrentSubJob && q->hasSubjobs()) {
204 job->d_ptr->startQueued();
211 mTag = mParentJob->d_ptr->newTag();
213 mTag = QByteArray::number(mSession->d->nextTag());
225 Q_ASSERT_X(!mWriteFinished,
"Job::writeData()",
"Calling writeData() after emitting writeFinished()");
226 mSession->d->writeData(data);
231 mSession->d->itemRevisionChanged(itemId, oldRevision, newRevision);
237 foreach (KJob *j, q->subjobs()) {
240 job->d_ptr->updateItemRevision(itemId, oldRevision, newRevision);
249 Q_UNUSED(oldRevision);
250 Q_UNUSED(newRevision);
253int JobPrivate::protocolVersion()
const
255 return mSession->d->protocolVersion;
260 : KCompositeJob(parent)
267 : KCompositeJob(parent)
279 QList<QVariant> argumentList;
280 argumentList << QString::number(reinterpret_cast<quintptr>(
this), 16)
282 s_jobtracker->callWithArgumentList(QDBus::NoBlock, QLatin1String(
"jobEnded"), argumentList);
295 d->mSession->d->forceReconnect();
308 str = i18n(
"Cannot connect to the Akonadi service.");
311 str = i18n(
"The protocol version of the Akonadi server is incompatible. Make sure you have a compatible version installed.");
314 str = i18n(
"User canceled operation.");
319 str = i18n(
"Unknown error.");
322 if (!errorText().isEmpty()) {
323 str += QString::fromLatin1(
" (%1)").arg(errorText());
330 bool rv = KCompositeJob::addSubjob(job);
333 QTimer::singleShot(0,
this, SLOT(startNext()));
340 bool rv = KCompositeJob::removeSubjob(job);
341 if (job == d_ptr->mCurrentSubJob) {
342 d_ptr->mCurrentSubJob = 0;
343 QTimer::singleShot(0,
this, SLOT(startNext()));
350 kDebug() <<
"Unhandled response: " << tag << data;
353void Job::slotResult(KJob *job)
355 if (d_ptr->mCurrentSubJob == job) {
357 d_ptr->mCurrentSubJob = 0;
358 KCompositeJob::slotResult(job);
360 QTimer::singleShot(0,
this, SLOT(startNext()));
366 KCompositeJob::removeSubjob(job);
372 d_ptr->mWriteFinished =
true;
376#include "moc_job.cpp"
virtual void doUpdateItemRevision(Akonadi::Item::Id, int oldRevision, int newRevision)
Overwrite this if your job does operations with conflict detection and update the item revisions if y...
QByteArray tag() const
Return the tag used for the request.
void itemRevisionChanged(Akonadi::Item::Id itemId, int oldRevision, int newRevision)
Notify following jobs about item revision changes.
void writeData(const QByteArray &data)
Sends raw data to the backend.
virtual void aboutToFinish()
This method is called right before result() and finished() signals are emitted.
QByteArray newTag()
Returns a new unique command tag for communication with the backend.
void updateItemRevision(Akonadi::Item::Id itemId, int oldRevision, int newRevision)
Propagate item revision changes to this job and its sub-jobs.
Base class for all actions in the Akonadi storage.
void aboutToStart(Akonadi::Job *job)
This signal is emitted directly before the job will be started.
void start()
Jobs are started automatically once entering the event loop again, no need to explicitly call this.
virtual ~Job()
Destroys the job.
@ ProtocolVersionMismatch
The server protocol version is too old or too new.
@ ConnectionFailed
The connection to the Akonadi server failed.
@ UserCanceled
The user canceld this job.
virtual bool doKill()
Kills the execution of the job.
void emitWriteFinished()
Call this method to indicate that this job will not call writeData() again.
virtual bool removeSubjob(KJob *job)
Removes the given subjob of this job.
Job(QObject *parent=0)
Creates a new job.
virtual QString errorString() const
Returns the error string, if there has been an error, an empty string otherwise.
void writeFinished(Akonadi::Job *job)
This signal is emitted if the job has finished all write operations, ie.
virtual bool addSubjob(KJob *job)
Adds the given job as a subjob to this job.
virtual void doHandleResponse(const QByteArray &tag, const QByteArray &data)
This method should be reimplemented in the concrete jobs in case you want to handle incoming data.
A communication session with the Akonadi storage.
static Session * defaultSession()
Returns the default session for this thread.
QByteArray sessionId() const
Returns the session identifier.
FreeBusyManager::Singleton.