Akonadi

specialcollectionshelperjobs.cpp
1 /*
2  Copyright (c) 2009 Constantin Berzan <[email protected]>
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 "specialcollectionshelperjobs_p.h"
21 
22 #include <QDBusConnection>
23 #include "specialcollectionattribute.h"
24 #include "specialcollections.h"
25 #include "servermanager.h"
26 
27 
28 #include "agentinstance.h"
29 #include "agentinstancecreatejob.h"
30 #include "agentmanager.h"
31 #include "collectionfetchjob.h"
32 #include "collectionfetchscope.h"
33 #include "collectionmodifyjob.h"
34 #include "entitydisplayattribute.h"
35 #include "resourcesynchronizationjob.h"
36 
37 #include "akonadicore_debug.h"
38 
39 #include <KLocalizedString>
40 #include <KCoreConfigSkeleton>
41 
42 #include <QDBusConnectionInterface>
43 #include <QDBusInterface>
44 #include <QDBusServiceWatcher>
45 #include <QMetaMethod>
46 #include <QTime>
47 #include <QTimer>
48 
49 #define LOCK_WAIT_TIMEOUT_SECONDS 30
50 
51 using namespace Akonadi;
52 
53 // convenient methods to get/set the default resource id
54 static void setDefaultResourceId(KCoreConfigSkeleton *settings, const QString &value)
55 {
56  KConfigSkeletonItem *item = settings->findItem(QStringLiteral("DefaultResourceId"));
57  Q_ASSERT(item);
58  item->setProperty(value);
59 }
60 
61 static QString defaultResourceId(KCoreConfigSkeleton *settings)
62 {
63  const KConfigSkeletonItem *item = settings->findItem(QStringLiteral("DefaultResourceId"));
64  Q_ASSERT(item);
65  return item->property().toString();
66 }
67 
68 static QString dbusServiceName()
69 {
70  QString service = QStringLiteral("org.kde.pim.SpecialCollections");
72  return service + ServerManager::instanceIdentifier();
73  }
74  return service;
75 }
76 
77 static QVariant::Type argumentType(const QMetaObject *mo, const QString &method)
78 {
79  QMetaMethod m;
80  for (int i = 0; i < mo->methodCount(); ++i) {
81  const QString signature = QString::fromLatin1(mo->method(i).methodSignature());
82  if (signature.startsWith(method)) {
83  m = mo->method(i);
84  }
85  }
86 
87  if (m.methodSignature().isEmpty()) {
88  return QVariant::Invalid;
89  }
90 
91  const QList<QByteArray> argTypes = m.parameterTypes();
92  if (argTypes.count() != 1) {
93  return QVariant::Invalid;
94  }
95 
96  return QVariant::nameToType(argTypes.first().constData());
97 }
98 
99 // ===================== ResourceScanJob ============================
100 
104 class Q_DECL_HIDDEN Akonadi::ResourceScanJob::Private
105 {
106 public:
107  Private(KCoreConfigSkeleton *settings, ResourceScanJob *qq);
108 
109  void fetchResult(KJob *job); // slot
110 
111  ResourceScanJob *const q;
112 
113  // Input:
114  QString mResourceId;
115  KCoreConfigSkeleton *mSettings = nullptr;
116 
117  // Output:
118  Collection mRootCollection;
119  Collection::List mSpecialCollections;
120 };
121 
122 ResourceScanJob::Private::Private(KCoreConfigSkeleton *settings, ResourceScanJob *qq)
123  : q(qq)
124  , mSettings(settings)
125 {
126 }
127 
128 void ResourceScanJob::Private::fetchResult(KJob *job)
129 {
130  if (job->error()) {
131  qCWarning(AKONADICORE_LOG) << job->errorText();
132  return;
133  }
134 
136  Q_ASSERT(fetchJob);
137 
138  Q_ASSERT(!mRootCollection.isValid());
139  Q_ASSERT(mSpecialCollections.isEmpty());
140  const Akonadi::Collection::List lstCols = fetchJob->collections();
141  for (const Collection &collection : lstCols) {
142  if (collection.parentCollection() == Collection::root()) {
143  if (mRootCollection.isValid()) {
144  qCWarning(AKONADICORE_LOG) << "Resource has more than one root collection. I don't know what to do.";
145  } else {
146  mRootCollection = collection;
147  }
148  }
149 
150  if (collection.hasAttribute<SpecialCollectionAttribute>()) {
151  mSpecialCollections.append(collection);
152  }
153  }
154 
155  qCDebug(AKONADICORE_LOG) << "Fetched root collection" << mRootCollection.id()
156  << "and" << mSpecialCollections.count() << "local folders"
157  << "(total" << fetchJob->collections().count() << "collections).";
158 
159  if (!mRootCollection.isValid()) {
160  q->setError(Unknown);
161  q->setErrorText(i18n("Could not fetch root collection of resource %1.", mResourceId));
162  q->emitResult();
163  return;
164  }
165 
166  // We are done!
167  q->emitResult();
168 }
169 
170 ResourceScanJob::ResourceScanJob(const QString &resourceId, KCoreConfigSkeleton *settings, QObject *parent)
171  : Job(parent)
172  , d(new Private(settings, this))
173 {
174  setResourceId(resourceId);
175 }
176 
177 ResourceScanJob::~ResourceScanJob()
178 {
179  delete d;
180 }
181 
182 QString ResourceScanJob::resourceId() const
183 {
184  return d->mResourceId;
185 }
186 
187 void ResourceScanJob::setResourceId(const QString &resourceId)
188 {
189  d->mResourceId = resourceId;
190 }
191 
192 Akonadi::Collection ResourceScanJob::rootResourceCollection() const
193 {
194  return d->mRootCollection;
195 }
196 
197 Akonadi::Collection::List ResourceScanJob::specialCollections() const
198 {
199  return d->mSpecialCollections;
200 }
201 
202 void ResourceScanJob::doStart()
203 {
204  if (d->mResourceId.isEmpty()) {
205  if (!qobject_cast<DefaultResourceJob *>(this)) {
206  qCCritical(AKONADICORE_LOG) << "No resource ID given.";
208  setErrorText(i18n("No resource ID given."));
209  }
210  emitResult();
211  return;
212  }
213 
216  fetchJob->fetchScope().setResource(d->mResourceId);
217  fetchJob->fetchScope().setIncludeStatistics(true);
219  connect(fetchJob, &CollectionFetchJob::result, this, [this](KJob *job) { d->fetchResult(job); });
220 }
221 
222 // ===================== DefaultResourceJob ============================
223 
227 class Akonadi::DefaultResourceJobPrivate
228 {
229 public:
230  DefaultResourceJobPrivate(KCoreConfigSkeleton *settings, DefaultResourceJob *qq);
231 
232  void tryFetchResource();
233  void resourceCreateResult(KJob *job); // slot
234  void resourceSyncResult(KJob *job); // slot
235  void collectionFetchResult(KJob *job); // slot
236  void collectionModifyResult(KJob *job); // slot
237 
238  DefaultResourceJob *const q;
239  KCoreConfigSkeleton *mSettings = nullptr;
240  QVariantMap mDefaultResourceOptions;
241  QList<QByteArray> mKnownTypes;
242  QMap<QByteArray, QString> mNameForTypeMap;
243  QMap<QByteArray, QString> mIconForTypeMap;
244  QString mDefaultResourceType;
245  int mPendingModifyJobs = 0;
246  bool mResourceWasPreexisting = true;
247 };
248 
249 DefaultResourceJobPrivate::DefaultResourceJobPrivate(KCoreConfigSkeleton *settings, DefaultResourceJob *qq)
250  : q(qq)
251  , mSettings(settings)
252  , mPendingModifyJobs(0)
253  , mResourceWasPreexisting(true /* for safety, so as not to accidentally delete data */)
254 {
255 }
256 
257 void DefaultResourceJobPrivate::tryFetchResource()
258 {
259  // Get the resourceId from config. Another instance might have changed it in the meantime.
260  mSettings->load();
261 
262  const QString resourceId = defaultResourceId(mSettings);
263 
264  qCDebug(AKONADICORE_LOG) << "Read defaultResourceId" << resourceId << "from config.";
265 
266  const AgentInstance resource = AgentManager::self()->instance(resourceId);
267  if (resource.isValid()) {
268  // The resource exists; scan it.
269  mResourceWasPreexisting = true;
270  qCDebug(AKONADICORE_LOG) << "Found resource" << resourceId;
271  q->setResourceId(resourceId);
272 
274  fetchJob->fetchScope().setResource(resourceId);
275  fetchJob->fetchScope().setIncludeStatistics(true);
276  q->connect(fetchJob, &CollectionFetchJob::result, q, [this](KJob *job) { collectionFetchResult(job); });
277  } else {
278  // Try harder: maybe the default resource has been removed and another one added
279  // without updating the config file, in this case search for a resource
280  // of the same type and the default name
281  const AgentInstance::List resources = AgentManager::self()->instances();
282  for (const AgentInstance &resource : resources) {
283  if (resource.type().identifier() == mDefaultResourceType) {
284  if (resource.name() == mDefaultResourceOptions.value(QStringLiteral("Name")).toString()) {
285  // found a matching one...
286  setDefaultResourceId(mSettings, resource.identifier());
287  mSettings->save();
288  mResourceWasPreexisting = true;
289  qCDebug(AKONADICORE_LOG) << "Found resource" << resource.identifier();
290  q->setResourceId(resource.identifier());
291  q->ResourceScanJob::doStart();
292  return;
293  }
294  }
295  }
296 
297  // Create the resource.
298  mResourceWasPreexisting = false;
299  qCDebug(AKONADICORE_LOG) << "Creating maildir resource.";
300  const AgentType type = AgentManager::self()->type(mDefaultResourceType);
302  QObject::connect(job, &AgentInstanceCreateJob::result, q, [this](KJob *job) { resourceCreateResult(job); });
303  job->start(); // non-Akonadi::Job
304  }
305 }
306 
307 void DefaultResourceJobPrivate::resourceCreateResult(KJob *job)
308 {
309  if (job->error()) {
310  qCWarning(AKONADICORE_LOG) << job->errorText();
311  //fail( i18n( "Failed to create the default resource (%1).", job->errorString() ) );
312  q->setError(job->error());
313  q->setErrorText(job->errorText());
314  q->emitResult();
315  return;
316  }
317 
318  AgentInstance agent;
319 
320  // Get the resource instance.
321  {
323  Q_ASSERT(createJob);
324  agent = createJob->instance();
325  setDefaultResourceId(mSettings, agent.identifier());
326  qCDebug(AKONADICORE_LOG) << "Created maildir resource with id" << defaultResourceId(mSettings);
327  }
328 
329  const QString defaultId = defaultResourceId(mSettings);
330 
331  // Configure the resource.
332  {
333  agent.setName(mDefaultResourceOptions.value(QStringLiteral("Name")).toString());
334 
335  const auto service = ServerManager::agentServiceName(ServerManager::Resource, defaultId);
336  QDBusInterface conf(service, QStringLiteral("/Settings"), QString());
337 
338  if (!conf.isValid()) {
339  q->setError(-1);
340  q->setErrorText(i18n("Invalid resource identifier '%1'", defaultId));
341  q->emitResult();
342  return;
343  }
344 
345  QMap<QString, QVariant>::const_iterator it = mDefaultResourceOptions.cbegin();
346  const QMap<QString, QVariant>::const_iterator itEnd = mDefaultResourceOptions.cend();
347  for (;it != itEnd; ++it) {
348 
349  if (it.key() == QLatin1String("Name")) {
350  continue;
351  }
352 
353  const QString methodName = QStringLiteral("set%1").arg(it.key());
354  const QVariant::Type argType = argumentType(conf.metaObject(), methodName);
355  if (argType == QVariant::Invalid) {
356  q->setError(Job::Unknown);
357  q->setErrorText(i18n("Failed to configure default resource via D-Bus."));
358  q->emitResult();
359  return;
360  }
361 
362  QDBusReply<void> reply = conf.call(methodName, it.value());
363  if (!reply.isValid()) {
364  q->setError(Job::Unknown);
365  q->setErrorText(i18n("Failed to configure default resource via D-Bus."));
366  q->emitResult();
367  return;
368  }
369  }
370 
371  conf.call(QStringLiteral("save"));
372 
373  agent.reconfigure();
374  }
375 
376  // Sync the resource.
377  {
379  QObject::connect(syncJob, &ResourceSynchronizationJob::result, q, [this](KJob *job) { resourceSyncResult(job); });
380  syncJob->start(); // non-Akonadi
381  }
382 }
383 
384 void DefaultResourceJobPrivate::resourceSyncResult(KJob *job)
385 {
386  if (job->error()) {
387  qCWarning(AKONADICORE_LOG) << job->errorText();
388  //fail( i18n( "ResourceSynchronizationJob failed (%1).", job->errorString() ) );
389  return;
390  }
391 
392  // Fetch the collections of the resource.
393  qCDebug(AKONADICORE_LOG) << "Fetching maildir collections.";
395  fetchJob->fetchScope().setResource(defaultResourceId(mSettings));
396  QObject::connect(fetchJob, &CollectionFetchJob::result, q, [this](KJob *job) { collectionFetchResult(job); });
397 }
398 
399 void DefaultResourceJobPrivate::collectionFetchResult(KJob *job)
400 {
401  if (job->error()) {
402  qCWarning(AKONADICORE_LOG) << job->errorText();
403  //fail( i18n( "Failed to fetch the root maildir collection (%1).", job->errorString() ) );
404  return;
405  }
406 
408  Q_ASSERT(fetchJob);
409 
410  const Collection::List collections = fetchJob->collections();
411  qCDebug(AKONADICORE_LOG) << "Fetched" << collections.count() << "collections.";
412 
413  // Find the root maildir collection.
414  Collection::List toRecover;
415  Collection resourceCollection;
416  for (const Collection &collection : collections) {
417  if (collection.parentCollection() == Collection::root()) {
418  resourceCollection = collection;
419  toRecover.append(collection);
420  break;
421  }
422  }
423 
424  if (!resourceCollection.isValid()) {
425  q->setError(Job::Unknown);
426  q->setErrorText(i18n("Failed to fetch the resource collection."));
427  q->emitResult();
428  return;
429  }
430 
431  // Find all children of the resource collection.
432  for (const Collection &collection : qAsConst(collections)) {
433  if (collection.parentCollection() == resourceCollection) {
434  toRecover.append(collection);
435  }
436  }
437 
438  QHash<QString, QByteArray> typeForName;
439  for (const QByteArray &type : qAsConst(mKnownTypes)) {
440  const QString displayName = mNameForTypeMap.value(type);
441  typeForName[displayName] = type;
442  }
443 
444  // These collections have been created by the maildir resource, when it
445  // found the folders on disk. So give them the necessary attributes now.
446  Q_ASSERT(mPendingModifyJobs == 0);
447  for (Collection collection : qAsConst(toRecover)) { // krazy:exclude=foreach
448 
449  if (collection.hasAttribute<SpecialCollectionAttribute>()) {
450  continue;
451  }
452 
453  // Find the type for the collection.
454  const QString name = collection.displayName();
455  const QByteArray type = typeForName.value(name);
456 
457  if (!type.isEmpty()) {
458  qCDebug(AKONADICORE_LOG) << "Recovering collection" << name;
459  setCollectionAttributes(collection, type, mNameForTypeMap, mIconForTypeMap);
460 
461  CollectionModifyJob *modifyJob = new CollectionModifyJob(collection, q);
462  QObject::connect(modifyJob, &CollectionModifyJob::result, q, [this](KJob *job) {collectionModifyResult(job); });
463  mPendingModifyJobs++;
464  } else {
465  qCDebug(AKONADICORE_LOG) << "Searching for names: " << typeForName.keys();
466  qCDebug(AKONADICORE_LOG) << "Unknown collection name" << name << "-- not recovering.";
467  }
468  }
469 
470  if (mPendingModifyJobs == 0) {
471  // Scan the resource.
472  q->setResourceId(defaultResourceId(mSettings));
473  q->ResourceScanJob::doStart();
474  }
475 }
476 
477 void DefaultResourceJobPrivate::collectionModifyResult(KJob *job)
478 {
479  if (job->error()) {
480  qCWarning(AKONADICORE_LOG) << job->errorText();
481  //fail( i18n( "Failed to modify the root maildir collection (%1).", job->errorString() ) );
482  return;
483  }
484 
485  Q_ASSERT(mPendingModifyJobs > 0);
486  mPendingModifyJobs--;
487  qCDebug(AKONADICORE_LOG) << "pendingModifyJobs now" << mPendingModifyJobs;
488  if (mPendingModifyJobs == 0) {
489  // Write the updated config.
490  qCDebug(AKONADICORE_LOG) << "Writing defaultResourceId" << defaultResourceId(mSettings) << "to config.";
491  mSettings->save();
492 
493  // Scan the resource.
494  q->setResourceId(defaultResourceId(mSettings));
495  q->ResourceScanJob::doStart();
496  }
497 }
498 
499 DefaultResourceJob::DefaultResourceJob(KCoreConfigSkeleton *settings, QObject *parent)
500  : ResourceScanJob(QString(), settings, parent)
501  , d(new DefaultResourceJobPrivate(settings, this))
502 {
503 }
504 
505 DefaultResourceJob::~DefaultResourceJob()
506 {
507  delete d;
508 }
509 
510 void DefaultResourceJob::setDefaultResourceType(const QString &type)
511 {
512  d->mDefaultResourceType = type;
513 }
514 
515 void DefaultResourceJob::setDefaultResourceOptions(const QVariantMap &options)
516 {
517  d->mDefaultResourceOptions = options;
518 }
519 
520 void DefaultResourceJob::setTypes(const QList<QByteArray> &types)
521 {
522  d->mKnownTypes = types;
523 }
524 
525 void DefaultResourceJob::setNameForTypeMap(const QMap<QByteArray, QString> &map)
526 {
527  d->mNameForTypeMap = map;
528 }
529 
530 void DefaultResourceJob::setIconForTypeMap(const QMap<QByteArray, QString> &map)
531 {
532  d->mIconForTypeMap = map;
533 }
534 
535 void DefaultResourceJob::doStart()
536 {
537  d->tryFetchResource();
538 }
539 
540 void DefaultResourceJob::slotResult(KJob *job)
541 {
542  if (job->error()) {
543  qCWarning(AKONADICORE_LOG) << job->errorText();
544  // Do some cleanup.
545  if (!d->mResourceWasPreexisting) {
546  // We only removed the resource instance if we have created it.
547  // Otherwise we might lose the user's data.
548  const AgentInstance resource = AgentManager::self()->instance(defaultResourceId(d->mSettings));
549  qCDebug(AKONADICORE_LOG) << "Removing resource" << resource.identifier();
550  AgentManager::self()->removeInstance(resource);
551  }
552  }
553 
554  Job::slotResult(job);
555 }
556 
557 // ===================== GetLockJob ============================
558 
559 class Q_DECL_HIDDEN Akonadi::GetLockJob::Private
560 {
561 public:
562  Private(GetLockJob *qq);
563 
564  void doStart(); // slot
565  void timeout(); // slot
566 
567  GetLockJob *const q;
568  QTimer *mSafetyTimer = nullptr;
569 };
570 
571 GetLockJob::Private::Private(GetLockJob *qq)
572  : q(qq)
573  , mSafetyTimer(nullptr)
574 {
575 }
576 
577 void GetLockJob::Private::doStart()
578 {
579  // Just doing registerService() and checking its return value is not sufficient,
580  // since we may *already* own the name, and then registerService() returns true.
581 
583  const bool alreadyLocked = bus.interface()->isServiceRegistered(dbusServiceName());
584  const bool gotIt = bus.registerService(dbusServiceName());
585 
586  if (gotIt && !alreadyLocked) {
587  //qCDebug(AKONADICORE_LOG) << "Got lock immediately.";
588  q->emitResult();
589  } else {
590  auto watcher = new QDBusServiceWatcher(dbusServiceName(), QDBusConnection::sessionBus(),
591  QDBusServiceWatcher::WatchForUnregistration, q);
593  q, [this]() {
594  if (QDBusConnection::sessionBus().registerService(dbusServiceName())) {
595  mSafetyTimer->stop();
596  q->emitResult();
597  }
598  });
599 
600  mSafetyTimer = new QTimer(q);
601  mSafetyTimer->setSingleShot(true);
602  mSafetyTimer->setInterval(LOCK_WAIT_TIMEOUT_SECONDS * 1000);
603  mSafetyTimer->start();
604  connect(mSafetyTimer, &QTimer::timeout, q, [this]() { timeout(); });
605  }
606 }
607 
608 void GetLockJob::Private::timeout()
609 {
610  qCWarning(AKONADICORE_LOG) << "Timeout trying to get lock. Check who has acquired the name" << dbusServiceName() << "on DBus, using qdbus or qdbusviewer.";
611  q->setError(Job::Unknown);
612  q->setErrorText(i18n("Timeout trying to get lock."));
613  q->emitResult();
614 }
615 
616 GetLockJob::GetLockJob(QObject *parent)
617  : KJob(parent)
618  , d(new Private(this))
619 {
620 }
621 
622 GetLockJob::~GetLockJob()
623 {
624  delete d;
625 }
626 
627 void GetLockJob::start()
628 {
629  QTimer::singleShot(0, this, [this]() { d->doStart(); });
630 }
631 
632 void Akonadi::setCollectionAttributes(Akonadi::Collection &collection, const QByteArray &type,
633  const QMap<QByteArray, QString> &nameForType,
634  const QMap<QByteArray, QString> &iconForType)
635 {
636  {
638  attr->setIconName(iconForType.value(type));
639  attr->setDisplayName(nameForType.value(type));
640  collection.addAttribute(attr);
641  }
642 
643  {
645  attr->setCollectionType(type);
646  collection.addAttribute(attr);
647  }
648 }
649 
650 bool Akonadi::releaseLock()
651 {
652  return QDBusConnection::sessionBus().unregisterService(dbusServiceName());
653 }
654 
655 #include "moc_specialcollectionshelperjobs_p.cpp"
Job that modifies a collection in the Akonadi storage.
virtual void setProperty(const QVariant &p)=0
Type type(const QString &mimeType)
AgentInstance::List instances() const
Returns the list of all available agent instances.
QMap::const_iterator cend() const const
Collection::List collections() const
Returns the list of fetched collection.
bool isValid() const
Returns whether the collection is valid.
Definition: collection.cpp:137
QString name(const QVariant &location)
static QString instanceIdentifier()
Returns the identifier of the Akonadi instance we are connected to.
void emitResult()
QVector< AgentInstance > List
Describes a list of agent instances.
void append(const T &value)
Unknown error.
Definition: job.h:115
QByteArray methodSignature() const const
QDBusConnectionInterface * interface() const const
CollectionFetchScope & fetchScope()
Returns the collection fetch scope.
void setResource(const QString &resource)
Sets a resource filter, that is only collections owned by the specified resource are retrieved...
Represents a collection of PIM items.
Definition: collection.h:76
AgentType type() const
Returns the agent type of this instance.
Job that fetches collections from the Akonadi storage.
void setListFilter(ListFilter)
Sets a filter for the collections to be listed.
void setError(int errorCode)
bool isEmpty() const const
void setIncludeStatistics(bool include)
Sets whether collection statistics should be included in the retrieved results.
An Attribute that stores the special collection type of a collection.
bool isValid() const const
QString identifier() const
Returns the unique identifier of the agent instance.
QDBusConnection sessionBus()
Base class for all actions in the Akonadi storage.
Definition: job.h:93
QList< QByteArray > parameterTypes() const const
QString identifier() const
Returns the unique identifier of the agent type.
void removeInstance(const AgentInstance &instance)
Removes the given agent instance.
QDBusReply< bool > isServiceRegistered(const QString &serviceName) const const
Only retrieve collections for display, taking the local preference and enabled into account...
Job that synchronizes a resource.
KConfigSkeletonItem * findItem(const QString &name) const
void timeout()
void setErrorText(const QString &errorText)
int count(const T &value) const const
A representation of an agent type.
AgentInstance instance(const QString &identifier) const
Returns the agent instance with the given identifier or an invalid agent instance if the identifier d...
void addAttribute(Attribute *attribute)
Adds an attribute to the collection.
Definition: collection.cpp:167
void setIconName(const QString &name)
Sets the icon name for the default icon.
QVariant::Type nameToType(const char *name)
bool isValid() const
Returns whether the agent instance object is valid.
int methodCount() const const
void serviceUnregistered(const QString &serviceName)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
static Collection root()
Returns the root collection.
Definition: collection.cpp:303
T & first()
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...
void setDisplayName(const QString &name)
Sets the name that should be used for display.
bool unregisterService(const QString &serviceName)
QList< Key > keys() const const
const T value(const Key &key) const const
AgentType type(const QString &identifier) const
Returns the agent type with the given identifier or an invalid agent type if the identifier does not ...
void setName(const QString &name)
Sets the user visible name of the agent instance.
QMap::const_iterator cbegin() const const
Job for creating new agent instances.
const Key key(const T &value, const Key &defaultKey) const const
QString i18n(const char *text, const TYPE &arg...)
void setCollectionType(const QByteArray &type)
Sets the special collections type of the collection.
QString name() const
Returns the user visible name of the agent instance.
Helper integration between Akonadi and Qt.
virtual Q_SCRIPTABLE void start()=0
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int count(const T &value) const const
static AgentManager * self()
Returns the global instance of the agent manager.
QString fromLatin1(const char *str, int size)
A representation of an agent instance.
void result(KJob *job)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QObject * parent() const const
virtual QVariant property() const =0
QString toString() const const
QMetaMethod method(int index) const const
Attribute that stores the properties that are used to display an entity.
static bool hasInstanceIdentifier()
Returns true if we are connected to a non-default Akonadi server instance.
bool registerService(const QString &serviceName)
QString errorText() const
int error() const
const T value(const Key &key, const T &defaultValue) const const
void reconfigure() const
Tell the agent that its configuration has been changed remotely via D-Bus.
AgentInstance instance() const
Returns the AgentInstance object of the newly created agent instance.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jun 5 2020 23:08:56 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.