Build with clang.
[kdepim.git] / kalarm / calendarmigrator.cpp
blob463ef66bf86186ae7c00c4567a1a78f82f315db0
1 /*
2 * calendarmigrator.cpp - migrates or creates KAlarm Akonadi resources
3 * Program: kalarm
4 * Copyright © 2011 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "calendarmigrator.h"
22 #include "akonadimodel.h"
23 #include "kalarmsettings.h"
24 #include "kalarmdirsettings.h"
25 #include "collectionattribute.h"
26 #include "compatibilityattribute.h"
27 #include "mainwindow.h"
28 #include "messagebox.h"
29 #include "version.h"
31 #include <akonadi/agentinstancecreatejob.h>
32 #include <akonadi/agentmanager.h>
33 #include <akonadi/collectionfetchjob.h>
34 #include <akonadi/collectionfetchscope.h>
35 #include <akonadi/collectionmodifyjob.h>
36 #include <akonadi/entitydisplayattribute.h>
37 #include <akonadi/resourcesynchronizationjob.h>
39 #include <klocale.h>
40 #include <kconfiggroup.h>
41 #include <kstandarddirs.h>
42 #include <kdebug.h>
44 #include <QTimer>
46 using namespace Akonadi;
47 using KAlarm::CollectionAttribute;
48 using KAlarm::CompatibilityAttribute;
51 // Creates, or migrates from KResources, a single alarm calendar
52 class CalendarCreator : public QObject
54 Q_OBJECT
55 public:
56 CalendarCreator(const QString& resourceType, const KConfigGroup&);
57 CalendarCreator(KAlarm::CalEvent::Type, const QString& file, const QString& name);
58 bool isValid() const { return mAlarmType != KAlarm::CalEvent::EMPTY; }
59 bool newCalendar() const { return mNew; }
60 QString resourceName() const { return mName; }
61 QString path() const { return mPath; }
62 QString errorMessage() const { return mErrorMessage; }
63 void createAgent(const QString& agentType, QObject* parent);
65 public slots:
66 void agentCreated(KJob*);
68 signals:
69 void creating(const QString& path);
70 void finished(CalendarCreator*);
72 private slots:
73 void fetchCollection();
74 void collectionFetchResult(KJob*);
75 void resourceSynchronised(KJob*);
76 void modifyCollectionJobDone(KJob*);
78 private:
79 void finish(bool cleanup);
80 bool migrateLocalFile();
81 bool migrateLocalDirectory();
82 bool migrateRemoteFile();
83 template <class Interface> Interface* migrateBasic();
85 enum ResourceType { LocalFile, LocalDir, RemoteFile };
87 Akonadi::AgentInstance mAgent;
88 KAlarm::CalEvent::Type mAlarmType;
89 ResourceType mResourceType;
90 QString mPath;
91 QString mName;
92 QColor mColour;
93 QString mErrorMessage;
94 int mCollectionFetchRetryCount;
95 bool mReadOnly;
96 bool mEnabled;
97 bool mStandard;
98 const bool mNew;
99 bool mFinished;
102 // Updates the backend calendar format of a single alarm calendar
103 class CalendarUpdater : public QObject
105 Q_OBJECT
106 public:
107 CalendarUpdater(const Collection& collection, bool dirResource,
108 bool ignoreKeepFormat, bool newCollection, QObject* parent);
110 public slots:
111 bool update();
113 private:
114 Akonadi::Collection mCollection;
115 QObject* mParent;
116 bool mDirResource;
117 bool mIgnoreKeepFormat;
118 bool mNewCollection;
122 CalendarMigrator* CalendarMigrator::mInstance = 0;
124 CalendarMigrator::CalendarMigrator(QObject* parent)
125 : QObject(parent)
129 CalendarMigrator::~CalendarMigrator()
131 kDebug();
134 /******************************************************************************
135 * Create and return the unique CalendarMigrator instance.
137 CalendarMigrator* CalendarMigrator::instance()
139 if (!mInstance)
140 mInstance = new CalendarMigrator;
141 return mInstance;
144 /******************************************************************************
145 * Migrate old KResource calendars, or if none, create default Akonadi resources.
147 void CalendarMigrator::execute()
149 instance()->migrateOrCreate();
152 /******************************************************************************
153 * Migrate old KResource calendars, or if none, create default Akonadi resources.
155 void CalendarMigrator::migrateOrCreate()
157 kDebug();
158 CalendarCreator* creator;
160 // First migrate any KResources alarm calendars from pre-Akonadi versions of KAlarm.
161 bool haveResources = false;
162 const QString configFile = KStandardDirs::locateLocal("config", QLatin1String("kresources/alarms/stdrc"));
163 KConfig config(configFile, KConfig::SimpleConfig);
165 // Fetch all the resource identifiers which are actually in use
166 KConfigGroup group = config.group("General");
167 QStringList keys = group.readEntry("ResourceKeys", QStringList())
168 + group.readEntry("PassiveResourceKeys", QStringList());
170 // Create an Akonadi resource for each resource id
171 foreach (const QString& id, keys)
173 KConfigGroup configGroup = config.group(QLatin1String("Resource_") + id);
174 QString resourceType = configGroup.readEntry("ResourceType", QString());
175 QString agentType;
176 if (resourceType == QLatin1String("file"))
177 agentType = QLatin1String("akonadi_kalarm_resource");
178 else if (resourceType == QLatin1String("dir"))
179 agentType = QLatin1String("akonadi_kalarm_dir_resource");
180 else if (resourceType == QLatin1String("remote"))
181 agentType = QLatin1String("akonadi_kalarm_resource");
182 else
183 continue; // unknown resource type - can't convert
185 haveResources = true;
186 creator = new CalendarCreator(resourceType, configGroup);
187 if (!creator->isValid())
188 delete creator;
189 else
191 connect(creator, SIGNAL(finished(CalendarCreator*)), SLOT(calendarCreated(CalendarCreator*)));
192 connect(creator, SIGNAL(creating(QString)), SLOT(creatingCalendar(QString)));
193 mCalendarsPending << creator;
194 creator->createAgent(agentType, this);
198 if (!haveResources)
200 // There were no KResources calendars to migrate, so create default ones.
201 // Normally this occurs on first installation of KAlarm.
202 // If the default files already exist, they will be used; otherwise they
203 // will be created.
204 creator = new CalendarCreator(KAlarm::CalEvent::ACTIVE, QLatin1String("calendar.ics"), i18nc("@info/plain", "Active Alarms"));
205 connect(creator, SIGNAL(finished(CalendarCreator*)), SLOT(calendarCreated(CalendarCreator*)));
206 connect(creator, SIGNAL(creating(QString)), SLOT(creatingCalendar(QString)));
207 mCalendarsPending << creator;
208 creator->createAgent(QLatin1String("akonadi_kalarm_resource"), this);
210 creator = new CalendarCreator(KAlarm::CalEvent::ARCHIVED, QLatin1String("expired.ics"), i18nc("@info/plain", "Archived Alarms"));
211 connect(creator, SIGNAL(finished(CalendarCreator*)), SLOT(calendarCreated(CalendarCreator*)));
212 connect(creator, SIGNAL(creating(QString)), SLOT(creatingCalendar(QString)));
213 mCalendarsPending << creator;
214 creator->createAgent(QLatin1String("akonadi_kalarm_resource"), this);
216 creator = new CalendarCreator(KAlarm::CalEvent::TEMPLATE, QLatin1String("template.ics"), i18nc("@info/plain", "Alarm Templates"));
217 connect(creator, SIGNAL(finished(CalendarCreator*)), SLOT(calendarCreated(CalendarCreator*)));
218 connect(creator, SIGNAL(creating(QString)), SLOT(creatingCalendar(QString)));
219 mCalendarsPending << creator;
220 creator->createAgent(QLatin1String("akonadi_kalarm_resource"), this);
223 if (mCalendarsPending.isEmpty())
224 deleteLater();
227 /******************************************************************************
228 * Called when a calendar resource is about to be created.
229 * Emits the 'creating' signal.
231 void CalendarMigrator::creatingCalendar(const QString& path)
233 emit creating(path, false);
236 /******************************************************************************
237 * Called when creation of a migrated or new default calendar resource has
238 * completed or failed.
240 void CalendarMigrator::calendarCreated(CalendarCreator* creator)
242 int i = mCalendarsPending.indexOf(creator);
243 if (i < 0)
244 return; // calendar already finished
246 emit creating(creator->path(), true);
248 if (!creator->errorMessage().isEmpty())
250 QString errmsg = creator->newCalendar()
251 ? i18nc("@info/plain", "Failed to create default calendar <resource>%1</resource>", creator->resourceName())
252 : i18nc("@info/plain 'Import Alarms' is the name of a menu option",
253 "Failed to convert old configuration for calendar <resource>%1</resource>. "
254 "Please use Import Alarms to load its alarms into a new or existing calendar.", creator->resourceName());
255 QString locn = i18nc("@info/plain File path or URL", "Location: %1", creator->path());
256 if (creator->errorMessage().isEmpty())
257 errmsg = i18nc("@info", "<para>%1</para><para>%2</para>", errmsg, locn);
258 else
259 errmsg = i18nc("@info", "<para>%1</para><para>%2<nl/>(%3)</para>", errmsg, locn, creator->errorMessage());
260 KAMessageBox::error(MainWindow::mainMainWindow(), errmsg);
262 creator->deleteLater();
264 mCalendarsPending.removeAt(i); // remove it from the pending list
265 if (mCalendarsPending.isEmpty())
266 deleteLater();
269 /******************************************************************************
270 * If an existing Akonadi resource calendar can be converted to the current
271 * KAlarm format, prompt the user whether to convert it, and if yes, tell the
272 * Akonadi resource to update the backend storage to the current format.
273 * The CollectionAttribute's KeepFormat property will be updated if the user
274 * chooses not to update the calendar.
276 * Note: the collection should be up to date: use AkonadiModel::refresh() before
277 * calling this function.
279 void CalendarMigrator::updateToCurrentFormat(const Collection& collection, bool ignoreKeepFormat, QWidget* parent)
281 kDebug() << collection.id();
282 AgentInstance agent = AgentManager::self()->instance(collection.resource());
283 const QString id = agent.type().identifier();
284 bool dirResource;
285 if (id == QLatin1String("akonadi_kalarm_resource"))
286 dirResource = false;
287 else if (id == QLatin1String("akonadi_kalarm_dir_resource"))
288 dirResource = true;
289 else
291 kError() << "Invalid agent type" << id;
292 return;
294 CalendarUpdater* updater = new CalendarUpdater(collection, dirResource, ignoreKeepFormat, false, parent);
295 QTimer::singleShot(0, updater, SLOT(update()));
299 CalendarUpdater::CalendarUpdater(const Collection& collection, bool dirResource,
300 bool ignoreKeepFormat, bool newCollection, QObject* parent)
301 : mCollection(collection),
302 mParent(parent),
303 mDirResource(dirResource),
304 mIgnoreKeepFormat(ignoreKeepFormat),
305 mNewCollection(newCollection)
309 bool CalendarUpdater::update()
311 kDebug() << mCollection.id() << (mDirResource ? "directory" : "file");
312 bool result = true;
313 if (mCollection.hasAttribute<CompatibilityAttribute>())
315 const CompatibilityAttribute* compatAttr = mCollection.attribute<CompatibilityAttribute>();
316 KAlarm::Calendar::Compat compatibility = compatAttr->compatibility();
317 if ((compatibility & ~KAlarm::Calendar::Converted)
318 // The calendar isn't in the current KAlarm format
319 && !(compatibility & ~(KAlarm::Calendar::Convertible | KAlarm::Calendar::Converted))
320 // The calendar format is convertible to the current KAlarm format
321 && (mIgnoreKeepFormat
322 || !mCollection.hasAttribute<CollectionAttribute>()
323 || !mCollection.attribute<CollectionAttribute>()->keepFormat()))
325 // The user hasn't previously said not to convert it
326 QString versionString = KAlarm::getVersionString(compatAttr->version());
327 QString msg = KAlarm::Calendar::conversionPrompt(mCollection.name(), versionString, false);
328 kDebug() << "Version" << versionString;
329 if (KAMessageBox::warningYesNo(qobject_cast<QWidget*>(mParent), msg) == KMessageBox::Yes)
331 // Tell the resource to update the backend storage format
332 QString errmsg;
333 if (!mNewCollection)
335 // Refetch the collection's details because anything could
336 // have happened since the prompt was first displayed.
337 if (!AkonadiModel::instance()->refresh(mCollection))
338 errmsg = i18nc("@info/plain", "Invalid collection");
340 if (errmsg.isEmpty())
342 AgentInstance agent = AgentManager::self()->instance(mCollection.resource());
343 if (mDirResource)
344 CalendarMigrator::updateStorageFormat<OrgKdeAkonadiKAlarmDirSettingsInterface>(agent, errmsg, mParent);
345 else
346 CalendarMigrator::updateStorageFormat<OrgKdeAkonadiKAlarmSettingsInterface>(agent, errmsg, mParent);
348 if (!errmsg.isEmpty())
350 KAMessageBox::error(MainWindow::mainMainWindow(),
351 i18nc("@info", "%1<nl/>(%2)",
352 i18nc("@info/plain", "Failed to update format of calendar <resource>%1</resource>", mCollection.name()),
353 errmsg));
356 else
358 // The user chose not to update the calendar
359 result = false;
360 if (!mNewCollection)
362 QModelIndex ix = AkonadiModel::instance()->collectionIndex(mCollection);
363 AkonadiModel::instance()->setData(ix, true, AkonadiModel::KeepFormatRole);
368 deleteLater();
369 return result;
372 /******************************************************************************
373 * Tell an Akonadi resource to update the backend storage format to the current
374 * KAlarm format.
375 * Reply = true if success; if false, 'errorMessage' contains the error message.
377 template <class Interface> bool CalendarMigrator::updateStorageFormat(const AgentInstance& agent, QString& errorMessage, QObject* parent)
379 kDebug();
380 Interface* iface = getAgentInterface<Interface>(agent, errorMessage, parent);
381 if (!iface)
383 kDebug() << errorMessage;
384 return false;
386 iface->setUpdateStorageFormat(true);
387 iface->writeConfig();
388 delete iface;
389 kDebug() << "true";
390 return true;
393 /******************************************************************************
394 * Create a D-Bus interface to an Akonadi resource.
395 * Reply = interface if success
396 * = 0 if error: 'errorMessage' contains the error message.
398 template <class Interface> Interface* CalendarMigrator::getAgentInterface(const AgentInstance& agent, QString& errorMessage, QObject* parent)
400 Interface* iface = new Interface("org.freedesktop.Akonadi.Resource." + agent.identifier(),
401 "/Settings", QDBusConnection::sessionBus(), parent);
402 if (!iface->isValid())
404 errorMessage = iface->lastError().message();
405 kDebug() << "D-Bus error accessing resource:" << errorMessage;
406 delete iface;
407 return 0;
409 return iface;
413 /******************************************************************************
414 * Constructor to migrate a KResources calendar, using its parameters.
416 CalendarCreator::CalendarCreator(const QString& resourceType, const KConfigGroup& config)
417 : mAlarmType(KAlarm::CalEvent::EMPTY),
418 mNew(false),
419 mFinished(false)
421 // Read the resource configuration parameters from the config
422 const char* pathKey = 0;
423 if (resourceType == QLatin1String("file"))
425 mResourceType = LocalFile;
426 pathKey = "CalendarURL";
428 else if (resourceType == QLatin1String("dir"))
430 mResourceType = LocalDir;
431 pathKey = "CalendarURL";
433 else if (resourceType == QLatin1String("remote"))
435 mResourceType = RemoteFile;
436 pathKey = "DownloadUrl";
438 else
440 kError() << "Invalid resource type:" << resourceType;
441 return;
443 mPath = config.readPathEntry(pathKey, "");
444 switch (config.readEntry("AlarmType", (int)0))
446 case 1: mAlarmType = KAlarm::CalEvent::ACTIVE; break;
447 case 2: mAlarmType = KAlarm::CalEvent::ARCHIVED; break;
448 case 4: mAlarmType = KAlarm::CalEvent::TEMPLATE; break;
449 default:
450 kError() << "Invalid alarm type for resource";
451 return;
453 mName = config.readEntry("ResourceName", QString());
454 mColour = config.readEntry("Color", QColor());
455 mReadOnly = config.readEntry("ResourceIsReadOnly", true);
456 mEnabled = config.readEntry("ResourceIsActive", false);
457 mStandard = config.readEntry("Standard", false);
458 kDebug() << "Migrating:" << mName << ", type=" << mAlarmType << ", path=" << mPath;
461 /******************************************************************************
462 * Constructor to create a new default local file resource.
463 * This is created as enabled, read-write, and standard for its alarm type.
465 CalendarCreator::CalendarCreator(KAlarm::CalEvent::Type alarmType, const QString& file, const QString& name)
466 : mAlarmType(alarmType),
467 mResourceType(LocalFile),
468 mName(name),
469 mColour(),
470 mReadOnly(false),
471 mEnabled(true),
472 mStandard(true),
473 mNew(true),
474 mFinished(false)
476 mPath = KStandardDirs::locateLocal("appdata", file);
477 kDebug() << "New:" << mName << ", type=" << mAlarmType << ", path=" << mPath;
480 /******************************************************************************
481 * Create the Akonadi agent for this calendar.
483 void CalendarCreator::createAgent(const QString& agentType, QObject* parent)
485 emit creating(mPath);
486 AgentInstanceCreateJob* job = new AgentInstanceCreateJob(agentType, parent);
487 connect(job, SIGNAL(result(KJob*)), SLOT(agentCreated(KJob*)));
488 job->start();
491 /******************************************************************************
492 * Called when the agent creation job for this resource has completed.
493 * Applies the calendar resource configuration to the Akonadi agent.
495 void CalendarCreator::agentCreated(KJob* j)
497 if (j->error())
499 mErrorMessage = j->errorString();
500 kError() << "AgentInstanceCreateJob error:" << mErrorMessage;
501 finish(false);
502 return;
505 // Configure the Akonadi Agent
506 kDebug() << mName;
507 AgentInstanceCreateJob* job = static_cast<AgentInstanceCreateJob*>(j);
508 mAgent = job->instance();
509 mAgent.setName(mName);
510 bool ok = false;
511 switch (mResourceType)
513 case LocalFile:
514 ok = migrateLocalFile();
515 break;
516 case LocalDir:
517 ok = migrateLocalDirectory();
518 break;
519 case RemoteFile:
520 ok = migrateRemoteFile();
521 break;
522 default:
523 kError() << "Invalid resource type";
524 break;
526 if (!ok)
528 finish(true);
529 return;
531 mAgent.reconfigure(); // notify the agent that its configuration has been changed
533 // Wait for the resource to create its collection.
534 ResourceSynchronizationJob* sjob = new ResourceSynchronizationJob(mAgent);
535 connect(sjob, SIGNAL(result(KJob*)), SLOT(resourceSynchronised(KJob*)));
536 sjob->start(); // this is required (not an Akonadi::Job)
539 /******************************************************************************
540 * Called when a resource synchronisation job has completed.
541 * Fetches the collection which this agent manages.
543 void CalendarCreator::resourceSynchronised(KJob* j)
545 kDebug() << mName;
546 if (j->error())
548 // Don't give up on error - we can still try to fetch the collection
549 kError() << "ResourceSynchronizationJob error: " << j->errorString();
551 mCollectionFetchRetryCount = 0;
552 fetchCollection();
555 /******************************************************************************
556 * Find the collection which this agent manages.
558 void CalendarCreator::fetchCollection()
560 CollectionFetchJob* job = new CollectionFetchJob(Collection::root(), CollectionFetchJob::FirstLevel);
561 job->fetchScope().setResource(mAgent.identifier());
562 connect(job, SIGNAL(result(KJob*)), SLOT(collectionFetchResult(KJob*)));
563 job->start();
566 bool CalendarCreator::migrateLocalFile()
568 OrgKdeAkonadiKAlarmSettingsInterface* iface = migrateBasic<OrgKdeAkonadiKAlarmSettingsInterface>();
569 if (!iface)
570 return false;
571 iface->setMonitorFile(true);
572 iface->writeConfig(); // save the Agent config changes
573 delete iface;
574 return true;
577 bool CalendarCreator::migrateLocalDirectory()
579 OrgKdeAkonadiKAlarmDirSettingsInterface* iface = migrateBasic<OrgKdeAkonadiKAlarmDirSettingsInterface>();
580 if (!iface)
581 return false;
582 iface->setMonitorFiles(true);
583 iface->writeConfig(); // save the Agent config changes
584 delete iface;
585 return true;
588 bool CalendarCreator::migrateRemoteFile()
590 OrgKdeAkonadiKAlarmSettingsInterface* iface = migrateBasic<OrgKdeAkonadiKAlarmSettingsInterface>();
591 if (!iface)
592 return false;
593 iface->setMonitorFile(true);
594 iface->writeConfig(); // save the Agent config changes
595 delete iface;
596 return true;
599 template <class Interface> Interface* CalendarCreator::migrateBasic()
601 Interface* iface = CalendarMigrator::getAgentInterface<Interface>(mAgent, mErrorMessage, this);
602 if (iface)
604 iface->setReadOnly(mReadOnly);
605 iface->setDisplayName(mName);
606 iface->setPath(mPath);
607 iface->setAlarmTypes(KAlarm::CalEvent::mimeTypes(mAlarmType));
608 iface->setUpdateStorageFormat(false);
610 return iface;
613 /******************************************************************************
614 * Called when a collection fetch job has completed.
615 * Obtains the collection handled by the agent, and configures it.
617 void CalendarCreator::collectionFetchResult(KJob* j)
619 kDebug() << mName;
620 if (j->error())
622 mErrorMessage = j->errorString();
623 kError() << "CollectionFetchJob error: " << mErrorMessage;
624 finish(true);
625 return;
627 CollectionFetchJob* job = static_cast<CollectionFetchJob*>(j);
628 Collection::List collections = job->collections();
629 if (collections.isEmpty())
631 if (++mCollectionFetchRetryCount >= 10)
633 mErrorMessage = i18nc("@info/plain", "New configuration timed out");
634 kError() << "Timeout fetching collection for resource";
635 finish(true);
636 return;
638 // Need to wait a bit longer until the resource has initialised and
639 // created its collection. Retry after 200ms.
640 kDebug() << "Retrying";
641 QTimer::singleShot(200, this, SLOT(fetchCollection()));
642 return;
644 if (collections.count() > 1)
646 mErrorMessage = i18nc("@info/plain", "New configuration was corrupt");
647 kError() << "Wrong number of collections for this resource:" << collections.count();
648 finish(true);
649 return;
652 // Set Akonadi Collection attributes
653 Collection collection = collections[0];
654 collection.setContentMimeTypes(KAlarm::CalEvent::mimeTypes(mAlarmType));
655 EntityDisplayAttribute* dattr = collection.attribute<EntityDisplayAttribute>(Collection::AddIfMissing);
656 dattr->setIconName("kalarm");
657 CollectionAttribute* attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
658 attr->setEnabled(mEnabled ? mAlarmType : KAlarm::CalEvent::EMPTY);
659 if (mStandard)
660 attr->setStandard(mAlarmType);
661 if (mColour.isValid())
662 attr->setBackgroundColor(mColour);
664 // Update the calendar to the current KAlarm format if necessary,
665 // and if the user agrees.
666 bool dirResource = false;
667 switch (mResourceType)
669 case LocalFile:
670 case RemoteFile:
671 break;
672 case LocalDir:
673 dirResource = true;
674 break;
675 default:
676 Q_ASSERT(0); // Invalid resource type
677 break;
679 CalendarUpdater* updater = new CalendarUpdater(collection, dirResource, false, true, this);
680 if (!updater->update()) // note that 'updater' will auto-delete when finished
682 // Record that the user chose not to update the calendar
683 attr->setKeepFormat(true);
686 // Update the collection's attributes in the Akonadi database
687 CollectionModifyJob* cmjob = new CollectionModifyJob(collection, this);
688 connect(cmjob, SIGNAL(result(KJob*)), this, SLOT(modifyCollectionJobDone(KJob*)));
691 /******************************************************************************
692 * Called when a collection modification job has completed.
693 * Checks for any error.
695 void CalendarCreator::modifyCollectionJobDone(KJob* j)
697 Collection collection = static_cast<CollectionModifyJob*>(j)->collection();
698 if (j->error())
700 mErrorMessage = j->errorString();
701 kError() << "CollectionFetchJob error: " << mErrorMessage;
702 finish(true);
704 else
706 kDebug() << "Completed:" << mName;
707 finish(false);
711 /******************************************************************************
712 * Emit the finished() signal. If 'cleanup' is true, delete the newly created
713 * but incomplete Agent.
715 void CalendarCreator::finish(bool cleanup)
717 if (!mFinished)
719 if (cleanup)
720 AgentManager::self()->removeInstance(mAgent);
721 mFinished = true;
722 emit finished(this);
726 #include "calendarmigrator.moc"
727 #include "moc_calendarmigrator.cpp"
729 // vim: et sw=4: