• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • sources
  • kde-4.14
  • kdepimlibs
  • akonadi
agentbase.cpp
1 /*
2  Copyright (c) 2006 Till Adam <adam@kde.org>
3  Copyright (c) 2007 Volker Krause <vkrause@kde.org>
4  Copyright (c) 2007 Bruno Virlet <bruno.virlet@gmail.com>
5  Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
6 
7  This library is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Library General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but WITHOUT
13  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15  License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to the
19  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  02110-1301, USA.
21 */
22 
23 #include "agentbase.h"
24 #include "agentbase_p.h"
25 
26 #include "agentmanager.h"
27 #include "changerecorder.h"
28 #include "controladaptor.h"
29 #include "dbusconnectionpool.h"
30 #include "itemfetchjob.h"
31 #include "kdepimlibs-version.h"
32 #include "monitor_p.h"
33 #include "servermanager_p.h"
34 #include "session.h"
35 #include "session_p.h"
36 #include "statusadaptor.h"
37 
38 #include <kaboutdata.h>
39 #include <kcmdlineargs.h>
40 #include <kdebug.h>
41 #include <kglobal.h>
42 #include <klocalizedstring.h>
43 #include <kstandarddirs.h>
44 
45 #include <Solid/PowerManagement>
46 
47 #include <QtCore/QDir>
48 #include <QtCore/QSettings>
49 #include <QtCore/QTimer>
50 #include <QtDBus/QtDBus>
51 #include <QApplication>
52 
53 #include <signal.h>
54 #include <stdlib.h>
55 #if defined __GLIBC__
56 # include <malloc.h> // for dumping memory information
57 #endif
58 
59 //#define EXPERIMENTAL_INPROCESS_AGENTS 1
60 
61 using namespace Akonadi;
62 
63 static AgentBase *sAgentBase = 0;
64 
65 AgentBase::Observer::Observer()
66 {
67 }
68 
69 AgentBase::Observer::~Observer()
70 {
71 }
72 
73 void AgentBase::Observer::itemAdded(const Item &item, const Collection &collection)
74 {
75  Q_UNUSED(item);
76  Q_UNUSED(collection);
77  if (sAgentBase != 0) {
78  sAgentBase->d_ptr->changeProcessed();
79  }
80 }
81 
82 void AgentBase::Observer::itemChanged(const Item &item, const QSet<QByteArray> &partIdentifiers)
83 {
84  Q_UNUSED(item);
85  Q_UNUSED(partIdentifiers);
86  if (sAgentBase != 0) {
87  sAgentBase->d_ptr->changeProcessed();
88  }
89 }
90 
91 void AgentBase::Observer::itemRemoved(const Item &item)
92 {
93  Q_UNUSED(item);
94  if (sAgentBase != 0) {
95  sAgentBase->d_ptr->changeProcessed();
96  }
97 }
98 
99 void AgentBase::Observer::collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent)
100 {
101  Q_UNUSED(collection);
102  Q_UNUSED(parent);
103  if (sAgentBase != 0) {
104  sAgentBase->d_ptr->changeProcessed();
105  }
106 }
107 
108 void AgentBase::Observer::collectionChanged(const Collection &collection)
109 {
110  Q_UNUSED(collection);
111  if (sAgentBase != 0) {
112  sAgentBase->d_ptr->changeProcessed();
113  }
114 }
115 
116 void AgentBase::Observer::collectionRemoved(const Collection &collection)
117 {
118  Q_UNUSED(collection);
119  if (sAgentBase != 0) {
120  sAgentBase->d_ptr->changeProcessed();
121  }
122 }
123 
124 void AgentBase::ObserverV2::itemMoved(const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest)
125 {
126  Q_UNUSED(item);
127  Q_UNUSED(source);
128  Q_UNUSED(dest);
129  if (sAgentBase != 0) {
130  sAgentBase->d_ptr->changeProcessed();
131  }
132 }
133 
134 void AgentBase::ObserverV2::itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
135 {
136  Q_UNUSED(item);
137  Q_UNUSED(collection);
138  if (sAgentBase != 0) {
139  // not implementation, let's disconnect the signal to enable optimizations in Monitor
140  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
141  sAgentBase->d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)));
142  sAgentBase->d_ptr->changeProcessed();
143  }
144 }
145 
146 void AgentBase::ObserverV2::itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
147 {
148  Q_UNUSED(item);
149  Q_UNUSED(collection);
150  if (sAgentBase != 0) {
151  // not implementation, let's disconnect the signal to enable optimizations in Monitor
152  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
153  sAgentBase->d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)));
154  sAgentBase->d_ptr->changeProcessed();
155  }
156 }
157 
158 void AgentBase::ObserverV2::collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest)
159 {
160  Q_UNUSED(collection);
161  Q_UNUSED(source);
162  Q_UNUSED(dest);
163  if (sAgentBase != 0) {
164  sAgentBase->d_ptr->changeProcessed();
165  }
166 }
167 
168 void AgentBase::ObserverV2::collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes)
169 {
170  Q_UNUSED(changedAttributes);
171  collectionChanged(collection);
172 }
173 
174 void AgentBase::ObserverV3::itemsFlagsChanged(const Akonadi::Item::List &items, const QSet< QByteArray > &addedFlags, const QSet< QByteArray > &removedFlags)
175 {
176  Q_UNUSED(items);
177  Q_UNUSED(addedFlags);
178  Q_UNUSED(removedFlags);
179 
180  if (sAgentBase != 0) {
181  // not implementation, let's disconnect the signal to enable optimizations in Monitor
182  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
183  sAgentBase->d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)));
184  sAgentBase->d_ptr->changeProcessed();
185  }
186 }
187 
188 void AgentBase::ObserverV3::itemsMoved(const Akonadi::Item::List &items, const Collection &sourceCollection, const Collection &destinationCollection)
189 {
190  Q_UNUSED(items);
191  Q_UNUSED(sourceCollection);
192  Q_UNUSED(destinationCollection);
193 
194  if (sAgentBase != 0) {
195  // not implementation, let's disconnect the signal to enable optimizations in Monitor
196  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
197  sAgentBase->d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)));
198  sAgentBase->d_ptr->changeProcessed();
199  }
200 }
201 
202 void AgentBase::ObserverV3::itemsRemoved(const Akonadi::Item::List &items)
203 {
204  Q_UNUSED(items);
205 
206  if (sAgentBase != 0) {
207  // not implementation, let's disconnect the signal to enable optimizations in Monitor
208  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsRemoved(Akonadi::Item::List)),
209  sAgentBase->d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)));
210  sAgentBase->d_ptr->changeProcessed();
211  }
212 }
213 
214 void AgentBase::ObserverV3::itemsLinked(const Akonadi::Item::List &items, const Collection &collection)
215 {
216  Q_UNUSED(items);
217  Q_UNUSED(collection);
218 
219  if (sAgentBase != 0) {
220  // not implementation, let's disconnect the signal to enable optimizations in Monitor
221  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
222  sAgentBase->d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)));
223  sAgentBase->d_ptr->changeProcessed();
224  }
225 }
226 
227 void AgentBase::ObserverV3::itemsUnlinked(const Akonadi::Item::List &items, const Collection &collection)
228 {
229  Q_UNUSED(items);
230  Q_UNUSED(collection)
231 
232  if (sAgentBase != 0) {
233  // not implementation, let's disconnect the signal to enable optimizations in Monitor
234  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
235  sAgentBase->d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)));
236  sAgentBase->d_ptr->changeProcessed();
237  }
238 }
239 
240 void AgentBase::ObserverV4::tagAdded(const Tag &tag)
241 {
242  Q_UNUSED(tag);
243 
244  if (sAgentBase != 0) {
245  // not implementation, let's disconnect the signal to enable optimization in Monitor
246  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(tagAdded(Akonadi::Tag)),
247  sAgentBase->d_ptr, SLOT(tagAdded(Akonadi::Tag)));
248  sAgentBase->d_ptr->changeProcessed();
249  }
250 }
251 
252 void AgentBase::ObserverV4::tagChanged(const Tag &tag)
253 {
254  Q_UNUSED(tag);
255 
256  if (sAgentBase != 0) {
257  // not implementation, let's disconnect the signal to enable optimization in Monitor
258  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(tagChanged(Akonadi::Tag)),
259  sAgentBase->d_ptr, SLOT(tagChanged(Akonadi::Tag)));
260  sAgentBase->d_ptr->changeProcessed();
261  }
262 }
263 
264 void AgentBase::ObserverV4::tagRemoved(const Tag &tag)
265 {
266  Q_UNUSED(tag);
267 
268  if (sAgentBase != 0) {
269  // not implementation, let's disconnect the signal to enable optimization in Monitor
270  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(tagRemoved(Akonadi::Tag)),
271  sAgentBase->d_ptr, SLOT(tagRemoved(Akonadi::Tag)));
272  sAgentBase->d_ptr->changeProcessed();
273  }
274 }
275 
276 void AgentBase::ObserverV4::itemsTagsChanged(const Item::List &items, const QSet<Tag> &addedTags, const QSet<Tag> &removedTags)
277 {
278  Q_UNUSED(items);
279  Q_UNUSED(addedTags);
280  Q_UNUSED(removedTags);
281 
282  if (sAgentBase != 0) {
283  // not implementation, let's disconnect the signal to enable optimization in Monitor
284  QObject::disconnect(sAgentBase->changeRecorder(), SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
285  sAgentBase->d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)));
286  sAgentBase->d_ptr->changeProcessed();
287  }
288 }
289 
290 //@cond PRIVATE
291 
292 AgentBasePrivate::AgentBasePrivate(AgentBase *parent)
293  : q_ptr(parent)
294  , mDBusConnection(QString())
295  , mStatusCode(AgentBase::Idle)
296  , mProgress(0)
297  , mNeedsNetwork(false)
298  , mOnline(false)
299  , mDesiredOnlineState(false)
300  , mSettings(0)
301  , mChangeRecorder(0)
302  , mTracer(0)
303  , mObserver(0)
304  , mTemporaryOfflineTimer(0)
305 {
306  Internal::setClientType(Internal::Agent);
307 }
308 
309 AgentBasePrivate::~AgentBasePrivate()
310 {
311  mChangeRecorder->setConfig(0);
312  delete mSettings;
313 }
314 
315 void AgentBasePrivate::init()
316 {
317  Q_Q(AgentBase);
318 
322  SessionPrivate::createDefaultSession(mId.toLatin1());
323 
324  if (QThread::currentThread() != QCoreApplication::instance()->thread()) {
325  mDBusConnection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, q->identifier());
326  Q_ASSERT(mDBusConnection.isConnected());
327  }
328 
329  mTracer = new org::freedesktop::Akonadi::Tracer(ServerManager::serviceName(ServerManager::Server),
330  QLatin1String("/tracing"),
331  DBusConnectionPool::threadConnection(), q);
332 
333  new Akonadi__ControlAdaptor(q);
334  new Akonadi__StatusAdaptor(q);
335  if (!DBusConnectionPool::threadConnection().registerObject(QLatin1String("/"), q, QDBusConnection::ExportAdaptors)) {
336  q->error(i18n("Unable to register object at dbus: %1", DBusConnectionPool::threadConnection().lastError().message()));
337  }
338 
339  mSettings = new QSettings(QString::fromLatin1("%1/agent_config_%2").arg(Internal::xdgSaveDir("config"), mId), QSettings::IniFormat);
340 
341  mChangeRecorder = new ChangeRecorder(q);
342  mChangeRecorder->ignoreSession(Session::defaultSession());
343  mChangeRecorder->itemFetchScope().setCacheOnly(true);
344  mChangeRecorder->setConfig(mSettings);
345 
346  mDesiredOnlineState = mSettings->value(QLatin1String("Agent/DesiredOnlineState"), true).toBool();
347  mOnline = mDesiredOnlineState;
348 
349  // reinitialize the status message now that online state is available
350  mStatusMessage = defaultReadyMessage();
351 
352  mName = mSettings->value(QLatin1String("Agent/Name")).toString();
353  if (mName.isEmpty()) {
354  mName = mSettings->value(QLatin1String("Resource/Name")).toString();
355  if (!mName.isEmpty()) {
356  mSettings->remove(QLatin1String("Resource/Name"));
357  mSettings->setValue(QLatin1String("Agent/Name"), mName);
358  }
359  }
360 
361  connect(mChangeRecorder, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
362  SLOT(itemAdded(Akonadi::Item,Akonadi::Collection)));
363  connect(mChangeRecorder, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
364  SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)));
365  connect(mChangeRecorder, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
366  SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)));
367  connect(mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection)),
368  SLOT(collectionChanged(Akonadi::Collection)));
369  connect(mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)),
370  SLOT(collectionChanged(Akonadi::Collection,QSet<QByteArray>)));
371  connect(mChangeRecorder, SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)),
372  SLOT(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)));
373  connect(mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
374  SLOT(collectionRemoved(Akonadi::Collection)));
375  connect(mChangeRecorder, SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),
376  SLOT(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)));
377  connect(mChangeRecorder, SIGNAL(collectionUnsubscribed(Akonadi::Collection)),
378  SLOT(collectionUnsubscribed(Akonadi::Collection)));
379 
380  connect(q, SIGNAL(status(int,QString)), q, SLOT(slotStatus(int,QString)));
381  connect(q, SIGNAL(percent(int)), q, SLOT(slotPercent(int)));
382  connect(q, SIGNAL(warning(QString)), q, SLOT(slotWarning(QString)));
383  connect(q, SIGNAL(error(QString)), q, SLOT(slotError(QString)));
384 
385  connect(Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), q, SLOT(slotResumedFromSuspend()));
386 
387  // Use reference counting to allow agents to finish internal jobs when the
388  // agent is stopped.
389  KGlobal::ref();
390  if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
391  KGlobal::setAllowQuit(true);
392  }
393 
394  // disable session management
395  if (KApplication::kApplication()) {
396  KApplication::kApplication()->disableSessionManagement();
397  }
398 
399  mResourceTypeName = AgentManager::self()->instance(mId).type().name();
400  setProgramName();
401 
402  QTimer::singleShot(0, q, SLOT(delayedInit()));
403 }
404 
405 void AgentBasePrivate::delayedInit()
406 {
407  Q_Q(AgentBase);
408 
409  const QString serviceId = ServerManager::agentServiceName(ServerManager::Agent, mId);
410  if (!DBusConnectionPool::threadConnection().registerService(serviceId)) {
411  kFatal() << "Unable to register service" << serviceId << "at dbus:" << DBusConnectionPool::threadConnection().lastError().message();
412  }
413  q->setOnlineInternal(mDesiredOnlineState);
414 
415  DBusConnectionPool::threadConnection().registerObject(QLatin1String("/Debug"), this, QDBusConnection::ExportScriptableSlots);
416 }
417 
418 void AgentBasePrivate::setProgramName()
419 {
420  // ugly, really ugly, if you find another solution, change it and blame me for this code (Andras)
421  QString programName = mResourceTypeName;
422  if (!mName.isEmpty()) {
423  programName = i18nc("Name and type of Akonadi resource", "%1 of type %2", mName, mResourceTypeName) ;
424  }
425  const_cast<KAboutData *>(KGlobal::mainComponent().aboutData())->setProgramName(ki18n(programName.toUtf8()));
426 }
427 
428 void AgentBasePrivate::itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection)
429 {
430  if (mObserver != 0) {
431  mObserver->itemAdded(item, collection);
432  }
433 }
434 
435 void AgentBasePrivate::itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers)
436 {
437  if (mObserver != 0) {
438  mObserver->itemChanged(item, partIdentifiers);
439  }
440 }
441 
442 void AgentBasePrivate::itemMoved(const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest)
443 {
444  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
445  if (mObserver) {
446  // inter-resource moves, requires we know which resources the source and destination are in though
447  if (!source.resource().isEmpty() && !dest.resource().isEmpty()) {
448  if (source.resource() != dest.resource()) {
449  if (source.resource() == q_ptr->identifier()) { // moved away from us
450  Akonadi::Item i(item);
451  i.setParentCollection(source);
452  mObserver->itemRemoved(i);
453  } else if (dest.resource() == q_ptr->identifier()) { // moved to us
454  mObserver->itemAdded(item, dest);
455  } else if (observer2) {
456  observer2->itemMoved(item, source, dest);
457  } else {
458  // not for us, not sure if we should get here at all
459  changeProcessed();
460  }
461  return;
462  }
463  }
464  // intra-resource move
465  if (observer2) {
466  observer2->itemMoved(item, source, dest);
467  } else {
468  // ### we cannot just call itemRemoved here as this will already trigger changeProcessed()
469  // so, just itemAdded() is good enough as no resource can have implemented intra-resource moves anyway
470  // without using ObserverV2
471  mObserver->itemAdded(item, dest);
472  // mObserver->itemRemoved( item );
473  }
474  }
475 }
476 
477 void AgentBasePrivate::itemRemoved(const Akonadi::Item &item)
478 {
479  if (mObserver != 0) {
480  mObserver->itemRemoved(item);
481  }
482 }
483 
484 void AgentBasePrivate::itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
485 {
486  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
487  if (observer2) {
488  observer2->itemLinked(item, collection);
489  } else {
490  changeProcessed();
491  }
492 }
493 
494 void AgentBasePrivate::itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
495 {
496  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
497  if (observer2) {
498  observer2->itemUnlinked(item, collection);
499  } else {
500  changeProcessed();
501  }
502 }
503 
504 void AgentBasePrivate::itemsFlagsChanged(const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags, const QSet<QByteArray> &removedFlags)
505 {
506  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3 *>(mObserver);
507  if (observer3) {
508  observer3->itemsFlagsChanged(items, addedFlags, removedFlags);
509  } else {
510  Q_ASSERT_X(false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available");
511  }
512 }
513 
514 void AgentBasePrivate::itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &source, const Akonadi::Collection &destination)
515 {
516  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3 *>(mObserver);
517  if (observer3) {
518  observer3->itemsMoved(items, source, destination);
519  } else {
520  Q_ASSERT_X(false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available");
521  }
522 }
523 
524 void AgentBasePrivate::itemsRemoved(const Akonadi::Item::List &items)
525 {
526  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3 *>(mObserver);
527  if (observer3) {
528  observer3->itemsRemoved(items);
529  } else {
530  Q_ASSERT_X(false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available");
531  }
532 }
533 
534 void AgentBasePrivate::itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
535 {
536  if (!mObserver) {
537  changeProcessed();
538  return;
539  }
540 
541  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3 *>(mObserver);
542  if (observer3) {
543  observer3->itemsLinked(items, collection);
544  } else {
545  Q_ASSERT_X(false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available");
546  }
547 }
548 
549 void AgentBasePrivate::itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
550 {
551  if (!mObserver) {
552  return;
553  }
554 
555  AgentBase::ObserverV3 *observer3 = dynamic_cast<AgentBase::ObserverV3 *>(mObserver);
556  if (observer3) {
557  observer3->itemsUnlinked(items, collection);
558  } else {
559  Q_ASSERT_X(false, Q_FUNC_INFO, "Batch slots must never be called when ObserverV3 is not available");
560  }
561 }
562 
563 void AgentBasePrivate::tagAdded(const Akonadi::Tag &tag)
564 {
565  if (!mObserver) {
566  return;
567  }
568 
569  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4 *>(mObserver);
570  if (observer4) {
571  observer4->tagAdded(tag);
572  } else {
573  changeProcessed();
574  }
575 }
576 
577 void AgentBasePrivate::tagChanged(const Akonadi::Tag &tag)
578 {
579  if (!mObserver) {
580  return;
581  }
582 
583  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4 *>(mObserver);
584  if (observer4) {
585  observer4->tagChanged(tag);
586  } else {
587  changeProcessed();
588  }
589 }
590 
591 void AgentBasePrivate::tagRemoved(const Akonadi::Tag &tag)
592 {
593  if (!mObserver) {
594  return;
595  }
596 
597  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4 *>(mObserver);
598  if (observer4) {
599  observer4->tagRemoved(tag);;
600  } else {
601  changeProcessed();
602  }
603 }
604 
605 void AgentBasePrivate::itemsTagsChanged(const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags, const QSet<Akonadi::Tag> &removedTags)
606 {
607  if (!mObserver) {
608  return;
609  }
610 
611  AgentBase::ObserverV4 *observer4 = dynamic_cast<AgentBase::ObserverV4 *>(mObserver);
612  if (observer4) {
613  observer4->itemsTagsChanged(items, addedTags, removedTags);
614  } else {
615  changeProcessed();
616  }
617 }
618 
619 void AgentBasePrivate::collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent)
620 {
621  if (mObserver != 0) {
622  mObserver->collectionAdded(collection, parent);
623  }
624 }
625 
626 void AgentBasePrivate::collectionChanged(const Akonadi::Collection &collection)
627 {
628  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
629  if (mObserver != 0 && observer2 == 0) { // For ObserverV2 we use the variant with the part identifiers
630  mObserver->collectionChanged(collection);
631  }
632 }
633 
634 void AgentBasePrivate::collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes)
635 {
636  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
637  if (observer2 != 0) {
638  observer2->collectionChanged(collection, changedAttributes);
639  }
640 }
641 
642 void AgentBasePrivate::collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &dest)
643 {
644  AgentBase::ObserverV2 *observer2 = dynamic_cast<AgentBase::ObserverV2 *>(mObserver);
645  if (observer2) {
646  observer2->collectionMoved(collection, source, dest);
647  } else if (mObserver) {
648  // ### we cannot just call collectionRemoved here as this will already trigger changeProcessed()
649  // so, just collectionAdded() is good enough as no resource can have implemented intra-resource moves anyway
650  // without using ObserverV2
651  mObserver->collectionAdded(collection, dest);
652  } else {
653  changeProcessed();
654  }
655 }
656 
657 void AgentBasePrivate::collectionRemoved(const Akonadi::Collection &collection)
658 {
659  if (mObserver != 0) {
660  mObserver->collectionRemoved(collection);
661  }
662 }
663 
664 void AgentBasePrivate::collectionSubscribed(const Akonadi::Collection &collection, const Akonadi::Collection &parent)
665 {
666  Q_UNUSED(collection);
667  Q_UNUSED(parent);
668  changeProcessed();
669 }
670 
671 void AgentBasePrivate::collectionUnsubscribed(const Akonadi::Collection &collection)
672 {
673  Q_UNUSED(collection);
674  changeProcessed();
675 }
676 
677 void AgentBasePrivate::changeProcessed()
678 {
679  mChangeRecorder->changeProcessed();
680  QTimer::singleShot(0, mChangeRecorder, SLOT(replayNext()));
681 }
682 
683 void AgentBasePrivate::slotStatus(int status, const QString &message)
684 {
685  mStatusMessage = message;
686  mStatusCode = 0;
687 
688  switch (status) {
689  case AgentBase::Idle:
690  if (mStatusMessage.isEmpty()) {
691  mStatusMessage = defaultReadyMessage();
692  }
693 
694  mStatusCode = 0;
695  break;
696  case AgentBase::Running:
697  if (mStatusMessage.isEmpty()) {
698  mStatusMessage = defaultSyncingMessage();
699  }
700 
701  mStatusCode = 1;
702  break;
703  case AgentBase::Broken:
704  if (mStatusMessage.isEmpty()) {
705  mStatusMessage = defaultErrorMessage();
706  }
707 
708  mStatusCode = 2;
709  break;
710 
711  case AgentBase::NotConfigured:
712  if (mStatusMessage.isEmpty()) {
713  mStatusMessage = defaultUnconfiguredMessage();
714  }
715 
716  mStatusCode = 3;
717  break;
718 
719  default:
720  Q_ASSERT(!"Unknown status passed");
721  break;
722  }
723 }
724 
725 void AgentBasePrivate::slotPercent(int progress)
726 {
727  mProgress = progress;
728 }
729 
730 void AgentBasePrivate::slotWarning(const QString &message)
731 {
732  mTracer->warning(QString::fromLatin1("AgentBase(%1)").arg(mId), message);
733 }
734 
735 void AgentBasePrivate::slotError(const QString &message)
736 {
737  mTracer->error(QString::fromLatin1("AgentBase(%1)").arg(mId), message);
738 }
739 
740 void AgentBasePrivate::slotNetworkStatusChange(Solid::Networking::Status stat)
741 {
742  Q_UNUSED(stat);
743  Q_Q(AgentBase);
744  q->setOnlineInternal(mDesiredOnlineState);
745 }
746 
747 void AgentBasePrivate::slotResumedFromSuspend()
748 {
749  if (mNeedsNetwork) {
750  slotNetworkStatusChange(Solid::Networking::status());
751  }
752 }
753 
754 void AgentBasePrivate::slotTemporaryOfflineTimeout()
755 {
756  Q_Q(AgentBase);
757  q->setOnlineInternal(true);
758 }
759 
760 QString AgentBasePrivate::dumpNotificationListToString() const
761 {
762  return mChangeRecorder->dumpNotificationListToString();
763 }
764 
765 void AgentBasePrivate::dumpMemoryInfo() const
766 {
767  // Send it to stdout, so we can debug user problems.
768  // since you have to explicitely call this
769  // it won't flood users with release builds.
770  QTextStream stream(stdout);
771  stream << dumpMemoryInfoToString();
772 }
773 
774 QString AgentBasePrivate::dumpMemoryInfoToString() const
775 {
776  // man mallinfo for more info
777  QString str;
778 #if defined __GLIBC__
779  struct mallinfo mi;
780  mi = mallinfo();
781  QTextStream stream(&str);
782  stream
783  << "Total non-mmapped bytes (arena): " << mi.arena << '\n'
784  << "# of free chunks (ordblks): " << mi.ordblks << '\n'
785  << "# of free fastbin blocks (smblks>: " << mi.smblks << '\n'
786  << "# of mapped regions (hblks): " << mi.hblks << '\n'
787  << "Bytes in mapped regions (hblkhd): " << mi.hblkhd << '\n'
788  << "Max. total allocated space (usmblks): " << mi.usmblks << '\n'
789  << "Free bytes held in fastbins (fsmblks):" << mi.fsmblks << '\n'
790  << "Total allocated space (uordblks): " << mi.uordblks << '\n'
791  << "Total free space (fordblks): " << mi.fordblks << '\n'
792  << "Topmost releasable block (keepcost): " << mi.keepcost << '\n';
793 #else
794  str = QLatin1String( "mallinfo() not supported" );
795 #endif
796  return str;
797 }
798 
799 AgentBase::AgentBase(const QString &id)
800  : d_ptr(new AgentBasePrivate(this))
801 {
802  sAgentBase = this;
803  d_ptr->mId = id;
804  d_ptr->init();
805 }
806 
807 AgentBase::AgentBase(AgentBasePrivate *d, const QString &id)
808  : d_ptr(d)
809 {
810  sAgentBase = this;
811  d_ptr->mId = id;
812  d_ptr->init();
813 }
814 
815 AgentBase::~AgentBase()
816 {
817  delete d_ptr;
818 }
819 
820 QString AgentBase::parseArguments(int argc, char **argv)
821 {
822  QString identifier;
823  if (argc < 3) {
824  kDebug() << "Not enough arguments passed...";
825  exit(1);
826  }
827 
828  for (int i = 1; i < argc - 1; ++i) {
829  if (QLatin1String(argv[i]) == QLatin1String("--identifier")) {
830  identifier = QLatin1String(argv[i + 1]);
831  }
832  }
833 
834  if (identifier.isEmpty()) {
835  kDebug() << "Identifier argument missing";
836  exit(1);
837  }
838 
839  const QFileInfo fi(QString::fromLocal8Bit(argv[0]));
840  // strip off full path and possible .exe suffix
841  const QByteArray catalog = fi.baseName().toLatin1();
842 
843  KCmdLineArgs::init(argc, argv, ServerManager::addNamespace(identifier).toLatin1(), catalog, ki18n("Akonadi Agent"), KDEPIMLIBS_VERSION,
844  ki18n("Akonadi Agent"));
845 
846  KCmdLineOptions options;
847  options.add("identifier <argument>", ki18n("Agent identifier"));
848  KCmdLineArgs::addCmdLineOptions(options);
849 
850  return identifier;
851 }
852 
853 // @endcond
854 
855 int AgentBase::init(AgentBase *r)
856 {
857  QApplication::setQuitOnLastWindowClosed(false);
858  KGlobal::locale()->insertCatalog(QLatin1String("libakonadi"));
859  int rv = kapp->exec();
860  delete r;
861  return rv;
862 }
863 
864 int AgentBase::status() const
865 {
866  Q_D(const AgentBase);
867 
868  return d->mStatusCode;
869 }
870 
871 QString AgentBase::statusMessage() const
872 {
873  Q_D(const AgentBase);
874 
875  return d->mStatusMessage;
876 }
877 
878 int AgentBase::progress() const
879 {
880  Q_D(const AgentBase);
881 
882  return d->mProgress;
883 }
884 
885 QString AgentBase::progressMessage() const
886 {
887  Q_D(const AgentBase);
888 
889  return d->mProgressMessage;
890 }
891 
892 bool AgentBase::isOnline() const
893 {
894  Q_D(const AgentBase);
895 
896  return d->mOnline;
897 }
898 
899 void AgentBase::setNeedsNetwork(bool needsNetwork)
900 {
901  Q_D(AgentBase);
902  d->mNeedsNetwork = needsNetwork;
903 
904  if (d->mNeedsNetwork) {
905  connect(Solid::Networking::notifier()
906  , SIGNAL(statusChanged(Solid::Networking::Status))
907  , this, SLOT(slotNetworkStatusChange(Solid::Networking::Status))
908  , Qt::UniqueConnection);
909 
910  } else {
911  disconnect(Solid::Networking::notifier(), 0, 0, 0);
912  setOnlineInternal(d->mDesiredOnlineState);
913  }
914 }
915 
916 void AgentBase::setOnline(bool state)
917 {
918  Q_D(AgentBase);
919  d->mDesiredOnlineState = state;
920  d->mSettings->setValue(QLatin1String("Agent/DesiredOnlineState"), state);
921  setOnlineInternal(state);
922 }
923 
924 void AgentBase::setTemporaryOffline(int makeOnlineInSeconds)
925 {
926  Q_D(AgentBase);
927 
928  // if not currently online, avoid bringing it online after the timeout
929  if (!d->mOnline) {
930  return;
931  }
932 
933  setOnlineInternal(false);
934 
935  if (!d->mTemporaryOfflineTimer) {
936  d->mTemporaryOfflineTimer = new QTimer(d);
937  d->mTemporaryOfflineTimer->setSingleShot(true);
938  connect(d->mTemporaryOfflineTimer, SIGNAL(timeout()), this, SLOT(slotTemporaryOfflineTimeout()));
939  }
940  d->mTemporaryOfflineTimer->setInterval(makeOnlineInSeconds * 1000);
941  d->mTemporaryOfflineTimer->start();
942 }
943 
944 void AgentBase::setOnlineInternal( bool state )
945 {
946  Q_D(AgentBase);
947  if (state && d->mNeedsNetwork) {
948  const Solid::Networking::Status stat = Solid::Networking::status();
949  if (stat != Solid::Networking::Unknown && stat != Solid::Networking::Connected) {
950  //Don't go online if the resource needs network but there is none
951  state = false;
952  }
953  }
954  d->mOnline = state;
955 
956  if (d->mTemporaryOfflineTimer) {
957  d->mTemporaryOfflineTimer->stop();
958  }
959 
960  const QString newMessage = d->defaultReadyMessage();
961  if ( d->mStatusMessage != newMessage && d->mStatusCode != AgentBase::Broken ) {
962  emit status( d->mStatusCode, newMessage );
963  }
964 
965  doSetOnline(state);
966  emit onlineChanged(state);
967 }
968 
969 void AgentBase::doSetOnline(bool online)
970 {
971  Q_UNUSED(online);
972 }
973 
974 void AgentBase::configure(WId windowId)
975 {
976  Q_UNUSED(windowId);
977  emit configurationDialogAccepted();
978 }
979 
980 #ifdef Q_OS_WIN //krazy:exclude=cpp
981 void AgentBase::configure(qlonglong windowId)
982 {
983  configure(reinterpret_cast<WId>(windowId));
984 }
985 #endif
986 
987 WId AgentBase::winIdForDialogs() const
988 {
989  const bool registered = DBusConnectionPool::threadConnection().interface()->isServiceRegistered(QLatin1String("org.freedesktop.akonaditray"));
990  if (!registered) {
991  return 0;
992  }
993 
994  QDBusInterface dbus(QLatin1String("org.freedesktop.akonaditray"), QLatin1String("/Actions"),
995  QLatin1String("org.freedesktop.Akonadi.Tray"));
996  const QDBusMessage reply = dbus.call(QLatin1String("getWinId"));
997 
998  if (reply.type() == QDBusMessage::ErrorMessage) {
999  return 0;
1000  }
1001 
1002  const WId winid = (WId)reply.arguments().at(0).toLongLong();
1003 
1004  return winid;
1005 }
1006 
1007 void AgentBase::quit()
1008 {
1009  Q_D(AgentBase);
1010  aboutToQuit();
1011 
1012  if (d->mSettings) {
1013  d->mChangeRecorder->setConfig(0);
1014  d->mSettings->sync();
1015  }
1016 
1017  KGlobal::deref();
1018 }
1019 
1020 void AgentBase::aboutToQuit()
1021 {
1022 }
1023 
1024 void AgentBase::cleanup()
1025 {
1026  Q_D(AgentBase);
1027  // prevent the monitor from picking up deletion signals for our own data if we are a resource
1028  // and thus avoid that we kill our own data as last act before our own death
1029  d->mChangeRecorder->blockSignals(true);
1030 
1031  aboutToQuit();
1032 
1033  const QString fileName = d->mSettings->fileName();
1034 
1035  /*
1036  * First destroy the settings object...
1037  */
1038  d->mChangeRecorder->setConfig(0);
1039  delete d->mSettings;
1040  d->mSettings = 0;
1041 
1042  /*
1043  * ... then remove the file from hd.
1044  */
1045  QFile::remove(fileName);
1046 
1047  /*
1048  * ... and remove the changes file from hd.
1049  */
1050  QFile::remove(fileName + QLatin1String("_changes.dat"));
1051 
1052  /*
1053  * ... and also remove the agent configuration file if there is one.
1054  */
1055  QString configFile = KStandardDirs::locateLocal("config", config()->name());
1056  QFile::remove(configFile);
1057 
1058  KGlobal::deref();
1059 }
1060 
1061 void AgentBase::registerObserver(Observer *observer)
1062 {
1063  // TODO in theory we should re-connect change recorder signals here that we disconnected previously
1064  d_ptr->mObserver = observer;
1065 
1066  const bool hasObserverV3 = (dynamic_cast<AgentBase::ObserverV3 *>(d_ptr->mObserver) != 0);
1067  const bool hasObserverV4 = (dynamic_cast<AgentBase::ObserverV4 *>(d_ptr->mObserver) != 0);
1068 
1069  disconnect(d_ptr->mChangeRecorder, SIGNAL(tagAdded(Akonadi::Tag)),
1070  d_ptr, SLOT(tagAdded(Akonadi::Tag)));
1071  disconnect(d_ptr->mChangeRecorder, SIGNAL(tagChanged(Akonadi::Tag)),
1072  d_ptr, SLOT(tagChanged(Akonadi::Tag)));
1073  disconnect(d_ptr->mChangeRecorder, SIGNAL(tagRemoved(Akonadi::Tag)),
1074  d_ptr, SLOT(tagRemoved(Akonadi::Tag)));
1075  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
1076  d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)));
1077  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
1078  d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)));
1079  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
1080  d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)));
1081  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsRemoved(Akonadi::Item::List)),
1082  d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)));
1083  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
1084  d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)));
1085  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
1086  d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)));
1087  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
1088  d_ptr, SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)));
1089  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
1090  d_ptr, SLOT(itemRemoved(Akonadi::Item)));
1091  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
1092  d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)));
1093  disconnect(d_ptr->mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
1094  d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)));
1095 
1096  if (hasObserverV4) {
1097  connect(d_ptr->mChangeRecorder, SIGNAL(tagAdded(Akonadi::Tag)),
1098  d_ptr, SLOT(tagAdded(Akonadi::Tag)));
1099  connect(d_ptr->mChangeRecorder, SIGNAL(tagChanged(Akonadi::Tag)),
1100  d_ptr, SLOT(tagChanged(Akonadi::Tag)));
1101  connect(d_ptr->mChangeRecorder, SIGNAL(tagRemoved(Akonadi::Tag)),
1102  d_ptr, SLOT(tagRemoved(Akonadi::Tag)));
1103  connect(d_ptr->mChangeRecorder, SIGNAL(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)),
1104  d_ptr, SLOT(itemsTagsChanged(Akonadi::Item::List,QSet<Akonadi::Tag>,QSet<Akonadi::Tag>)));
1105  }
1106 
1107  if (hasObserverV3) {
1108  connect(d_ptr->mChangeRecorder, SIGNAL(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)),
1109  d_ptr, SLOT(itemsFlagsChanged(Akonadi::Item::List,QSet<QByteArray>,QSet<QByteArray>)));
1110  connect(d_ptr->mChangeRecorder, SIGNAL(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)),
1111  d_ptr, SLOT(itemsMoved(Akonadi::Item::List,Akonadi::Collection,Akonadi::Collection)));
1112  connect(d_ptr->mChangeRecorder, SIGNAL(itemsRemoved(Akonadi::Item::List)),
1113  d_ptr, SLOT(itemsRemoved(Akonadi::Item::List)));
1114  connect(d_ptr->mChangeRecorder, SIGNAL(itemsLinked(Akonadi::Item::List,Akonadi::Collection)),
1115  d_ptr, SLOT(itemsLinked(Akonadi::Item::List,Akonadi::Collection)));
1116  connect(d_ptr->mChangeRecorder, SIGNAL(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)),
1117  d_ptr, SLOT(itemsUnlinked(Akonadi::Item::List,Akonadi::Collection)));
1118  } else {
1119  // V2 - don't connect these if we have V3
1120  connect(d_ptr->mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
1121  d_ptr, SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)));
1122  connect(d_ptr->mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
1123  d_ptr, SLOT(itemRemoved(Akonadi::Item)));
1124  connect(d_ptr->mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
1125  d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)));
1126  connect(d_ptr->mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
1127  d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)));
1128  }
1129 }
1130 
1131 QString AgentBase::identifier() const
1132 {
1133  return d_ptr->mId;
1134 }
1135 
1136 void AgentBase::setAgentName(const QString &name)
1137 {
1138  Q_D(AgentBase);
1139  if (name == d->mName) {
1140  return;
1141  }
1142 
1143  // TODO: rename collection
1144  d->mName = name;
1145 
1146  if (d->mName.isEmpty() || d->mName == d->mId) {
1147  d->mSettings->remove(QLatin1String("Resource/Name"));
1148  d->mSettings->remove(QLatin1String("Agent/Name"));
1149  } else
1150  d->mSettings->setValue(QLatin1String("Agent/Name"), d->mName);
1151 
1152  d->mSettings->sync();
1153 
1154  d->setProgramName();
1155 
1156  emit agentNameChanged(d->mName);
1157 }
1158 
1159 QString AgentBase::agentName() const
1160 {
1161  Q_D(const AgentBase);
1162  if (d->mName.isEmpty()) {
1163  return d->mId;
1164  } else {
1165  return d->mName;
1166  }
1167 }
1168 
1169 void AgentBase::changeProcessed()
1170 {
1171  Q_D(AgentBase);
1172  d->changeProcessed();
1173 }
1174 
1175 ChangeRecorder *AgentBase::changeRecorder() const
1176 {
1177  return d_ptr->mChangeRecorder;
1178 }
1179 
1180 KSharedConfigPtr AgentBase::config()
1181 {
1182  if (QCoreApplication::instance()->thread() == QThread::currentThread()) {
1183  return KGlobal::config();
1184  } else {
1185  return componentData().config();
1186  }
1187 }
1188 
1189 void AgentBase::abort()
1190 {
1191  emit abortRequested();
1192 }
1193 
1194 void AgentBase::reconfigure()
1195 {
1196  emit reloadConfiguration();
1197 }
1198 
1199 extern QThreadStorage<KComponentData *> s_agentComponentDatas;
1200 
1201 KComponentData AgentBase::componentData()
1202 {
1203  if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
1204  if (s_agentComponentDatas.hasLocalData()) {
1205  return *(s_agentComponentDatas.localData());
1206  } else {
1207  return KGlobal::mainComponent();
1208  }
1209  }
1210 
1211  Q_ASSERT(s_agentComponentDatas.hasLocalData());
1212  return *(s_agentComponentDatas.localData());
1213 }
1214 
1215 #include "moc_agentbase.cpp"
1216 #include "moc_agentbase_p.cpp"
QTimer::setInterval
void setInterval(int msec)
Akonadi::AgentBase::winIdForDialogs
WId winIdForDialogs() const
This method returns the windows id, which should be used for dialogs.
Akonadi::AgentBase::ObserverV4::itemsTagsChanged
virtual void itemsTagsChanged(const Akonadi::Item::List &items, const QSet< Akonadi::Tag > &addedTags, const QSet< Akonadi::Tag > &removedTags)
Reimplement to handle items tagging.
Definition: agentbase.cpp:276
Akonadi::AgentBase::ObserverV3::itemsUnlinked
virtual void itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
Reimplement to handle batch notifications about items unlinking.
Definition: agentbase.cpp:227
Akonadi::AgentBase::ObserverV3::itemsMoved
virtual void itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &sourceCollection, const Akonadi::Collection &destinationCollection)
Reimplement to handle batch notification about items move.
Definition: agentbase.cpp:188
QSettings::sync
void sync()
QApplication::setQuitOnLastWindowClosed
void setQuitOnLastWindowClosed(bool quit)
Akonadi::AgentBase::percent
void percent(int progress)
This signal should be emitted whenever the progress of an action in the agent (e.g.
Akonadi::AgentBase::abortRequested
void abortRequested()
Emitted when another application has remotely asked the agent to abort its current operation...
Akonadi::AgentBase::NotConfigured
The agent is lacking required configuration.
Definition: agentbase.h:415
Akonadi::AgentBase::ObserverV4::tagAdded
virtual void tagAdded(const Akonadi::Tag &tag)
Reimplement to handle tags additions.
Definition: agentbase.cpp:240
Akonadi::AgentBase::AgentBase
AgentBase(const QString &id)
Creates an agent base.
QByteArray
Akonadi::AgentBase::ObserverV4::tagRemoved
virtual void tagRemoved(const Akonadi::Tag &tag)
Reimplement to handle tags removal.
Definition: agentbase.cpp:264
QFile::remove
bool remove()
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::AgentInstance::type
AgentType type() const
Returns the agent type of this instance.
Definition: agentinstance.cpp:50
Akonadi::AgentBase::ObserverV2::itemMoved
virtual void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination)
Reimplement to handle item moves.
Definition: agentbase.cpp:124
Akonadi::AgentBase::setNeedsNetwork
void setNeedsNetwork(bool needsNetwork)
Sets whether the agent needs network or not.
Akonadi::AgentType::name
QString name() const
Returns the i18n'ed name of the agent type.
Definition: agenttype.cpp:51
QDBusMessage::arguments
QList< QVariant > arguments() const
Akonadi::AgentBase::ObserverV2::collectionMoved
virtual void collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination)
Reimplement to handle collection moves.
Definition: agentbase.cpp:158
Akonadi::AgentBase::Observer
The interface for reacting on monitored or replayed changes.
Definition: agentbase.h:186
Akonadi::AgentBase::componentData
static KComponentData componentData()
Returns the component data object for this agent instance.
Definition: agentbase.cpp:1201
Akonadi::AgentBase::agentNameChanged
void agentNameChanged(const QString &name)
This signal is emitted whenever the name of the agent has changed.
QDBusMessage::type
MessageType type() const
Akonadi::AgentBase::reloadConfiguration
void reloadConfiguration()
Emitted if another application has changed the agent's configuration remotely and called AgentInstanc...
Akonadi::SessionPrivate::createDefaultSession
static void createDefaultSession(const QByteArray &sessionId)
Creates a new default session for this thread with the given sessionId.
Definition: session.cpp:481
Akonadi::ServerManager::serviceName
static QString serviceName(ServiceType serviceType)
Returns the namespaced D-Bus service name for serviceType.
Definition: servermanager.cpp:307
Akonadi::AgentBase::configurationDialogAccepted
void configurationDialogAccepted()
This signal is emitted whenever the user has accepted the configuration dialog.
Akonadi::AgentBase::ObserverV2::collectionChanged
virtual void collectionChanged(const Akonadi::Collection &collection, const QSet< QByteArray > &changedAttributes)
Reimplement to handle changes to existing collections.
Definition: agentbase.cpp:168
QObject::thread
QThread * thread() const
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Akonadi::Session::defaultSession
static Session * defaultSession()
Returns the default session for this thread.
Definition: session.cpp:496
QTextStream
Akonadi::AgentBase::~AgentBase
~AgentBase()
Destroys the agent base.
Akonadi::AgentBasePrivate
Definition: agentbase_p.h:39
Akonadi::AgentBase
The base class for all Akonadi agents and resources.
Definition: agentbase.h:80
QSettings::setValue
void setValue(const QString &key, const QVariant &value)
QObject::name
const char * name() const
Akonadi::AgentBase::Observer::itemChanged
virtual void itemChanged(const Akonadi::Item &item, const QSet< QByteArray > &partIdentifiers)
Reimplement to handle changes to existing items.
Definition: agentbase.cpp:82
Akonadi::AgentBase::setAgentName
void setAgentName(const QString &name)
This method is used to set the name of the agent.
Definition: agentbase.cpp:1136
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
Akonadi::AgentBase::error
void error(const QString &message)
This signal shall be used to report errors.
Akonadi::AgentBase::aboutToQuit
virtual void aboutToQuit()
This method is called whenever the agent application is about to quit.
Akonadi::AgentBase::Observer::~Observer
virtual ~Observer()
Destroys the observer instance.
Definition: agentbase.cpp:69
Akonadi::AgentBase::status
virtual int status() const
This method returns the current status code of the agent.
Akonadi::AgentBase::setOnline
void setOnline(bool state)
Sets whether the agent shall be online or not.
Akonadi::AgentBase::Observer::itemAdded
virtual void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle adding of new items.
Definition: agentbase.cpp:73
QTimer
Akonadi::AgentBase::ObserverV2::itemUnlinked
virtual void itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle item unlinking.
Definition: agentbase.cpp:146
Akonadi::AgentManager::instance
AgentInstance instance(const QString &identifier) const
Returns the agent instance with the given identifier or an invalid agent instance if the identifier d...
Definition: agentmanager.cpp:401
Akonadi::AgentBase::ObserverV3::itemsFlagsChanged
virtual void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet< QByteArray > &addedFlags, const QSet< QByteArray > &removedFlags)
Reimplement to handle changes in flags of existing items.
Definition: agentbase.cpp:174
QSettings::fileName
QString fileName() const
Akonadi::AgentBase::config
KSharedConfigPtr config()
Returns the config object for this Agent.
Definition: agentbase.cpp:1180
Akonadi::AgentBase::doSetOnline
virtual void doSetOnline(bool online)
This method is called whenever the online status has changed.
Akonadi::AgentBase::configure
virtual void configure(WId windowId)
This method is called whenever the agent shall show its configuration dialog to the user...
QString::isEmpty
bool isEmpty() const
Akonadi::AgentBase::ObserverV2
BC extension of Observer with support for monitoring item and collection moves.
Definition: agentbase.h:245
Akonadi::AgentBase::Observer::itemRemoved
virtual void itemRemoved(const Akonadi::Item &item)
Reimplement to handle deletion of items.
Definition: agentbase.cpp:91
Akonadi::AgentBase::cleanup
virtual void cleanup()
This method is called when the agent is removed from the system, so it can do some cleanup stuff...
QCoreApplication::instance
QCoreApplication * instance()
QSet< QByteArray >
QString
Akonadi::ServerManager::agentServiceName
static QString agentServiceName(ServiceAgentType agentType, const QString &identifier)
Returns the namespaced D-Bus service name for an agent of type agentType with agent identifier identi...
Definition: servermanager.cpp:323
Akonadi::AgentBase::ObserverV3
BC extension of ObserverV2 with support for batch operations.
Definition: agentbase.h:310
Akonadi::AgentBase::statusMessage
virtual QString statusMessage() const
This method returns an i18n'ed description of the current status code.
QDBusInterface
QFileInfo
QObject::blockSignals
bool blockSignals(bool block)
QSettings
QThreadStorage
QSettings::remove
void remove(const QString &key)
Akonadi::AgentBase::ObserverV4::tagChanged
virtual void tagChanged(const Akonadi::Tag &tag)
Reimplement to handle tags changes.
Definition: agentbase.cpp:252
QTimer::stop
void stop()
QDBusConnection::connectToBus
QDBusConnection connectToBus(BusType type, const QString &name)
Akonadi::AgentBase::Observer::collectionRemoved
virtual void collectionRemoved(const Akonadi::Collection &collection)
Reimplement to handle deletion of collections.
Definition: agentbase.cpp:116
Akonadi::ChangeRecorder::setConfig
void setConfig(QSettings *settings)
Sets the QSettings object used for persistent recorded changes.
Definition: changerecorder.cpp:42
Akonadi::AgentBase::ObserverV3::itemsRemoved
virtual void itemsRemoved(const Akonadi::Item::List &items)
Reimplement to handle batch notification about items deletion.
Definition: agentbase.cpp:202
Akonadi::AgentBase::Broken
The agent encountered an error state.
Definition: agentbase.h:414
Akonadi::AgentBase::progress
virtual int progress() const
This method returns the current progress of the agent in percentage.
Akonadi::AgentBase::Observer::Observer
Observer()
Creates an observer instance.
Definition: agentbase.cpp:65
Akonadi::AgentBase::identifier
QString identifier() const
Returns the instance identifier of this agent.
Definition: agentbase.cpp:1131
Akonadi::AgentBase::Observer::collectionChanged
virtual void collectionChanged(const Akonadi::Collection &collection)
Reimplement to handle changes to existing collections.
Definition: agentbase.cpp:108
Akonadi::AgentBase::changeRecorder
ChangeRecorder * changeRecorder() const
Returns the Akonadi::ChangeRecorder object used for monitoring.
Definition: agentbase.cpp:1175
QDBusMessage
Akonadi::AgentBase::registerObserver
void registerObserver(Observer *observer)
Registers the given observer for reacting on monitored or recorded changes.
Definition: agentbase.cpp:1061
QLatin1String
QThread::currentThread
QThread * currentThread()
Akonadi::AgentBase::isOnline
bool isOnline() const
Returns whether the agent is currently online.
Akonadi::AgentBase::changeProcessed
void changeProcessed()
Marks the current change as processes and replays the next change if change recording is enabled (noo...
Definition: agentbase.cpp:1169
Akonadi::AgentBase::ObserverV4
Observer that adds support for item tagging.
Definition: agentbase.h:369
Akonadi::Tag
An Akonadi Tag.
Definition: tag.h:43
Akonadi::AgentBase::ObserverV3::itemsLinked
virtual void itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection)
Reimplement to handle batch notifications about items linking.
Definition: agentbase.cpp:214
Akonadi::AgentBase::ObserverV2::itemLinked
virtual void itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection)
Reimplement to handle item linking.
Definition: agentbase.cpp:134
Akonadi::AgentManager::self
static AgentManager * self()
Returns the global instance of the agent manager.
Definition: agentmanager.cpp:377
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QTimer::start
void start(int msec)
Akonadi::AgentBase::init
static int init(int argc, char **argv)
Use this method in the main function of your agent application to initialize your agent subclass...
Definition: agentbase.h:443
Akonadi::Collection::resource
QString resource() const
Returns the identifier of the resource owning the collection.
Definition: collection.cpp:207
Akonadi::AgentBase::onlineChanged
void onlineChanged(bool online)
Emitted when the online state changed.
QDBusContext::message
const QDBusMessage & message() const
Akonadi::AgentBase::Running
The agent is working on something.
Definition: agentbase.h:413
Akonadi::AgentBase::warning
void warning(const QString &message)
This signal shall be used to report warnings.
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Akonadi::ServerManager::addNamespace
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with '_' as separator).
Definition: servermanager.cpp:337
QObject::parent
QObject * parent() const
Akonadi::AgentBase::Observer::collectionAdded
virtual void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent)
Reimplement to handle adding of new collections.
Definition: agentbase.cpp:99
Akonadi::AgentBase::progressMessage
virtual QString progressMessage() const
This method returns an i18n'ed description of the current progress.
Akonadi::AgentBase::Idle
The agent does currently nothing.
Definition: agentbase.h:412
Akonadi::AgentBase::agentName
QString agentName() const
Returns the name of the agent.
Definition: agentbase.cpp:1159
Akonadi::ChangeRecorder
Records and replays change notification.
Definition: changerecorder.h:47
QTimer::singleShot
singleShot
Akonadi::AgentBase::setTemporaryOffline
void setTemporaryOffline(int makeOnlineInSeconds=300)
Sets the agent offline but will make it online again after a given time.
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:02 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal