File indexing completed on 2024-05-12 05:25:33

0001 /*
0002    SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "abstractimportexportjob.h"
0008 #include "archivestorage.h"
0009 #include "backupresourcefilejobbase.h"
0010 #include "backupresourcefilejobimpl.h"
0011 #include "importexportprogressindicatorbase.h"
0012 #include "synchronizeresourcejob.h"
0013 
0014 #include <Akonadi/AgentInstance>
0015 #include <PimCommonAkonadi/CreateResource>
0016 
0017 #include <KLocalizedString>
0018 #include <KZip>
0019 #include <QTemporaryDir>
0020 
0021 #include <Akonadi/ServerManager>
0022 
0023 #include <KConfigGroup>
0024 #include <QCoreApplication>
0025 #include <QDir>
0026 #include <QFile>
0027 #include <QStandardPaths>
0028 
0029 int AbstractImportExportJob::sArchiveVersion = -1;
0030 
0031 AbstractImportExportJob::AbstractImportExportJob(QObject *parent, ArchiveStorage *archiveStorage, Utils::StoredTypes typeSelected, int numberOfStep)
0032     : QObject(parent)
0033     , mTypeSelected(typeSelected)
0034     , mArchiveStorage(archiveStorage)
0035     , mNumberOfStep(numberOfStep)
0036     , mImportExportProgressIndicator(new ImportExportProgressIndicatorBase(this))
0037 {
0038     mImportExportProgressIndicator->setNumberOfStep(numberOfStep);
0039     connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::info, this, &AbstractImportExportJob::emitInfo);
0040 }
0041 
0042 AbstractImportExportJob::~AbstractImportExportJob()
0043 {
0044     delete mCreateResource;
0045     delete mTempDir;
0046 }
0047 
0048 void AbstractImportExportJob::createProgressDialog(const QString &title)
0049 {
0050     mImportExportProgressIndicator->createProgressDialog(title);
0051     connect(mImportExportProgressIndicator, &ImportExportProgressIndicatorBase::canceled, this, &AbstractImportExportJob::slotTaskCanceled);
0052 }
0053 
0054 void AbstractImportExportJob::slotTaskCanceled()
0055 {
0056     Q_EMIT error(i18n("Task Canceled"));
0057     Q_EMIT jobFinished();
0058 }
0059 
0060 bool AbstractImportExportJob::wasCanceled() const
0061 {
0062     return mImportExportProgressIndicator->wasCanceled();
0063 }
0064 
0065 void AbstractImportExportJob::increaseProgressDialog()
0066 {
0067     mImportExportProgressIndicator->increaseProgressDialog();
0068 }
0069 
0070 void AbstractImportExportJob::setProgressDialogLabel(const QString &text)
0071 {
0072     mImportExportProgressIndicator->setProgressDialogLabel(text);
0073 }
0074 
0075 ImportExportProgressIndicatorBase *AbstractImportExportJob::importExportProgressIndicator() const
0076 {
0077     return mImportExportProgressIndicator;
0078 }
0079 
0080 void AbstractImportExportJob::setImportExportProgressIndicator(ImportExportProgressIndicatorBase *importExportProgressIndicator)
0081 {
0082     delete mImportExportProgressIndicator;
0083     mImportExportProgressIndicator = importExportProgressIndicator;
0084     mImportExportProgressIndicator->setNumberOfStep(mNumberOfStep);
0085 }
0086 
0087 KZip *AbstractImportExportJob::archive() const
0088 {
0089     return mArchiveStorage->archive();
0090 }
0091 
0092 void AbstractImportExportJob::backupUiRcFile(const QString &configFileName, const QString &application)
0093 {
0094     const QString configrcStr(configFileName);
0095     const QString configrc =
0096         QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("kxmlgui6") + application + QLatin1Char('/') + configrcStr;
0097     if (QFileInfo::exists(configrc)) {
0098         backupFile(configrc, Utils::configsPath(), configrcStr);
0099     }
0100 }
0101 
0102 void AbstractImportExportJob::backupConfigFile(const QString &configFileName)
0103 {
0104     const QString configrcStr(configFileName);
0105     const QString configrc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configrcStr;
0106     if (QFileInfo::exists(configrc)) {
0107         backupFile(configrc, Utils::configsPath(), configrcStr);
0108     }
0109 }
0110 
0111 void AbstractImportExportJob::backupFile(const QString &filename, const QString &path, const QString &storedName)
0112 {
0113     if (QFileInfo::exists(filename)) {
0114         const bool fileAdded = archive()->addLocalFile(filename, path + storedName);
0115         if (fileAdded) {
0116             emitInfo(i18n("\"%1\" backup done.", path + storedName));
0117         } else {
0118             Q_EMIT error(i18n("\"%1\" cannot be exported.", path + storedName));
0119         }
0120     } else {
0121         Q_EMIT error(i18n("\"%1\" does not exist.", filename));
0122     }
0123 }
0124 
0125 int AbstractImportExportJob::mergeConfigMessageBox(const QString &configName) const
0126 {
0127     return mImportExportProgressIndicator->mergeConfigMessageBox(configName);
0128 }
0129 
0130 bool AbstractImportExportJob::overwriteConfigMessageBox(const QString &configName) const
0131 {
0132     return mImportExportProgressIndicator->overwriteConfigMessageBox(configName);
0133 }
0134 
0135 void AbstractImportExportJob::overwriteDirectory(const QString &path, const KArchiveEntry *entry)
0136 {
0137     if (QDir(path).exists()) {
0138         if (overwriteDirectoryMessageBox(path)) {
0139             const auto dirEntry = static_cast<const KArchiveDirectory *>(entry);
0140             if (!dirEntry->copyTo(path)) {
0141                 qCWarning(PIMDATAEXPORTERCORE_LOG) << "directory cannot overwrite to " << path;
0142             }
0143         }
0144     } else {
0145         const auto dirEntry = static_cast<const KArchiveDirectory *>(entry);
0146         if (dirEntry->copyTo(path)) {
0147             qCWarning(PIMDATAEXPORTERCORE_LOG) << "directory cannot overwrite to " << path;
0148         }
0149     }
0150 }
0151 
0152 void AbstractImportExportJob::searchAllFiles(const KArchiveDirectory *dir, const QString &prefix, const QString &searchEntryName)
0153 {
0154     const QStringList lst = dir->entries();
0155     for (const QString &entryName : lst) {
0156         const KArchiveEntry *entry = dir->entry(entryName);
0157         if (entry && entry->isDirectory()) {
0158             const QString newPrefix = (prefix.isEmpty() ? prefix : prefix + QLatin1Char('/')) + entryName;
0159             if (entryName == searchEntryName) {
0160                 storeArchiveInfoResources(static_cast<const KArchiveDirectory *>(entry), entryName);
0161             } else {
0162                 searchAllFiles(static_cast<const KArchiveDirectory *>(entry), newPrefix, searchEntryName);
0163             }
0164         }
0165     }
0166 }
0167 
0168 void AbstractImportExportJob::storeArchiveInfoResources(const KArchiveDirectory *dir, const QString &prefix)
0169 {
0170     const QStringList lst = dir->entries();
0171     for (const QString &entryName : lst) {
0172         const KArchiveEntry *entry = dir->entry(entryName);
0173         if (entry && entry->isDirectory()) {
0174             const auto resourceDir = static_cast<const KArchiveDirectory *>(entry);
0175             const QStringList lst = resourceDir->entries();
0176 
0177             if (lst.count() >= 2) {
0178                 const QString archPath(prefix + QLatin1Char('/') + entryName + QLatin1Char('/'));
0179                 ResourceFiles files;
0180                 for (const QString &name : lst) {
0181                     if (isAConfigFile(name)) {
0182                         files.akonadiConfigFile = archPath + name;
0183                     } else if (name.startsWith(Utils::prefixAkonadiConfigFile())) {
0184                         files.akonadiAgentConfigFile = archPath + name;
0185                     } else {
0186                         files.akonadiResources = archPath + name;
0187                     }
0188                 }
0189                 files.debug();
0190                 mListResourceFile.append(files);
0191             } else {
0192                 qCWarning(PIMDATAEXPORTERCORE_LOG) << " Problem in archive. number of file " << lst.count();
0193             }
0194         }
0195     }
0196     std::sort(mListResourceFile.begin(), mListResourceFile.end());
0197 }
0198 
0199 bool AbstractImportExportJob::isAConfigFile(const QString &name) const
0200 {
0201     Q_UNUSED(name)
0202     // Redefine in subclass
0203     return true;
0204 }
0205 
0206 bool AbstractImportExportJob::overwriteDirectoryMessageBox(const QString &directory) const
0207 {
0208     return mImportExportProgressIndicator->overwriteDirectoryMessageBox(directory);
0209 }
0210 
0211 qint64 AbstractImportExportJob::convertRealPathToCollection(KConfigGroup &group, const QString &currentKey, bool addCollectionPrefix)
0212 {
0213     qint64 colId = -1;
0214     if (group.hasKey(currentKey)) {
0215         const QString path = group.readEntry(currentKey);
0216         if (!path.isEmpty()) {
0217             const Akonadi::Collection::Id id = convertPathToId(path);
0218             if (id != -1) {
0219                 if (addCollectionPrefix) {
0220                     group.writeEntry(currentKey, QStringLiteral("c%1").arg(id));
0221                 } else {
0222                     group.writeEntry(currentKey, id);
0223                 }
0224             } else {
0225                 group.deleteEntry(currentKey);
0226             }
0227             colId = id;
0228         }
0229     }
0230     return colId;
0231 }
0232 
0233 Akonadi::Collection::Id AbstractImportExportJob::convertPathToId(const QString &path)
0234 {
0235     if (path.isEmpty()) {
0236         return -1;
0237     }
0238     Akonadi::Collection::Id val = mHashConvertPathCollectionId.value(path, -1);
0239     if (val != -1) {
0240         return val;
0241     }
0242     const Akonadi::Collection::Id id = convertFolderPathToCollectionId(path);
0243     if (id != -1) {
0244         mHashConvertPathCollectionId.insert(path, id);
0245     }
0246     return id;
0247 }
0248 
0249 void AbstractImportExportJob::initializeImportJob()
0250 {
0251     if (mTempDir) {
0252         qCDebug(PIMDATAEXPORTERCORE_LOG) << " initializeImportJob already called";
0253     } else {
0254         mTempDir = new QTemporaryDir();
0255         mTempDirName = mTempDir->path();
0256         mCreateResource = new PimCommon::CreateResource();
0257         connect(mCreateResource, &PimCommon::CreateResource::createResourceInfo, this, &AbstractImportExportJob::emitInfo);
0258         connect(mCreateResource, &PimCommon::CreateResource::createResourceError, this, &AbstractImportExportJob::emitError);
0259     }
0260 }
0261 
0262 void AbstractImportExportJob::copyToDirectory(const KArchiveEntry *entry, const QString &dest)
0263 {
0264     const auto subfolderDir = static_cast<const KArchiveDirectory *>(entry);
0265     if (!subfolderDir->copyTo(dest)) {
0266         qCDebug(PIMDATAEXPORTERCORE_LOG) << "directory cannot copy to " << dest;
0267     }
0268     emitInfo(i18n("\"%1\" was copied.", dest));
0269 }
0270 
0271 void AbstractImportExportJob::copyToFile(const KArchiveFile *archivefile, const QString &dest, const QString &filename, const QString &prefix)
0272 {
0273     emitInfo(i18n("Restoring \"%1\"...", filename));
0274     QDir dir(mTempDirName);
0275     const QString copyToDirName(mTempDirName + QLatin1Char('/') + prefix);
0276     const bool created = dir.mkpath(copyToDirName);
0277     if (!created) {
0278         qCWarning(PIMDATAEXPORTERCORE_LOG) << " directory :" << prefix << " not created";
0279     }
0280 
0281     if (!archivefile->copyTo(copyToDirName)) {
0282         qCWarning(PIMDATAEXPORTERCORE_LOG) << "copyToFile file " << filename << " can not copy to " << dest;
0283     }
0284     QFile file;
0285     file.setFileName(copyToDirName + QLatin1Char('/') + filename);
0286 
0287     // QFile doesn't overwrite => remove old file before
0288     // qCDebug(PIMDATAEXPORTERCORE_LOG)<<" dest "<<dest;
0289     // qCDebug(PIMDATAEXPORTERCORE_LOG)<<" file "<<file.fileName();
0290     QFile destination(dest);
0291     if (destination.exists()) {
0292         destination.remove();
0293     }
0294     QFileInfo destFileInfo(dest);
0295 
0296     QDir().mkpath(destFileInfo.path());
0297     if (!file.copy(dest)) {
0298         mImportExportProgressIndicator->showErrorMessage(i18n("File \"%1\" cannot be copied to \"%2\".", filename, dest), i18n("Copy file"));
0299     } else {
0300         emitInfo(i18n("\"%1\" was restored.", filename));
0301     }
0302 }
0303 
0304 void AbstractImportExportJob::backupResourceFile(const QString &identifier, const QString &defaultPath)
0305 {
0306     auto job = new BackupResourceFileJobImpl(this);
0307     job->setDefaultPath(defaultPath);
0308     job->setIdentifier(identifier);
0309     job->setZip(archive());
0310     connect(job, &BackupResourceFileJobImpl::error, this, &AbstractImportExportJob::emitError);
0311     connect(job, &BackupResourceFileJobImpl::info, this, &AbstractImportExportJob::emitInfo);
0312     job->start();
0313 }
0314 
0315 QStringList
0316 AbstractImportExportJob::restoreResourceFile(const QString &resourceBaseName, const QString &defaultPath, const QString &storePath, bool overwriteResources)
0317 {
0318     QStringList resourceToSync;
0319     // TODO fix sync config after created a resource
0320     if (!mListResourceFile.isEmpty()) {
0321         QDir dir(mTempDirName);
0322         dir.mkdir(defaultPath);
0323         const QString copyToDirName(mTempDirName + QLatin1Char('/') + defaultPath);
0324         if (!QDir().mkpath(copyToDirName)) {
0325             qCWarning(PIMDATAEXPORTERCORE_LOG) << " impossible to create :" << copyToDirName;
0326         }
0327 
0328         for (int i = 0, total = mListResourceFile.size(); i < total; ++i) {
0329             ResourceFiles value = mListResourceFile.at(i);
0330             QMap<QString, QVariant> settings;
0331             if (value.akonadiConfigFile.contains(resourceBaseName + QLatin1Char('_'))) {
0332                 const KArchiveEntry *fileResouceEntry = mArchiveDirectory->entry(value.akonadiConfigFile);
0333                 if (fileResouceEntry && fileResouceEntry->isFile()) {
0334                     const auto file = static_cast<const KArchiveFile *>(fileResouceEntry);
0335                     if (!file->copyTo(copyToDirName)) {
0336                         qCWarning(PIMDATAEXPORTERCORE_LOG)
0337                             << "AbstractImportExportJob file " << value.akonadiConfigFile << " can not copy to " << copyToDirName;
0338                     }
0339                     QString resourceName(file->name());
0340 
0341                     QString filename(file->name());
0342                     // TODO adapt filename otherwise it will use all the time the same filename.
0343                     qCDebug(PIMDATAEXPORTERCORE_LOG) << " filename :" << filename;
0344 
0345                     KSharedConfig::Ptr resourceConfig = KSharedConfig::openConfig(copyToDirName + QLatin1Char('/') + resourceName);
0346 
0347                     QString newUrl = adaptNewResourceUrl(overwriteResources, resourceConfig, storePath);
0348                     const QString dataFile = value.akonadiResources;
0349                     const KArchiveEntry *dataResouceEntry = mArchiveDirectory->entry(dataFile);
0350                     if (dataResouceEntry && dataResouceEntry->isFile()) {
0351                         const auto file = static_cast<const KArchiveFile *>(dataResouceEntry);
0352                         if (!file->copyTo(QFileInfo(newUrl).path())) {
0353                             qCWarning(PIMDATAEXPORTERCORE_LOG) << "AbstractImportExportJob: file " << dataFile << " can not copy to " << newUrl;
0354                         }
0355                     }
0356                     // setPath doesn't exist in groupware
0357                     if (resourceBaseName != QStringLiteral("akonadi_davgroupware_resource")
0358                         && resourceBaseName != QStringLiteral("akonadi_openxchange_resource")
0359                         && resourceBaseName != QStringLiteral("akonadi_google_resource")) {
0360                         if (!newUrl.isEmpty()) {
0361                             settings.insert(QStringLiteral("Path"), newUrl);
0362                         }
0363                     }
0364                     const QString agentConfigFile = value.akonadiAgentConfigFile;
0365                     if (!agentConfigFile.isEmpty()) {
0366                         const KArchiveEntry *akonadiAgentConfigEntry = mArchiveDirectory->entry(agentConfigFile);
0367                         if (akonadiAgentConfigEntry->isFile()) {
0368                             const auto file = static_cast<const KArchiveFile *>(akonadiAgentConfigEntry);
0369                             file->copyTo(copyToDirName);
0370                             resourceName = file->name();
0371                             const QString configPath = copyToDirName + QLatin1Char('/') + resourceName;
0372                             filename = Utils::akonadiAgentName(configPath);
0373                         }
0374                     }
0375 
0376                     addSpecificResourceSettings(resourceConfig, resourceBaseName, settings);
0377 
0378                     const QString newResource = createResource(resourceBaseName, filename, settings, false);
0379                     infoAboutNewResource(newResource);
0380                     resourceToSync << newResource;
0381                     qCDebug(PIMDATAEXPORTERCORE_LOG) << " newResource" << newResource;
0382                 }
0383             }
0384         }
0385         emitInfo(i18n("Resources restored."));
0386     } else {
0387         Q_EMIT error(i18n("No resources files found."));
0388         qDebug() << " resourceBaseName " << resourceBaseName;
0389     }
0390     return resourceToSync;
0391 }
0392 
0393 void AbstractImportExportJob::addSpecificResourceSettings(const KSharedConfig::Ptr /*resourceConfig*/ &,
0394                                                           const QString & /*resourceName*/,
0395                                                           QMap<QString, QVariant> & /*settings*/)
0396 {
0397     // Redefine it in subclass
0398 }
0399 
0400 bool AbstractImportExportJob::copyArchiveFileTo(const KArchiveFile *file, const QString &destination)
0401 {
0402     const bool result = file->copyTo(destination);
0403     if (!result) {
0404         qCWarning(PIMDATAEXPORTERCORE_LOG) << "copyArchiveFileTo file " << file->name() << " can not copy to " << destination;
0405     }
0406     return result;
0407 }
0408 
0409 void AbstractImportExportJob::extractZipFile(const KArchiveFile *file, const QString &source, const QString &destination, bool isStoredAsZippedArchive)
0410 {
0411     if (!file->copyTo(source)) {
0412         qCWarning(PIMDATAEXPORTERCORE_LOG) << "extractZipFile file " << file->name() << " can not copy to " << source;
0413     }
0414     QDir dest(destination);
0415     if (!dest.exists()) {
0416         dest.mkpath(destination);
0417     }
0418     if (isStoredAsZippedArchive) {
0419         QString errorMsg;
0420         KZip *zip = Utils::openZip(source + QLatin1Char('/') + file->name(), errorMsg);
0421         if (zip) {
0422             const KArchiveDirectory *zipDir = zip->directory();
0423             const QStringList lst = zipDir->entries();
0424             for (const QString &entryName : lst) {
0425                 const KArchiveEntry *entry = zipDir->entry(entryName);
0426                 if (entry) {
0427                     if (entry->isDirectory()) {
0428                         const auto dir = static_cast<const KArchiveDirectory *>(entry);
0429                         if (!dir->copyTo(destination + QLatin1Char('/') + dir->name(), true)) {
0430                             qCWarning(PIMDATAEXPORTERCORE_LOG) << " Error to copy directory" << destination + QLatin1Char('/') + dir->name();
0431                         }
0432                     } else if (entry->isFile()) {
0433                         const auto dir = static_cast<const KArchiveFile *>(entry);
0434                         if (!dir->copyTo(destination)) {
0435                             qCWarning(PIMDATAEXPORTERCORE_LOG) << " Error to copy file" << destination;
0436                         }
0437                     }
0438                 }
0439                 qApp->processEvents();
0440             }
0441             delete zip;
0442         } else {
0443             Q_EMIT error(errorMsg);
0444         }
0445     } else {
0446         QFile archiveFile(source + QLatin1Char('/') + file->name());
0447         if (!archiveFile.copy(destination + QLatin1Char('/') + file->name())) {
0448             Q_EMIT error(i18n("Unable to copy file %1", file->name()));
0449         }
0450     }
0451 }
0452 
0453 void AbstractImportExportJob::restoreUiRcFile(const QString &configNameStr, const QString &applicationName)
0454 {
0455     const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr);
0456     if (configNameentry && configNameentry->isFile()) {
0457         const auto configNameconfiguration = static_cast<const KArchiveFile *>(configNameentry);
0458         const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("kxmlgui6") + applicationName
0459             + QLatin1Char('/') + configNameStr;
0460         if (QFileInfo::exists(configNamerc)) {
0461             if (overwriteConfigMessageBox(configNameStr)) {
0462                 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
0463             }
0464         } else {
0465             copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
0466         }
0467     }
0468 }
0469 
0470 void AbstractImportExportJob::restoreConfigFile(const QString &configNameStr)
0471 {
0472     const KArchiveEntry *configNameentry = mArchiveDirectory->entry(Utils::configsPath() + configNameStr);
0473     if (configNameentry && configNameentry->isFile()) {
0474         const auto configNameconfiguration = static_cast<const KArchiveFile *>(configNameentry);
0475         const QString configNamerc = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configNameStr;
0476         if (QFileInfo::exists(configNamerc)) {
0477             // TODO 4.12 allow to merge config.
0478             if (overwriteConfigMessageBox(configNameStr)) {
0479                 copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
0480             }
0481         } else {
0482             copyToFile(configNameconfiguration, configNamerc, configNameStr, Utils::configsPath());
0483         }
0484     }
0485 }
0486 
0487 void AbstractImportExportJob::infoAboutNewResource(const QString &resourceName)
0488 {
0489     emitInfo(i18n("Resource \'%1\' created.", resourceName));
0490 }
0491 
0492 int AbstractImportExportJob::archiveVersion()
0493 {
0494     return sArchiveVersion;
0495 }
0496 
0497 void AbstractImportExportJob::setArchiveVersion(int version)
0498 {
0499     sArchiveVersion = version;
0500 }
0501 
0502 void AbstractImportExportJob::slotSynchronizeInstanceFailed(const QString &instance)
0503 {
0504     Q_EMIT error(i18n("Failed to synchronize \'%1\'.", instance));
0505 }
0506 
0507 void AbstractImportExportJob::slotSynchronizeInstanceDone(const QString &name, const QString &identifier)
0508 {
0509     emitInfo(i18n("Resource \'%1\' synchronized.", name));
0510     Q_EMIT needSynchronizeResource(name, identifier);
0511 }
0512 
0513 void AbstractImportExportJob::slotAllResourceSynchronized()
0514 {
0515     emitInfo(i18n("All resources synchronized."));
0516     slotNextStep();
0517 }
0518 
0519 void AbstractImportExportJob::slotNextStep()
0520 {
0521     // Implement in sub class.
0522 }
0523 
0524 QString AbstractImportExportJob::generateInfo(const QString &info)
0525 {
0526     return applicationName() + QLatin1Char(' ') + info;
0527 }
0528 
0529 void AbstractImportExportJob::emitInfo(const QString &str)
0530 {
0531     Q_EMIT info(generateInfo(str));
0532 }
0533 
0534 void AbstractImportExportJob::emitError(const QString &str)
0535 {
0536     Q_EMIT error(generateInfo(str));
0537 }
0538 
0539 void AbstractImportExportJob::startSynchronizeResources(const QStringList &listResourceToSync)
0540 {
0541     emitInfo(i18n("Start synchronizing..."));
0542     auto job = new SynchronizeResourceJob(this);
0543     job->setListResources(listResourceToSync);
0544     connect(job, &SynchronizeResourceJob::synchronizationFinished, this, &AbstractImportExportJob::slotAllResourceSynchronized);
0545     connect(job, &SynchronizeResourceJob::synchronizationInstanceDone, this, &AbstractImportExportJob::slotSynchronizeInstanceDone);
0546     connect(job, &SynchronizeResourceJob::synchronizationInstanceFailed, this, &AbstractImportExportJob::slotSynchronizeInstanceFailed);
0547     job->start();
0548 }
0549 
0550 void AbstractImportExportJob::initializeListStep()
0551 {
0552     if (mTypeSelected & Utils::MailTransport) {
0553         mListStep << Utils::MailTransport;
0554     }
0555     if (mTypeSelected & Utils::Mails) {
0556         mListStep << Utils::Mails;
0557     }
0558     if (mTypeSelected & Utils::Resources) {
0559         mListStep << Utils::Resources;
0560     }
0561     if (mTypeSelected & Utils::Identity) {
0562         mListStep << Utils::Identity;
0563     }
0564     if (mTypeSelected & Utils::Config) {
0565         mListStep << Utils::Config;
0566     }
0567     if (mTypeSelected & Utils::Data) {
0568         mListStep << Utils::Data;
0569     }
0570 }
0571 
0572 void AbstractImportExportJob::storeDirectory(const QString &subDirectory)
0573 {
0574     const QDir directoryToStore(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + subDirectory);
0575     if (directoryToStore.exists()) {
0576         const bool templateDirAdded = archive()->addLocalDirectory(directoryToStore.path(), Utils::dataPath() + subDirectory);
0577         if (templateDirAdded) {
0578             emitInfo(i18n("Directory \"%1\" added to backup file.", directoryToStore.path()));
0579         } else {
0580             Q_EMIT error(i18n("Directory \"%1\" cannot be added to backup file.", directoryToStore.path()));
0581         }
0582     }
0583 }
0584 
0585 void AbstractImportExportJob::importDataSubdirectory(const QString &subdirectoryRelativePath)
0586 {
0587     const KArchiveEntry *themeEntry = mArchiveDirectory->entry(Utils::dataPath() + subdirectoryRelativePath);
0588     if (themeEntry && themeEntry->isDirectory()) {
0589         const auto themeDir = static_cast<const KArchiveDirectory *>(themeEntry);
0590         const QStringList lst = themeDir->entries();
0591         for (const QString &entryName : lst) {
0592             const KArchiveEntry *entry = themeDir->entry(entryName);
0593             if (entry && entry->isDirectory()) {
0594                 QString subFolderName = entryName;
0595                 const QString topLevelPath =
0596                     QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + subdirectoryRelativePath;
0597                 QDir themeDirectory(topLevelPath + QStringLiteral("/%1").arg(entryName));
0598                 int i = 1;
0599                 while (themeDirectory.exists()) {
0600                     subFolderName = entryName + QStringLiteral("_%1").arg(i);
0601                     themeDirectory = QDir(topLevelPath + QStringLiteral("/%1").arg(subFolderName));
0602                     ++i;
0603                 }
0604                 copyToDirectory(entry, topLevelPath + QStringLiteral("/%1").arg(subFolderName));
0605             }
0606         }
0607     }
0608 }
0609 
0610 void AbstractImportExportJob::convertCollectionListStrToAkonadiId(const KSharedConfig::Ptr &config,
0611                                                                   const QString &groupName,
0612                                                                   const QString &key,
0613                                                                   bool addCollectionPrefix)
0614 {
0615     if (config->hasGroup(groupName)) {
0616         KConfigGroup group = config->group(groupName);
0617         convertRealPathToCollectionList(group, key, addCollectionPrefix);
0618     }
0619 }
0620 
0621 void AbstractImportExportJob::convertRealPathToCollectionList(KConfigGroup &group, const QString &currentKey, bool addCollectionPrefix)
0622 {
0623     if (group.hasKey(currentKey)) {
0624         const QStringList listExpension = group.readEntry(currentKey, QStringList());
0625         QStringList result;
0626         if (!listExpension.isEmpty()) {
0627             for (const QString &collection : listExpension) {
0628                 const Akonadi::Collection::Id id = convertPathToId(collection);
0629                 if (id != -1) {
0630                     if (addCollectionPrefix) {
0631                         result << QStringLiteral("c%1").arg(id);
0632                     } else {
0633                         result << QStringLiteral("%1").arg(id);
0634                     }
0635                 }
0636             }
0637             if (result.isEmpty()) {
0638                 group.deleteEntry(currentKey);
0639             } else {
0640                 group.writeEntry(currentKey, result);
0641             }
0642         }
0643     }
0644 }
0645 
0646 void AbstractImportExportJob::setTempDirName(const QString &tempDirName)
0647 {
0648     mTempDirName = tempDirName;
0649 }
0650 
0651 #include "moc_abstractimportexportjob.cpp"