7#include "specialcollectionshelperjobs_p.h"
9#include "servermanager.h"
10#include "specialcollectionattribute.h"
11#include <QDBusConnection>
13#include "agentinstance.h"
14#include "agentinstancecreatejob.h"
15#include "agentmanager.h"
16#include "collectionfetchjob.h"
17#include "collectionfetchscope.h"
18#include "collectionmodifyjob.h"
19#include "entitydisplayattribute.h"
20#include "resourcesynchronizationjob.h"
22#include "akonadicore_debug.h"
24#include <KCoreConfigSkeleton>
25#include <KLocalizedString>
27#include <QDBusConnectionInterface>
28#include <QDBusInterface>
29#include <QDBusServiceWatcher>
34#define LOCK_WAIT_TIMEOUT_SECONDS 30
55 const QString service = QStringLiteral(
"org.kde.pim.SpecialCollections");
56 if (ServerManager::hasInstanceIdentifier()) {
57 return service + ServerManager::instanceIdentifier();
65 for (
int i = 0; i < metaObject->
methodCount(); ++i) {
68 metaMethod = metaObject->
method(i);
77 if (argTypes.
count() != 1) {
89class Akonadi::ResourceScanJobPrivate
94 void fetchResult(
KJob *job);
96 ResourceScanJob *
const q;
107ResourceScanJobPrivate::ResourceScanJobPrivate(
KCoreConfigSkeleton *settings, ResourceScanJob *qq)
109 , mSettings(settings)
113void ResourceScanJobPrivate::fetchResult(
KJob *job)
116 qCWarning(AKONADICORE_LOG) << job->
errorText();
120 auto fetchJob = qobject_cast<CollectionFetchJob *>(job);
123 Q_ASSERT(!mRootCollection.isValid());
124 Q_ASSERT(mSpecialCollections.
isEmpty());
126 for (
const Collection &collection : lstCols) {
128 if (mRootCollection.isValid()) {
129 qCWarning(AKONADICORE_LOG) <<
"Resource has more than one root collection. I don't know what to do.";
131 mRootCollection = collection;
136 mSpecialCollections.
append(collection);
140 qCDebug(AKONADICORE_LOG) <<
"Fetched root collection" << mRootCollection.id() <<
"and" << mSpecialCollections.
count() <<
"local folders"
141 <<
"(total" << fetchJob->collections().count() <<
"collections).";
143 if (!mRootCollection.isValid()) {
144 q->setError(ResourceScanJob::Unknown);
145 q->setErrorText(
i18n(
"Could not fetch root collection of resource %1.", mResourceId));
156 , d(new ResourceScanJobPrivate(settings, this))
158 setResourceId(resourceId);
161ResourceScanJob::~ResourceScanJob() =
default;
163QString ResourceScanJob::resourceId()
const
165 return d->mResourceId;
168void ResourceScanJob::setResourceId(
const QString &resourceId)
170 d->mResourceId = resourceId;
175 return d->mRootCollection;
180 return d->mSpecialCollections;
183void ResourceScanJob::doStart()
185 if (d->mResourceId.isEmpty()) {
186 if (!qobject_cast<DefaultResourceJob *>(
this)) {
187 qCCritical(AKONADICORE_LOG) <<
"No resource ID given.";
189 setErrorText(
i18n(
"No resource ID given."));
196 fetchJob->fetchScope().setResource(d->mResourceId);
197 fetchJob->fetchScope().setIncludeStatistics(
true);
198 fetchJob->fetchScope().setListFilter(CollectionFetchScope::Display);
199 connect(fetchJob, &CollectionFetchJob::result,
this, [
this](
KJob *job) {
209class Akonadi::DefaultResourceJobPrivate
214 void tryFetchResource();
215 void resourceCreateResult(
KJob *job);
216 void resourceSyncResult(
KJob *job);
217 void collectionFetchResult(
KJob *job);
218 void collectionModifyResult(
KJob *job);
220 DefaultResourceJob *
const q;
227 int mPendingModifyJobs = 0;
228 bool mResourceWasPreexisting =
true;
231DefaultResourceJobPrivate::DefaultResourceJobPrivate(
KCoreConfigSkeleton *settings, DefaultResourceJob *qq)
233 , mSettings(settings)
234 , mPendingModifyJobs(0)
235 , mResourceWasPreexisting(true )
239void DefaultResourceJobPrivate::tryFetchResource()
244 const QString resourceId = defaultResourceId(mSettings);
246 qCDebug(AKONADICORE_LOG) <<
"Read defaultResourceId" << resourceId <<
"from config.";
249 if (resource.isValid()) {
251 mResourceWasPreexisting =
true;
252 qCDebug(AKONADICORE_LOG) <<
"Found resource" << resourceId;
253 q->setResourceId(resourceId);
256 fetchJob->fetchScope().setResource(resourceId);
257 fetchJob->fetchScope().setIncludeStatistics(
true);
259 collectionFetchResult(job);
267 if (resourceInstance.type().identifier() == mDefaultResourceType) {
268 if (resourceInstance.name() == mDefaultResourceOptions.
value(QStringLiteral(
"Name")).
toString()) {
270 setDefaultResourceId(mSettings, resourceInstance.identifier());
272 mResourceWasPreexisting =
true;
273 qCDebug(AKONADICORE_LOG) <<
"Found resource" << resourceInstance.identifier();
274 q->setResourceId(resourceInstance.identifier());
275 q->ResourceScanJob::doStart();
282 mResourceWasPreexisting =
false;
283 qCDebug(AKONADICORE_LOG) <<
"Creating maildir resource.";
287 resourceCreateResult(job);
293void DefaultResourceJobPrivate::resourceCreateResult(
KJob *job)
296 qCWarning(AKONADICORE_LOG) << job->
errorText();
298 q->setError(job->
error());
308 auto createJob = qobject_cast<AgentInstanceCreateJob *>(job);
310 agent = createJob->instance();
311 setDefaultResourceId(mSettings, agent.
identifier());
312 qCDebug(AKONADICORE_LOG) <<
"Created maildir resource with id" << defaultResourceId(mSettings);
315 const QString defaultId = defaultResourceId(mSettings);
319 agent.setName(mDefaultResourceOptions.
value(QStringLiteral(
"Name")).
toString());
324 if (!conf.isValid()) {
326 q->setErrorText(
i18n(
"Invalid resource identifier '%1'", defaultId));
333 for (; it != itEnd; ++it) {
338 const QString methodName = QStringLiteral(
"set%1").
arg(it.key());
339 const QMetaType::Type argType = argumentType(conf.metaObject(), methodName);
342 q->setErrorText(
i18n(
"Failed to configure default resource via D-Bus."));
350 q->setErrorText(
i18n(
"Failed to configure default resource via D-Bus."));
356 conf.call(QStringLiteral(
"save"));
365 resourceSyncResult(job);
371void DefaultResourceJobPrivate::resourceSyncResult(
KJob *job)
374 qCWarning(AKONADICORE_LOG) << job->
errorText();
380 qCDebug(AKONADICORE_LOG) <<
"Fetching maildir collections.";
382 fetchJob->fetchScope().setResource(defaultResourceId(mSettings));
384 collectionFetchResult(job);
388void DefaultResourceJobPrivate::collectionFetchResult(
KJob *job)
391 qCWarning(AKONADICORE_LOG) << job->
errorText();
396 auto fetchJob = qobject_cast<CollectionFetchJob *>(job);
400 qCDebug(AKONADICORE_LOG) <<
"Fetched" << collections.
count() <<
"collections.";
405 for (
const Collection &collection : collections) {
407 resourceCollection = collection;
408 toRecover.
append(collection);
413 if (!resourceCollection.isValid()) {
415 q->setErrorText(
i18n(
"Failed to fetch the resource collection."));
421 for (
const Collection &collection : std::as_const(collections)) {
422 if (collection.parentCollection() == resourceCollection) {
423 toRecover.
append(collection);
428 for (
const QByteArray &type : std::as_const(mKnownTypes)) {
435 Q_ASSERT(mPendingModifyJobs == 0);
436 for (
Collection collection : std::as_const(toRecover)) {
445 if (!
type.isEmpty()) {
446 qCDebug(AKONADICORE_LOG) <<
"Recovering collection" <<
name;
447 setCollectionAttributes(collection, type, mNameForTypeMap, mIconForTypeMap);
451 collectionModifyResult(job);
453 mPendingModifyJobs++;
455 qCDebug(AKONADICORE_LOG) <<
"Searching for names: " << typeForName.
keys();
456 qCDebug(AKONADICORE_LOG) <<
"Unknown collection name" <<
name <<
"-- not recovering.";
460 if (mPendingModifyJobs == 0) {
462 q->setResourceId(defaultResourceId(mSettings));
463 q->ResourceScanJob::doStart();
467void DefaultResourceJobPrivate::collectionModifyResult(
KJob *job)
470 qCWarning(AKONADICORE_LOG) << job->
errorText();
475 Q_ASSERT(mPendingModifyJobs > 0);
476 mPendingModifyJobs--;
477 qCDebug(AKONADICORE_LOG) <<
"pendingModifyJobs now" << mPendingModifyJobs;
478 if (mPendingModifyJobs == 0) {
480 qCDebug(AKONADICORE_LOG) <<
"Writing defaultResourceId" << defaultResourceId(mSettings) <<
"to config.";
484 q->setResourceId(defaultResourceId(mSettings));
485 q->ResourceScanJob::doStart();
490 : ResourceScanJob(
QString(), settings, parent)
491 , d(new DefaultResourceJobPrivate(settings, this))
495DefaultResourceJob::~DefaultResourceJob() =
default;
497void DefaultResourceJob::setDefaultResourceType(
const QString &type)
499 d->mDefaultResourceType =
type;
502void DefaultResourceJob::setDefaultResourceOptions(
const QVariantMap &options)
504 d->mDefaultResourceOptions = options;
509 d->mKnownTypes = types;
514 d->mNameForTypeMap =
map;
519 d->mIconForTypeMap =
map;
522void DefaultResourceJob::doStart()
524 d->tryFetchResource();
527void DefaultResourceJob::slotResult(
KJob *job)
530 qCWarning(AKONADICORE_LOG) << job->
errorText();
532 if (!d->mResourceWasPreexisting) {
535 const AgentInstance resource = AgentManager::self()->instance(defaultResourceId(d->mSettings));
536 qCDebug(AKONADICORE_LOG) <<
"Removing resource" << resource.
identifier();
537 AgentManager::self()->removeInstance(resource);
541 Job::slotResult(job);
546class Akonadi::GetLockJobPrivate
549 explicit GetLockJobPrivate(GetLockJob *qq);
555 QTimer *mSafetyTimer =
nullptr;
558GetLockJobPrivate::GetLockJobPrivate(GetLockJob *qq)
560 , mSafetyTimer(nullptr)
564void GetLockJobPrivate::doStart()
573 if (gotIt && !alreadyLocked) {
580 mSafetyTimer->
stop();
585 mSafetyTimer =
new QTimer(q);
586 mSafetyTimer->setSingleShot(
true);
587 mSafetyTimer->setInterval(LOCK_WAIT_TIMEOUT_SECONDS * 1000);
588 mSafetyTimer->start();
595void GetLockJobPrivate::timeout()
597 qCWarning(AKONADICORE_LOG) <<
"Timeout trying to get lock. Check who has acquired the name" << dbusServiceName() <<
"on DBus, using qdbus or qdbusviewer.";
599 q->setErrorText(
i18n(
"Timeout trying to get lock."));
603GetLockJob::GetLockJob(
QObject *parent)
605 , d(new GetLockJobPrivate(this))
609GetLockJob::~GetLockJob() =
default;
611void GetLockJob::start()
626 attr->setDisplayName(nameForType.
value(type));
637bool Akonadi::releaseLock()
642#include "moc_specialcollectionshelperjobs_p.cpp"
Represents one agent instance and takes care of communication with it.
QString identifier() const
Set/get the unique identifier of this AgentInstance.
Job for creating new agent instances.
AgentType type(const QString &identifier) const
Returns the agent type with the given identifier or an invalid agent type if the identifier does not ...
static AgentManager * self()
Returns the global instance of the agent manager.
AgentInstance instance(const QString &identifier) const
Returns the agent instance with the given identifier or an invalid agent instance if the identifier d...
AgentInstance::List instances() const
Returns the list of all available agent instances.
Job that fetches collections from the Akonadi storage.
@ Recursive
List all sub-collections.
Job that modifies a collection in the Akonadi storage.
Represents a collection of PIM items.
void addAttribute(Attribute *attribute)
Adds an attribute to the collection.
static Collection root()
Returns the root collection.
Attribute that stores the properties that are used to display an entity.
void setIconName(const QString &name)
Sets the icon name for the default icon.
Base class for all actions in the Akonadi storage.
Job that synchronizes a resource.
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...
An Attribute that stores the special collection type of a collection.
void setCollectionType(const QByteArray &type)
Sets the special collections type of the collection.
virtual void setProperty(const QVariant &p)=0
virtual QVariant property() const=0
KConfigSkeletonItem * findItem(const QString &name) const
virtual Q_SCRIPTABLE void start()=0
QString errorText() const
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT QString displayName(Akonadi::ETMCalendar *calendar, const Akonadi::Collection &collection)
Helper integration between Akonadi and Qt.
char * toString(const EngineQuery &query)
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
bool isEmpty() const const
QDBusConnectionInterface * interface() const const
bool registerService(const QString &serviceName)
QDBusConnection sessionBus()
bool unregisterService(const QString &serviceName)
QDBusReply< bool > isServiceRegistered(const QString &serviceName) const const
bool isValid() const const
void serviceUnregistered(const QString &serviceName)
QList< Key > keys() const const
T value(const Key &key) const const
void append(QList< T > &&value)
qsizetype count() const const
bool isEmpty() const const
const_iterator cbegin() const const
const_iterator cend() const const
T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const