1 /*
2 SPDX-FileCopyrightText: 2012-2021 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "abstractimportexportjob.h"
8 #include "archivestorage.h"
9 #include "backupresourcefilejobbase.h"
10 #include "backupresourcefilejobimpl.h"
11 #include "importexportprogressindicatorbase.h"
12 #include "storeresourcejob.h"
13 #include "synchronizeresourcejob.h"
14
15 #include <Akonadi/AgentInstance>
16 #include <PimCommonAkonadi/CreateResource>
17
18 #include <KLocalizedString>
19 #include <KZip>
20 #include <QTemporaryDir>
21
22 #include <Akonadi/ServerManager>
23
24 #include <KConfigGroup>
25 #include <QCoreApplication>
26 #include <QDir>
27 #include <QFile>
28 #include <QStandardPaths>
29
30 int AbstractImportExportJob::sArchiveVersion = -1;
31
AbstractImportExportJob(QObject * parent,ArchiveStorage * archiveStorage,Utils::StoredTypes typeSelected,int numberOfStep)32 AbstractImportExportJob::AbstractImportExportJob(QObject *parent, ArchiveStorage *archiveStorage, Utils::StoredTypes typeSelected, int numberOfStep)
33 : QObject(parent)
34 , mTypeSelected(typeSelected)
35 , mArchiveStorage(archiveStorage)
36 , mNumberOfStep(numberOfStep)
37 , mImportExportProgressIndicator(new ImportExportProgressIndicatorBase(this))
38 {
39 mImportExportProgressIndicator->setNumberOfStep(numberOfStep);
40 connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::info, this, &AbstractImportExportJob::info);
41 }
42
~AbstractImportExportJob()43 AbstractImportExportJob::~AbstractImportExportJob()
44 {
45 delete mCreateResource;
46 delete mTempDir;
47 }
48
createProgressDialog(const QString & title)49 void AbstractImportExportJob::createProgressDialog(const QString &title)
50 {
51 mImportExportProgressIndicator->createProgressDialog(title);
52 connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::canceled, this, &AbstractImportExportJob::slotTaskCanceled);
53 }
54
slotTaskCanceled()55 void AbstractImportExportJob::slotTaskCanceled()
56 {
57 Q_EMIT error(i18n("Task Canceled"));
58 Q_EMIT jobFinished();
59 }
60
wasCanceled() const61 bool AbstractImportExportJob::wasCanceled() const
62 {
63 return mImportExportProgressIndicator->wasCanceled();
64 }
65
increaseProgressDialog()66 void AbstractImportExportJob::increaseProgressDialog()
67 {
68 mImportExportProgressIndicator->increaseProgressDialog();
69 }
70
setProgressDialogLabel(const QString & text)71 void AbstractImportExportJob::setProgressDialogLabel(const QString &text)
72 {
73 mImportExportProgressIndicator->setProgressDialogLabel(text);
74 }
75
importExportProgressIndicator() const76 ImportExportProgressIndicatorBase *AbstractImportExportJob::importExportProgressIndicator() const
77 {
78 return mImportExportProgressIndicator;
79 }
80
setImportExportProgressIndicator(ImportExportProgressIndicatorBase * importExportProgressIndicator)81 void AbstractImportExportJob::setImportExportProgressIndicator(ImportExportProgressIndicatorBase *importExportProgressIndicator)
82 {
83 delete mImportExportProgressIndicator;
84 mImportExportProgressIndicator = importExportProgressIndicator;
85 mImportExportProgressIndicator->setNumberOfStep(mNumberOfStep);
86 }
87
archive() const88 KZip *AbstractImportExportJob::archive() const
89 {
90 return mArchiveStorage->archive();
91 }
92
backupUiRcFile(const QString & configFileName,const QString & application)93 void AbstractImportExportJob::backupUiRcFile(const QString &configFileName, const QString &application)
94 {
95 const QString configrcStr(configFileName);
96 const QString configrc =
97 QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kxmlgui5/") + application + QLatin1Char('/') + configrcStr;
98 if (QFileInfo::exists(configrc)) {
99 backupFile(configrc, Utils::configsPath(), configrcStr);
100 }
101 }
102
backupConfigFile(const QString & configFileName)103 void AbstractImportExportJob::backupConfigFile(const QString &configFileName)
104 {
105 const QString configrcStr(configFileName);
106 const QString configrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configrcStr;
107 if (QFileInfo::exists(configrc)) {
108 backupFile(configrc, Utils::configsPath(), configrcStr);
109 }
110 }
111
backupFile(const QString & filename,const QString & path,const QString & storedName)112 void AbstractImportExportJob::backupFile(const QString &filename, const QString &path, const QString &storedName)
113 {
114 if (QFileInfo::exists(filename)) {
115 const bool fileAdded = archive()->addLocalFile(filename, path + storedName);
116 if (fileAdded) {
117 Q_EMIT info(i18n("\"%1\" backup done.", path + storedName));
118 } else {
119 Q_EMIT error(i18n("\"%1\" cannot be exported.", path + storedName));
120 }
121 } else {
122 Q_EMIT error(i18n("\"%1\" does not exist.", filename));
123 }
124 }
125
mergeConfigMessageBox(const QString & configName) const126 int AbstractImportExportJob::mergeConfigMessageBox(const QString &configName) const
127 {
128 return mImportExportProgressIndicator->mergeConfigMessageBox(configName);
129 }
130
overwriteConfigMessageBox(const QString & configName) const131 bool AbstractImportExportJob::overwriteConfigMessageBox(const QString &configName) const
132 {
133 return mImportExportProgressIndicator->overwriteConfigMessageBox(configName);
134 }
135
overwriteDirectory(const QString & path,const KArchiveEntry * entry)136 void AbstractImportExportJob::overwriteDirectory(const QString &path, const KArchiveEntry *entry)
137 {
138 if (QDir(path).exists()) {
139 if (overwriteDirectoryMessageBox(path)) {
140 const auto dirEntry = static_cast<const KArchiveDirectory *>(entry);
141 if (!dirEntry->copyTo(path)) {
142 qCWarning(PIMDATAEXPORTERCORE_LOG) << "directory cannot overwrite to " << path;
143 }
144 }
145 } else {
146 const auto dirEntry = static_cast<const KArchiveDirectory *>(entry);
147 if (dirEntry->copyTo(path)) {
148 qCWarning(PIMDATAEXPORTERCORE_LOG) << "directory cannot overwrite to " << path;
149 }
150 }
151 }
152
searchAllFiles(const KArchiveDirectory * dir,const QString & prefix,const QString & searchEntryName)153 void AbstractImportExportJob::searchAllFiles(const KArchiveDirectory *dir, const QString &prefix, const QString &searchEntryName)
154 {
155 const QStringList lst = dir->entries();
156 for (const QString &entryName : lst) {
157 const KArchiveEntry *entry = dir->entry(entryName);
158 if (entry && entry->isDirectory()) {
159 const QString newPrefix = (prefix.isEmpty() ? prefix : prefix + QLatin1Char('/')) + entryName;
160 if (entryName == searchEntryName) {
161 storeArchiveInfoResources(static_cast<const KArchiveDirectory *>(entry), entryName);
162 } else {
163 searchAllFiles(static_cast<const KArchiveDirectory *>(entry), newPrefix, searchEntryName);
164 }
165 }
166 }
167 }
168
storeArchiveInfoResources(const KArchiveDirectory * dir,const QString & prefix)169 void AbstractImportExportJob::storeArchiveInfoResources(const KArchiveDirectory *dir, const QString &prefix)
170 {
171 const QStringList lst = dir->entries();
172 for (const QString &entryName : lst) {
173 const KArchiveEntry *entry = dir->entry(entryName);
174 if (entry && entry->isDirectory()) {
175 const auto resourceDir = static_cast<const KArchiveDirectory *>(entry);
176 const QStringList lst = resourceDir->entries();
177
178 if (lst.count() >= 2) {
179 const QString archPath(prefix + QLatin1Char('/') + entryName + QLatin1Char('/'));
180 ResourceFiles files;
181 for (const QString &name : lst) {
182 if (isAConfigFile(name)) {
183 files.akonadiConfigFile = archPath + name;
184 } else if (name.startsWith(Utils::prefixAkonadiConfigFile())) {
185 files.akonadiAgentConfigFile = archPath + name;
186 } else {
187 files.akonadiResources = archPath + name;
188 }
189 }
190 files.debug();
191 mListResourceFile.append(files);
192 } else {
193 qCWarning(PIMDATAEXPORTERCORE_LOG) << " Problem in archive. number of file " << lst.count();
194 }
195 }
196 }
197 std::sort(mListResourceFile.begin(), mListResourceFile.end());
198 }
199
isAConfigFile(const QString & name) const200 bool AbstractImportExportJob::isAConfigFile(const QString &name) const
201 {
202 Q_UNUSED(name)
203 // Redefine in subclass
204 return true;
205 }
206
overwriteDirectoryMessageBox(const QString & directory) const207 bool AbstractImportExportJob::overwriteDirectoryMessageBox(const QString &directory) const
208 {
209 return mImportExportProgressIndicator->overwriteDirectoryMessageBox(directory);
210 }
211
convertRealPathToCollection(KConfigGroup & group,const QString & currentKey,bool addCollectionPrefix)212 qint64 AbstractImportExportJob::convertRealPathToCollection(KConfigGroup &group, const QString ¤tKey, bool addCollectionPrefix)
213 {
214 qint64 colId = -1;
215 if (group.hasKey(currentKey)) {
216 const QString path = group.readEntry(currentKey);
217 if (!path.isEmpty()) {
218 const Akonadi::Collection::Id id = convertPathToId(path);
219 if (id != -1) {
220 if (addCollectionPrefix) {
221 group.writeEntry(currentKey, QStringLiteral("c%1").arg(id));
222 } else {
223 group.writeEntry(currentKey, id);
224 }
225 } else {
226 group.deleteEntry(currentKey);
227 }
228 colId = id;
229 }
230 }
231 return colId;
232 }
233
convertPathToId(const QString & path)234 Akonadi::Collection::Id AbstractImportExportJob::convertPathToId(const QString &path)
235 {
236 if (path.isEmpty()) {
237 return -1;
238 }
239 Akonadi::Collection::Id val = mHashConvertPathCollectionId.value(path, -1);
240 if (val != -1) {
241 return val;
242 }
243 const Akonadi::Collection::Id id = convertFolderPathToCollectionId(path);
244 if (id != -1) {
245 mHashConvertPathCollectionId.insert(path, id);
246 }
247 return id;
248 }
249
initializeImportJob()250 void AbstractImportExportJob::initializeImportJob()
251 {
252 if (mTempDir) {
253 qCDebug(PIMDATAEXPORTERCORE_LOG) << " initializeImportJob already called";
254 } else {
255 mTempDir = new QTemporaryDir();
256 mTempDirName = mTempDir->path();
257 mCreateResource = new PimCommon::CreateResource();
258 connect(mCreateResource, &PimCommon::CreateResource::createResourceInfo, this, &AbstractImportExportJob::info);
259 connect(mCreateResource, &PimCommon::CreateResource::createResourceError, this, &AbstractImportExportJob::error);
260 }
261 }
262
copyToDirectory(const KArchiveEntry * entry,const QString & dest)263 void AbstractImportExportJob::copyToDirectory(const KArchiveEntry *entry, const QString &dest)
264 {
265 const auto subfolderDir = static_cast<const KArchiveDirectory *>(entry);
266 if (!subfolderDir->copyTo(dest)) {
267 qCDebug(PIMDATAEXPORTERCORE_LOG) << "directory cannot copy to " << dest;
268 }
269 Q_EMIT info(i18n("\"%1\" was copied.", dest));
270 }
271
copyToFile(const KArchiveFile * archivefile,const QString & dest,const QString & filename,const QString & prefix)272 void AbstractImportExportJob::copyToFile(const KArchiveFile *archivefile, const QString &dest, const QString &filename, const QString &prefix)
273 {
274 QDir dir(mTempDirName);
275 const QString copyToDirName(mTempDirName + QLatin1Char('/') + prefix);
276 const bool created = dir.mkpath(copyToDirName);
277 if (!created) {
278 qCWarning(PIMDATAEXPORTERCORE_LOG) << " directory :" << prefix << " not created";
279 }
280
281 if (!archivefile->copyTo(copyToDirName)) {
282 qCWarning(PIMDATAEXPORTERCORE_LOG) << "copyToFile file " << filename << " can not copy to " << dest;
283 }
284 QFile file;
285 file.setFileName(copyToDirName + QLatin1Char('/') + filename);
286
287 // QFile doesn't overwrite => remove old file before
288 // qCDebug(PIMDATAEXPORTERCORE_LOG)<<" dest "<<dest;
289 // qCDebug(PIMDATAEXPORTERCORE_LOG)<<" file "<<file.fileName();
290 QFile destination(dest);
291 if (destination.exists()) {
292 destination.remove();
293 }
294 QFileInfo destFileInfo(dest);
295
296 QDir().mkpath(destFileInfo.path());
297 if (!file.copy(dest)) {
298 mImportExportProgressIndicator->showErrorMessage(i18n("File \"%1\" cannot be copied to \"%2\".", filename, dest), i18n("Copy file"));
299 } else {
300 Q_EMIT info(i18n("\"%1\" was restored.", filename));
301 }
302 }
303
backupResourceFile(const QString & identifier,const QString & defaultPath)304 void AbstractImportExportJob::backupResourceFile(const QString &identifier, const QString &defaultPath)
305 {
306 auto job = new BackupResourceFileJobImpl(this);
307 job->setDefaultPath(defaultPath);
308 job->setIdentifier(identifier);
309 job->setZip(archive());
310 connect(job, &BackupResourceFileJobImpl::error, this, &AbstractImportExportJob::error);
311 connect(job, &BackupResourceFileJobImpl::info, this, &AbstractImportExportJob::info);
312 job->start();
313 }
314
315 QStringList
restoreResourceFile(const QString & resourceBaseName,const QString & defaultPath,const QString & storePath,bool overwriteResources)316 AbstractImportExportJob::restoreResourceFile(const QString &resourceBaseName, const QString &defaultPath, const QString &storePath, bool overwriteResources)
317 {
318 QStringList resourceToSync;
319 // TODO fix sync config after created a resource
320 if (!mListResourceFile.isEmpty()) {
321 QDir dir(mTempDirName);
322 dir.mkdir(defaultPath);
323 const QString copyToDirName(mTempDirName + QLatin1Char('/') + defaultPath);
324 if (!QDir().mkpath(copyToDirName)) {
325 qCWarning(PIMDATAEXPORTERCORE_LOG) << " impossible to create :" << copyToDirName;
326 }
327
328 for (int i = 0, total = mListResourceFile.size(); i < total; ++i) {
329 ResourceFiles value = mListResourceFile.at(i);
330 QMap<QString, QVariant> settings;
331 if (value.akonadiConfigFile.contains(resourceBaseName + QLatin1Char('_'))) {
332 const KArchiveEntry *fileResouceEntry = mArchiveDirectory->entry(value.akonadiConfigFile);
333 if (fileResouceEntry && fileResouceEntry->isFile()) {
334 const auto file = static_cast<const KArchiveFile *>(fileResouceEntry);
335 if (!file->copyTo(copyToDirName)) {
336 qCWarning(PIMDATAEXPORTERCORE_LOG)
337 << "AbstractImportExportJob file " << value.akonadiConfigFile << " can not copy to " << copyToDirName;
338 }
339 QString resourceName(file->name());
340
341 QString filename(file->name());
342 // TODO adapt filename otherwise it will use all the time the same filename.
343 qCDebug(PIMDATAEXPORTERCORE_LOG) << " filename :" << filename;
344
345 KSharedConfig::Ptr resourceConfig = KSharedConfig::openConfig(copyToDirName + QLatin1Char('/') + resourceName);
346
347 QString newUrl = adaptNewResourceUrl(overwriteResources, resourceConfig, storePath);
348 const QString dataFile = value.akonadiResources;
349 const KArchiveEntry *dataResouceEntry = mArchiveDirectory->entry(dataFile);
350 if (dataResouceEntry && dataResouceEntry->isFile()) {
351 const auto file = static_cast<const KArchiveFile *>(dataResouceEntry);
352 if (!file->copyTo(newUrl)) {
353 qCWarning(PIMDATAEXPORTERCORE_LOG) << "AbstractImportExportJob: file " << dataFile << " can not copy to " << newUrl;
354 }
355 }
356 if (!newUrl.isEmpty()) {
357 settings.insert(QStringLiteral("Path"), newUrl);
358 }
359
360 const QString agentConfigFile = value.akonadiAgentConfigFile;
361 if (!agentConfigFile.isEmpty()) {
362 const KArchiveEntry *akonadiAgentConfigEntry = mArchiveDirectory->entry(agentConfigFile);
363 if (akonadiAgentConfigEntry->isFile()) {
364 const auto file = static_cast<const KArchiveFile *>(akonadiAgentConfigEntry);
365 file->copyTo(copyToDirName);
366 resourceName = file->name();
367 const QString configPath = copyToDirName + QLatin1Char('/') + resourceName;
368 filename = Utils::akonadiAgentName(configPath);
369 }
370 }
371
372 addSpecificResourceSettings(resourceConfig, resourceBaseName, settings);
373
374 const QString newResource = createResource(resourceBaseName, filename, settings);
375 infoAboutNewResource(newResource);
376 resourceToSync << newResource;
377 qCDebug(PIMDATAEXPORTERCORE_LOG) << " newResource" << newResource;
378 }
379 }
380 }
381 Q_EMIT info(i18n("Resources restored."));
382 } else {
383 Q_EMIT error(i18n("No resources files found."));
384 qDebug() << " resourceBaseName " << resourceBaseName;
385 }
386 return resourceToSync;
387 }
388
addSpecificResourceSettings(const KSharedConfig::Ptr &,const QString &,QMap<QString,QVariant> &)389 void AbstractImportExportJob::addSpecificResourceSettings(const KSharedConfig::Ptr /*resourceConfig*/ &,
390 const QString & /*resourceName*/,
391 QMap<QString, QVariant> & /*settings*/)
392 {
393 // Redefine it in subclass
394 }
395
copyArchiveFileTo(const KArchiveFile * file,const QString & destination)396 bool AbstractImportExportJob::copyArchiveFileTo(const KArchiveFile *file, const QString &destination)
397 {
398 const bool result = file->copyTo(destination);
399 if (!result) {
400 qCWarning(PIMDATAEXPORTERCORE_LOG) << "copyArchiveFileTo file " << file->name() << " can not copy to " << destination;
401 }
402 return result;
403 }
404
extractZipFile(const KArchiveFile * file,const QString & source,const QString & destination,bool isStoredAsZippedArchive)405 void AbstractImportExportJob::extractZipFile(const KArchiveFile *file, const QString &source, const QString &destination, bool isStoredAsZippedArchive)
406 {
407 if (!file->copyTo(source)) {
408 qCWarning(PIMDATAEXPORTERCORE_LOG) << "extractZipFile file " << file->name() << " can not copy to " << source;
409 }
410 QDir dest(destination);
411 if (!dest.exists()) {
412 dest.mkpath(destination);
413 }
414 if (isStoredAsZippedArchive) {
415 QString errorMsg;
416 KZip *zip = Utils::openZip(source + QLatin1Char('/') + file->name(), errorMsg);
417 if (zip) {
418 const KArchiveDirectory *zipDir = zip->directory();
419 const QStringList lst = zipDir->entries();
420 for (const QString &entryName : lst) {
421 const KArchiveEntry *entry = zipDir->entry(entryName);
422 if (entry) {
423 if (entry->isDirectory()) {
424 const auto dir = static_cast<const KArchiveDirectory *>(entry);
425 dir->copyTo(destination + QLatin1Char('/') + dir->name(), true);
426 } else if (entry->isFile()) {
427 const auto dir = static_cast<const KArchiveFile *>(entry);
428 dir->copyTo(destination);
429 }
430 }
431 qApp->processEvents();
432 }
433 delete zip;
434 } else {
435 Q_EMIT error(errorMsg);
436 }
437 } else {
438 QFile archiveFile(source + QLatin1Char('/') + file->name());
439 if (!archiveFile.copy(destination + QLatin1Char('/') + file->name())) {
440 Q_EMIT error(i18n("Unable to copy file %1", file->name()));
441 }
442 }
443 }
444
restoreUiRcFile(const QString & configNameStr,const QString & applicationName)445 void AbstractImportExportJob::restoreUiRcFile(const QString &configNameStr, const QString &applicationName)
446 {
447 const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr);
448 if (configNameentry && configNameentry->isFile()) {
449 const auto configNameconfiguration = static_cast<const KArchiveFile *>(configNameentry);
450 const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kxmlgui5/") + applicationName
451 + QLatin1Char('/') + configNameStr;
452 if (QFileInfo::exists(configNamerc)) {
453 if (overwriteConfigMessageBox(configNameStr)) {
454 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
455 }
456 } else {
457 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
458 }
459 }
460 }
461
restoreConfigFile(const QString & configNameStr)462 void AbstractImportExportJob::restoreConfigFile(const QString &configNameStr)
463 {
464 const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr);
465 if (configNameentry && configNameentry->isFile()) {
466 const auto configNameconfiguration = static_cast<const KArchiveFile *>(configNameentry);
467 const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configNameStr;
468 if (QFileInfo::exists(configNamerc)) {
469 // TODO 4.12 allow to merge config.
470 if (overwriteConfigMessageBox(configNameStr)) {
471 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
472 }
473 } else {
474 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
475 }
476 }
477 }
478
infoAboutNewResource(const QString & resourceName)479 void AbstractImportExportJob::infoAboutNewResource(const QString &resourceName)
480 {
481 Q_EMIT info(i18n("Resource \'%1\' created.", resourceName));
482 }
483
archiveVersion()484 int AbstractImportExportJob::archiveVersion()
485 {
486 return sArchiveVersion;
487 }
488
setArchiveVersion(int version)489 void AbstractImportExportJob::setArchiveVersion(int version)
490 {
491 sArchiveVersion = version;
492 }
493
slotSynchronizeInstanceFailed(const QString & instance)494 void AbstractImportExportJob::slotSynchronizeInstanceFailed(const QString &instance)
495 {
496 Q_EMIT error(i18n("Failed to synchronize %1.", instance));
497 }
498
slotSynchronizeInstanceDone(const QString & name,const QString & identifier)499 void AbstractImportExportJob::slotSynchronizeInstanceDone(const QString &name, const QString &identifier)
500 {
501 Q_EMIT info(i18n("Resource %1 synchronized.", name));
502 Q_EMIT needSynchronizeResource(name, identifier);
503 }
504
slotAllResourceSynchronized()505 void AbstractImportExportJob::slotAllResourceSynchronized()
506 {
507 Q_EMIT info(i18n("All resources synchronized."));
508 slotNextStep();
509 }
510
slotNextStep()511 void AbstractImportExportJob::slotNextStep()
512 {
513 // Implement in sub class.
514 }
515
startSynchronizeResources(const QStringList & listResourceToSync)516 void AbstractImportExportJob::startSynchronizeResources(const QStringList &listResourceToSync)
517 {
518 Q_EMIT info(i18n("Start synchronizing..."));
519 auto job = new SynchronizeResourceJob(this);
520 job->setListResources(listResourceToSync);
521 connect(job, &SynchronizeResourceJob::synchronizationFinished, this, &AbstractImportExportJob::slotAllResourceSynchronized);
522 connect(job, &SynchronizeResourceJob::synchronizationInstanceDone, this, &AbstractImportExportJob::slotSynchronizeInstanceDone);
523 connect(job, &SynchronizeResourceJob::synchronizationInstanceFailed, this, &AbstractImportExportJob::slotSynchronizeInstanceFailed);
524 job->start();
525 }
526
initializeListStep()527 void AbstractImportExportJob::initializeListStep()
528 {
529 if (mTypeSelected & Utils::MailTransport) {
530 mListStep << Utils::MailTransport;
531 }
532 if (mTypeSelected & Utils::Mails) {
533 mListStep << Utils::Mails;
534 }
535 if (mTypeSelected & Utils::Resources) {
536 mListStep << Utils::Resources;
537 }
538 if (mTypeSelected & Utils::Identity) {
539 mListStep << Utils::Identity;
540 }
541 if (mTypeSelected & Utils::Config) {
542 mListStep << Utils::Config;
543 }
544 if (mTypeSelected & Utils::Data) {
545 mListStep << Utils::Data;
546 }
547 }
548
storeDirectory(const QString & subDirectory)549 void AbstractImportExportJob::storeDirectory(const QString &subDirectory)
550 {
551 const QDir directoryToStore(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + subDirectory);
552 if (directoryToStore.exists()) {
553 const bool templateDirAdded = archive()->addLocalDirectory(directoryToStore.path(), Utils::dataPath() + subDirectory);
554 if (templateDirAdded) {
555 Q_EMIT info(i18n("Directory \"%1\" added to backup file.", directoryToStore.path()));
556 } else {
557 Q_EMIT error(i18n("Directory \"%1\" cannot be added to backup file.", directoryToStore.path()));
558 }
559 }
560 }
561
importDataSubdirectory(const QString & subdirectoryRelativePath)562 void AbstractImportExportJob::importDataSubdirectory(const QString &subdirectoryRelativePath)
563 {
564 const KArchiveEntry *themeEntry = mArchiveDirectory->entry(Utils::dataPath() + subdirectoryRelativePath);
565 if (themeEntry && themeEntry->isDirectory()) {
566 const auto themeDir = static_cast<const KArchiveDirectory *>(themeEntry);
567 const QStringList lst = themeDir->entries();
568 for (const QString &entryName : lst) {
569 const KArchiveEntry *entry = themeDir->entry(entryName);
570 if (entry && entry->isDirectory()) {
571 QString subFolderName = entryName;
572 const QString topLevelPath =
573 QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + subdirectoryRelativePath;
574 QDir themeDirectory(topLevelPath + QStringLiteral("/%1").arg(entryName));
575 int i = 1;
576 while (themeDirectory.exists()) {
577 subFolderName = entryName + QStringLiteral("_%1").arg(i);
578 themeDirectory = QDir(topLevelPath + QStringLiteral("/%1").arg(subFolderName));
579 ++i;
580 }
581 copyToDirectory(entry, topLevelPath + QStringLiteral("/%1").arg(subFolderName));
582 }
583 }
584 }
585 }
586
convertCollectionListStrToAkonadiId(const KSharedConfig::Ptr & config,const QString & groupName,const QString & key,bool addCollectionPrefix)587 void AbstractImportExportJob::convertCollectionListStrToAkonadiId(const KSharedConfig::Ptr &config,
588 const QString &groupName,
589 const QString &key,
590 bool addCollectionPrefix)
591 {
592 if (config->hasGroup(groupName)) {
593 KConfigGroup group = config->group(groupName);
594 convertRealPathToCollectionList(group, key, addCollectionPrefix);
595 }
596 }
597
convertRealPathToCollectionList(KConfigGroup & group,const QString & currentKey,bool addCollectionPrefix)598 void AbstractImportExportJob::convertRealPathToCollectionList(KConfigGroup &group, const QString ¤tKey, bool addCollectionPrefix)
599 {
600 if (group.hasKey(currentKey)) {
601 const QStringList listExpension = group.readEntry(currentKey, QStringList());
602 QStringList result;
603 if (!listExpension.isEmpty()) {
604 for (const QString &collection : listExpension) {
605 const Akonadi::Collection::Id id = convertPathToId(collection);
606 if (id != -1) {
607 if (addCollectionPrefix) {
608 result << QStringLiteral("c%1").arg(id);
609 } else {
610 result << QStringLiteral("%1").arg(id);
611 }
612 }
613 }
614 if (result.isEmpty()) {
615 group.deleteEntry(currentKey);
616 } else {
617 group.writeEntry(currentKey, result);
618 }
619 }
620 }
621 }
622
setTempDirName(const QString & tempDirName)623 void AbstractImportExportJob::setTempDirName(const QString &tempDirName)
624 {
625 mTempDirName = tempDirName;
626 }
627