File indexing completed on 2024-04-21 13:07:29

0001 /*
0002     SPDX-FileCopyrightText: 2017 Smith AR <audoban@openmailbox.org>
0003     SPDX-FileCopyrightText: 2017 Michail Vourlakos <mvourlakos@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "importer.h"
0009 
0010 // local
0011 #include <coretypes.h>
0012 #include "manager.h"
0013 #include "../lattecorona.h"
0014 #include "../screenpool.h"
0015 #include "../layout/abstractlayout.h"
0016 #include "../settings/universalsettings.h"
0017 #include "../templates/templatesmanager.h"
0018 #include "../tools/commontools.h"
0019 
0020 // Qt
0021 #include <QFile>
0022 #include <QLatin1String>
0023 
0024 // KDE
0025 #include <KArchive/KTar>
0026 #include <KArchive/KArchiveEntry>
0027 #include <KArchive/KArchiveDirectory>
0028 #include <KConfigGroup>
0029 #include <KLocalizedString>
0030 #include <KNotification>
0031 
0032 
0033 enum SessionType
0034 {
0035     DefaultSession = 0,
0036     AlternativeSession
0037 };
0038 
0039 namespace Latte {
0040 namespace Layouts {
0041 
0042 Importer::Importer(QObject *parent)
0043     : QObject(parent)
0044 {
0045     m_manager = qobject_cast<Layouts::Manager *>(parent);
0046 
0047     qDebug() << " IMPORTER, STORAGE TEMP DIR ::: " << m_storageTmpDir.path();
0048 }
0049 
0050 Importer::~Importer()
0051 {
0052 }
0053 
0054 bool Importer::updateOldConfiguration()
0055 {
0056     QFile oldAppletsFile(Latte::configPath() + "/lattedock-appletsrc");
0057 
0058     if (!oldAppletsFile.exists()) {
0059         return false;
0060     }
0061 
0062     //! import standard old configuration and create the relevant layouts
0063     importOldLayout(Latte::configPath() + "/lattedock-appletsrc", i18n("My Layout"));
0064     importOldLayout(Latte::configPath() + "/lattedock-appletsrc", i18n("Alternative"), true);
0065 
0066     QFile extFile(Latte::configPath() + "/lattedockextrc");
0067 
0068     //! import also the old user layouts into the new architecture
0069     if (extFile.exists()) {
0070         KSharedConfigPtr extFileConfig = KSharedConfig::openConfig(extFile.fileName());
0071         KConfigGroup externalSettings = KConfigGroup(extFileConfig, "External");
0072         QStringList userLayouts = externalSettings.readEntry("userLayouts", QStringList());
0073 
0074         for(const auto &userConfig : userLayouts) {
0075             qDebug() << "user layout : " << userConfig;
0076             importOldConfiguration(userConfig);
0077         }
0078     }
0079 
0080     m_manager->corona()->universalSettings()->setVersion(2);
0081     m_manager->corona()->universalSettings()->setSingleModeLayoutName(i18n("My Layout"));
0082 
0083     return true;
0084 }
0085 
0086 bool Importer::importOldLayout(QString oldAppletsPath, QString newName, bool alternative, QString exportDirectory)
0087 {
0088     QString newLayoutPath = layoutCanBeImported(oldAppletsPath, newName, exportDirectory);
0089     qDebug() << "New Layout Should be created: " << newLayoutPath;
0090 
0091     KSharedConfigPtr oldFile = KSharedConfig::openConfig(oldAppletsPath);
0092     KSharedConfigPtr newFile = KSharedConfig::openConfig(newLayoutPath);
0093 
0094     KConfigGroup containments = KConfigGroup(oldFile, "Containments");
0095     KConfigGroup copiedContainments = KConfigGroup(newFile, "Containments");
0096 
0097     QList<int> systrays;
0098 
0099     bool atLeastOneContainmentWasFound{false};
0100 
0101     //! first copy the latte containments that correspond to the correct session
0102     //! and find also the systrays that should be copied also
0103     for(const auto &containmentId : containments.groupList()) {
0104         KConfigGroup containmentGroup = containments.group(containmentId);
0105 
0106         QString plugin = containmentGroup.readEntry("plugin", QString());
0107         SessionType session = (SessionType)containmentGroup.readEntry("session", (int)DefaultSession);
0108 
0109         bool shouldImport = false;
0110 
0111         if (plugin == QLatin1String("org.kde.latte.containment") && session == DefaultSession && !alternative) {
0112             qDebug() << containmentId << " - " << plugin << " - " << session;
0113             shouldImport = true;
0114         } else if (plugin == QLatin1String("org.kde.latte.containment") && session == AlternativeSession && alternative) {
0115             qDebug() << containmentId << " - " << plugin << " - " << session;
0116             shouldImport = true;
0117         }
0118 
0119         // this latte containment should be imported
0120         if (shouldImport) {
0121             auto applets = containments.group(containmentId).group("Applets");
0122 
0123             for(const auto &applet : applets.groupList()) {
0124                 KConfigGroup appletSettings = applets.group(applet).group("Configuration");
0125 
0126                 int systrayId = appletSettings.readEntry("SystrayContainmentId", "-1").toInt();
0127 
0128                 if (systrayId != -1) {
0129                     systrays.append(systrayId);
0130                     qDebug() << "systray was found in the containment...";
0131                     break;
0132                 }
0133             }
0134 
0135             KConfigGroup newContainment = copiedContainments.group(containmentId);
0136             containmentGroup.copyTo(&newContainment);
0137             atLeastOneContainmentWasFound = true;
0138         }
0139     }
0140 
0141     //! not even one latte containment was found for that layout so we must break
0142     //! the code here
0143     if (!atLeastOneContainmentWasFound) {
0144         return false;
0145     }
0146 
0147     //! copy also the systrays that were discovered
0148     for(const auto &containmentId : containments.groupList()) {
0149         int cId = containmentId.toInt();
0150 
0151         if (systrays.contains(cId)) {
0152             KConfigGroup containmentGroup = containments.group(containmentId);
0153             KConfigGroup newContainment = copiedContainments.group(containmentId);
0154             containmentGroup.copyTo(&newContainment);
0155         }
0156     }
0157 
0158     copiedContainments.sync();
0159 
0160     KConfigGroup oldGeneralSettings = KConfigGroup(oldFile, "General");
0161 
0162     QStringList layoutLaunchers;
0163 
0164     if (!alternative) {
0165         layoutLaunchers = oldGeneralSettings.readEntry("globalLaunchers_default", QStringList());
0166     } else {
0167         layoutLaunchers = oldGeneralSettings.readEntry("globalLaunchers_alternative", QStringList());
0168     }
0169 
0170     //! update also the layout settings correctly
0171     Layout::AbstractLayout newLayout(this, newLayoutPath, newName);
0172     newLayout.setVersion(2);
0173     newLayout.setLaunchers(layoutLaunchers);
0174 
0175     //newLayout.setShowInMenu(true);
0176 
0177     if (alternative) {
0178         newLayout.setColor("purple");
0179     } else {
0180         newLayout.setColor("blue");
0181     }
0182 
0183     return true;
0184 }
0185 
0186 QStringList Importer::standardPaths(bool localfirst)
0187 {
0188     QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
0189 
0190     if (localfirst) {
0191         return paths;
0192     } else {
0193         QStringList reversed;
0194 
0195         for (int i=paths.count()-1; i>=0; i--) {
0196             reversed << paths[i];
0197         }
0198 
0199         return reversed;
0200     }
0201 }
0202 
0203 QStringList Importer::standardPathsFor(QString subPath, bool localfirst)
0204 {
0205     QStringList paths = standardPaths(localfirst);
0206 
0207     QString separator = subPath.startsWith("/") ? "" : "/";
0208 
0209     for (int i=0; i<paths.count(); ++i) {
0210         paths[i] = paths[i] + separator + subPath;
0211     }
0212 
0213     return paths;
0214 }
0215 
0216 QString Importer::standardPath(QString subPath, bool localfirst)
0217 {
0218     QStringList paths = standardPaths(localfirst);
0219 
0220     for(const auto &pt : paths) {
0221         QString ptF = pt + "/" +subPath;
0222         if (QFileInfo(ptF).exists()) {
0223             return ptF;
0224         }
0225     }
0226 
0227     //! in any case that above fails
0228     if (QFileInfo("/usr/share/"+subPath).exists()) {
0229         return "/usr/share/"+subPath;
0230     }
0231 
0232     return "";
0233 }
0234 
0235 QString Importer::storageTmpDir() const
0236 {
0237     return m_storageTmpDir.path();
0238 }
0239 
0240 QString Importer::layoutCanBeImported(QString oldAppletsPath, QString newName, QString exportDirectory)
0241 {
0242     QFile oldAppletsrc(oldAppletsPath);
0243 
0244     //! old file doesn't exist
0245     if (!oldAppletsrc.exists()) {
0246         return QString();
0247     }
0248 
0249     KSharedConfigPtr lConfig = KSharedConfig::openConfig(oldAppletsPath);
0250     KConfigGroup m_layoutGroup = KConfigGroup(lConfig, "LayoutSettings");
0251     int layoutVersion = m_layoutGroup.readEntry("version", 1);
0252 
0253     //! old file layout appears to not be old as its version is >=2
0254     if (layoutVersion >= 2) {
0255         return QString();
0256     }
0257 
0258     QDir layoutDir(exportDirectory.isNull() ? layoutUserDir() : exportDirectory);
0259 
0260     if (!layoutDir.exists() && exportDirectory.isNull()) {
0261         QDir(Latte::configPath()).mkdir("latte");
0262     }
0263 
0264     //! set up the new layout name
0265     if (newName.isEmpty()) {
0266         int extension = oldAppletsrc.fileName().lastIndexOf(".latterc");
0267 
0268         if (extension > 0) {
0269             //! remove the last 8 characters that contain the extension
0270             newName = oldAppletsrc.fileName().remove(extension, 8);
0271         } else {
0272             newName = oldAppletsrc.fileName();
0273         }
0274     }
0275 
0276     QString newLayoutPath = layoutDir.absolutePath() + "/" + newName + ".layout.latte";
0277     QFile newLayoutFile(newLayoutPath);
0278 
0279     QStringList filter;
0280     filter.append(QString(newName + "*.layout.latte"));
0281     QStringList files = layoutDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0282 
0283     //! if the newLayout already exists provide a newName that doesn't
0284     if (files.count() >= 1) {
0285         int newCounter = files.count() + 1;
0286 
0287         newLayoutPath = layoutDir.absolutePath() + "/" + newName + "-" + QString::number(newCounter) + ".layout.latte";
0288     }
0289 
0290     return newLayoutPath;
0291 }
0292 
0293 bool Importer::importOldConfiguration(QString oldConfigPath, QString newName)
0294 {
0295     QFile oldConfigFile(oldConfigPath);
0296 
0297     if (!oldConfigFile.exists()) {
0298         return false;
0299     }
0300 
0301     KTar archive(oldConfigPath, QStringLiteral("application/x-tar"));
0302     archive.open(QIODevice::ReadOnly);
0303 
0304     if (!archive.isOpen()) {
0305         return false;
0306     }
0307 
0308     auto rootDir = archive.directory();
0309     QTemporaryDir uniqueTempDir;
0310     QDir tempDir{uniqueTempDir.path()};
0311 
0312     qDebug() << "temp layout directory : " << tempDir.absolutePath();
0313 
0314     if (rootDir) {
0315         if (!tempDir.exists())
0316             tempDir.mkpath(tempDir.absolutePath());
0317 
0318         for(const auto &name : rootDir->entries()) {
0319             auto fileEntry = rootDir->file(name);
0320 
0321             if (fileEntry && (fileEntry->name() == QLatin1String("lattedockrc")
0322                               || fileEntry->name() == QLatin1String("lattedock-appletsrc"))) {
0323                 if (!fileEntry->copyTo(tempDir.absolutePath())) {
0324                     qInfo() << i18nc("import/export config", "The extracted file could not be copied!!!");
0325                     archive.close();
0326                     return false;
0327                 }
0328             } else {
0329                 qInfo() << i18nc("import/export config", "The file has a wrong format!!!");
0330                 archive.close();
0331                 return false;
0332             }
0333         }
0334     } else {
0335         qInfo() << i18nc("import/export config", "The temp directory could not be created!!!");
0336         archive.close();
0337         return false;
0338     }
0339 
0340     //! only if the above has passed we must process the files
0341     QString appletsPath(tempDir.absolutePath() + "/lattedock-appletsrc");
0342     QString screensPath(tempDir.absolutePath() + "/lattedockrc");
0343 
0344     if (!QFile(appletsPath).exists() || !QFile(screensPath).exists()) {
0345         return false;
0346     }
0347 
0348 
0349     if (newName.isEmpty()) {
0350         int lastSlash = oldConfigPath.lastIndexOf("/");
0351         newName = oldConfigPath.remove(0, lastSlash + 1);
0352 
0353         int ext = newName.lastIndexOf(".latterc");
0354         newName = newName.remove(ext, 8);
0355     }
0356 
0357     if (!importOldLayout(appletsPath, newName)) {
0358         return false;
0359     }
0360 
0361     //! the old configuration contains also screen values, these must be updated also
0362     /*
0363     * do not use any deprecated screen ids
0364     * KSharedConfigPtr oldScreensConfig = KSharedConfig::openConfig(screensPath);
0365     KConfigGroup m_screensGroup = KConfigGroup(oldScreensConfig, "ScreenConnectors");
0366 
0367     //restore the known ids to connector mappings
0368     for(const QString &key : m_screensGroup.keyList()) {
0369         QString connector = m_screensGroup.readEntry(key, QString());
0370         int id = key.toInt();
0371 
0372         if (id >= 10 && !m_manager->corona()->screenPool()->hasScreenId(id)) {
0373             m_manager->corona()->screenPool()->insertScreenMapping(id, connector);
0374         }
0375     }*/
0376 
0377     return true;
0378 }
0379 
0380 bool Importer::exportFullConfiguration(QString file)
0381 {
0382     if (QFile::exists(file) && !QFile::remove(file)) {
0383         return false;
0384     }
0385 
0386     KTar archive(file, QStringLiteral("application/x-tar"));
0387 
0388     if (!archive.open(QIODevice::WriteOnly)) {
0389         return false;
0390     }
0391 
0392     archive.addLocalFile(QString(Latte::configPath() + "/lattedockrc"), QStringLiteral("lattedockrc"));
0393 
0394     for(const auto &layoutName : availableLayouts()) {
0395         archive.addLocalFile(layoutUserFilePath(layoutName), QString("latte/" + layoutName + ".layout.latte"));
0396     }
0397 
0398     //! custom templates
0399     QDir templatesDir(Latte::configPath() + "/latte/templates");
0400     QStringList filters;
0401     filters.append(QString("*.layout.latte"));
0402     QStringList templates = templatesDir.entryList(filters, QDir::Files | QDir::Hidden | QDir::NoSymLinks);
0403 
0404     for (int i=0; i<templates.count(); ++i) {
0405         QString templatePath = templatesDir.path() + "/" + templates[i];
0406         archive.addLocalFile(templatePath, QString("latte/templates/" + templates[i]));
0407     }
0408 
0409     filters.clear();
0410     filters.append(QString("*.view.latte"));
0411     templates = templatesDir.entryList(filters, QDir::Files | QDir::Hidden | QDir::NoSymLinks);
0412 
0413     for (int i=0; i<templates.count(); ++i) {
0414         QString templatePath = templatesDir.path() + "/" + templates[i];
0415         archive.addLocalFile(templatePath, QString("latte/templates/" + templates[i]));
0416     }
0417 
0418     archive.close();
0419 
0420     return true;
0421 }
0422 
0423 Importer::LatteFileVersion Importer::fileVersion(QString file)
0424 {
0425     if (!QFile::exists(file))
0426         return UnknownFileType;
0427 
0428     if (file.endsWith(".layout.latte")) {
0429         KSharedConfigPtr lConfig = KSharedConfig::openConfig(QFileInfo(file).absoluteFilePath());
0430         KConfigGroup layoutGroup = KConfigGroup(lConfig, "LayoutSettings");
0431         int version = layoutGroup.readEntry("version", 1);
0432 
0433         if (version == 2)
0434             return Importer::LayoutVersion2;
0435         else
0436             return Importer::UnknownFileType;
0437     }
0438 
0439     if (!file.endsWith(".latterc")) {
0440         return Importer::UnknownFileType;
0441     }
0442 
0443     KTar archive(file, QStringLiteral("application/x-tar"));
0444     archive.open(QIODevice::ReadOnly);
0445 
0446     //! if the file isnt a tar archive
0447     if (!archive.isOpen()) {
0448         return Importer::UnknownFileType;
0449     }
0450 
0451     QTemporaryDir archiveTempDir;
0452 
0453     bool version1rc = false;
0454     bool version1applets = false;
0455 
0456     bool version2rc = false;
0457     bool version2LatteDir = false;
0458     bool version2layout = false;
0459 
0460     archive.directory()->copyTo(archiveTempDir.path());
0461 
0462 
0463     //rc file
0464     QString rcFile(archiveTempDir.path() + "/lattedockrc");
0465 
0466     if (QFile(rcFile).exists()) {
0467         KSharedConfigPtr lConfig = KSharedConfig::openConfig(rcFile);
0468         KConfigGroup universalGroup = KConfigGroup(lConfig, "UniversalSettings");
0469         int version = universalGroup.readEntry("version", 1);
0470 
0471         if (version == 1) {
0472             version1rc = true;
0473         } else if (version == 2) {
0474             version2rc = true;
0475         }
0476     }
0477 
0478     //applets file
0479     QString appletsFile(archiveTempDir.path() + "/lattedock-appletsrc");
0480 
0481     if (QFile(appletsFile).exists() && version1rc) {
0482         KSharedConfigPtr lConfig = KSharedConfig::openConfig(appletsFile);
0483         KConfigGroup generalGroup = KConfigGroup(lConfig, "LayoutSettings");
0484         int version = generalGroup.readEntry("version", 1);
0485 
0486         if (version == 1) {
0487             version1applets = true;
0488         } else if (version == 2) {
0489             version2layout = true;
0490         }
0491     }
0492 
0493     //latte directory
0494     QString latteDir(archiveTempDir.path() + "/latte");
0495 
0496     if (QDir(latteDir).exists()) {
0497         version2LatteDir = true;
0498     }
0499 
0500     if (version1applets) {
0501         return ConfigVersion1;
0502     } else if (version2rc && version2LatteDir) {
0503         return ConfigVersion2;
0504     }
0505 
0506     return Importer::UnknownFileType;
0507 }
0508 
0509 bool Importer::importHelper(QString fileName)
0510 {
0511     LatteFileVersion version = fileVersion(fileName);
0512 
0513     if ((version != ConfigVersion1) && (version != ConfigVersion2)) {
0514         return false;
0515     }
0516 
0517     KTar archive(fileName, QStringLiteral("application/x-tar"));
0518     archive.open(QIODevice::ReadOnly);
0519 
0520     if (!archive.isOpen()) {
0521         return false;
0522     }
0523 
0524     QDir latteDir(layoutUserDir());
0525 
0526     if (latteDir.exists()) {
0527         latteDir.removeRecursively();
0528     }
0529 
0530     archive.directory()->copyTo(Latte::configPath());
0531 
0532     return true;
0533 }
0534 
0535 bool Importer::isAutostartEnabled()
0536 {
0537     QFile autostartFile(Latte::configPath() + "/autostart/org.kde.latte-dock.desktop");
0538     return autostartFile.exists();
0539 }
0540 
0541 void Importer::enableAutostart()
0542 {
0543     //! deprecated old file
0544     QFile oldAutostartFile(Latte::configPath() + "/autostart/latte-dock.desktop");
0545 
0546     if (oldAutostartFile.exists()) {
0547         //! remove deprecated file
0548         oldAutostartFile.remove();
0549     }
0550 
0551     QFile autostartFile(Latte::configPath() + "/autostart/org.kde.latte-dock.desktop");
0552     QFile metaFile(standardPath("applications/org.kde.latte-dock.desktop", false));
0553 
0554     if (autostartFile.exists()) {
0555         //! if autostart file already exists, do nothing
0556         return;
0557     }
0558 
0559     if (metaFile.exists()) {
0560         //! check if autostart folder exists and create otherwise
0561         QDir autostartDir(Latte::configPath() + "/autostart");
0562         if (!autostartDir.exists()) {
0563             QDir configDir(Latte::configPath());
0564             configDir.mkdir("autostart");
0565         }
0566 
0567         metaFile.copy(autostartFile.fileName());
0568     }
0569 }
0570 
0571 void Importer::disableAutostart()
0572 {
0573     QFile oldAutostartFile(Latte::configPath() + "/autostart/latte-dock.desktop");
0574 
0575     if (oldAutostartFile.exists()) {
0576         //! remove deprecated file
0577         oldAutostartFile.remove();
0578     }
0579 
0580     QFile autostartFile(Latte::configPath() + "/autostart/org.kde.latte-dock.desktop");
0581 
0582     if (autostartFile.exists()) {
0583         autostartFile.remove();
0584     }
0585 }
0586 
0587 bool Importer::hasViewTemplate(const QString &name)
0588 {
0589     return availableViewTemplates().contains(name);
0590 }
0591 
0592 QString Importer::importLayout(const QString &fileName, const QString &suggestedLayoutName)
0593 {
0594     QString newLayoutName = importLayoutHelper(fileName, suggestedLayoutName);
0595 
0596     if (!newLayoutName.isEmpty()) {
0597         emit newLayoutAdded(layoutUserFilePath(newLayoutName));
0598     }
0599 
0600     return newLayoutName;
0601 }
0602 
0603 QString Importer::importLayoutHelper(const QString &fileName, const QString &suggestedLayoutName)
0604 {
0605     LatteFileVersion version = fileVersion(fileName);
0606 
0607     if (version != LayoutVersion2) {
0608         return QString();
0609     }
0610 
0611     QString newLayoutName = !suggestedLayoutName.isEmpty() ? suggestedLayoutName : Layout::AbstractLayout::layoutName(fileName);
0612     newLayoutName = uniqueLayoutName(newLayoutName);
0613 
0614     QString newPath = layoutUserFilePath(newLayoutName);
0615 
0616     QDir localLayoutsDir(layoutUserDir());
0617 
0618     if (!localLayoutsDir.exists()) {
0619         QDir(Latte::configPath()).mkdir("latte");
0620     }
0621 
0622     QFile(fileName).copy(newPath);
0623 
0624     QFileInfo newFileInfo(newPath);
0625 
0626     if (newFileInfo.exists() && !newFileInfo.isWritable()) {
0627         QFile(newPath).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther);
0628     }
0629 
0630     return newLayoutName;
0631 }
0632 
0633 QStringList Importer::availableLayouts()
0634 {
0635     QDir layoutDir(layoutUserDir());
0636     QStringList filter;
0637     filter.append(QString("*.layout.latte"));
0638     QStringList files = layoutDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0639 
0640     QStringList layoutNames;
0641 
0642     for(const auto &file : files) {
0643         layoutNames.append(Layout::AbstractLayout::layoutName(file));
0644     }
0645 
0646     return layoutNames;
0647 }
0648 
0649 QStringList Importer::availableViewTemplates()
0650 {
0651     QStringList templates;
0652 
0653     QDir localDir(layoutUserDir() + "/templates");
0654     QStringList filter;
0655     filter.append(QString("*.view.latte"));
0656     QStringList files = localDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0657 
0658     for(const auto &file : files) {
0659         templates.append(Templates::Manager::templateName(file));
0660     }
0661 
0662     QDir systemDir(systemShellDataPath()+"/contents/templates");
0663     QStringList sfiles = systemDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0664 
0665     for(const auto &file : sfiles) {
0666         QString name = Templates::Manager::templateName(file);
0667         if (!templates.contains(name)) {
0668             templates.append(name);
0669         }
0670     }
0671 
0672     return templates;
0673 }
0674 
0675 QStringList Importer::availableLayoutTemplates()
0676 {
0677     QStringList templates;
0678 
0679     QDir localDir(layoutUserDir() + "/templates");
0680     QStringList filter;
0681     filter.append(QString("*.layout.latte"));
0682     QStringList files = localDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0683 
0684     for(const auto &file : files) {
0685         templates.append(Templates::Manager::templateName(file));
0686     }
0687 
0688     QDir systemDir(systemShellDataPath()+"/contents/templates");
0689     QStringList sfiles = systemDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
0690 
0691     for(const auto &file : sfiles) {
0692         QString name = Templates::Manager::templateName(file);
0693         if (!templates.contains(name)) {
0694             templates.append(name);
0695         }
0696     }
0697 
0698     return templates;
0699 }
0700 
0701 QString Importer::nameOfConfigFile(const QString &fileName)
0702 {
0703     int lastSlash = fileName.lastIndexOf("/");
0704     QString tempLayoutFile = fileName;
0705     QString layoutName = tempLayoutFile.remove(0, lastSlash + 1);
0706 
0707     int ext = layoutName.lastIndexOf(".latterc");
0708     layoutName = layoutName.remove(ext, 8);
0709 
0710     return layoutName;
0711 }
0712 
0713 bool Importer::layoutExists(QString layoutName)
0714 {
0715     return QFile::exists(layoutUserFilePath(layoutName));
0716 }
0717 
0718 
0719 QString Importer::layoutUserDir()
0720 {
0721     return QString(Latte::configPath() + "/latte");
0722 }
0723 
0724 QString Importer::layoutUserFilePath(QString layoutName)
0725 {
0726     return QString(layoutUserDir() + "/" + layoutName + ".layout.latte");
0727 }
0728 
0729 QString Importer::systemShellDataPath()
0730 {
0731     QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
0732     QString rootpath = paths.count() > 0 ? paths[paths.count()-1] : "/usr/share";
0733     return  rootpath + "/plasma/shells/org.kde.latte.shell";
0734 }
0735 
0736 QString Importer::layoutTemplateSystemFilePath(const QString &name)
0737 {
0738     return systemShellDataPath() + "/contents/templates/" + name + ".layout.latte";
0739 }
0740 
0741 QString Importer::uniqueLayoutName(QString name)
0742 {
0743     int pos_ = name.lastIndexOf(QRegExp(QString(" - [0-9]+")));
0744 
0745     if (layoutExists(name) && pos_ > 0) {
0746         name = name.left(pos_);
0747     }
0748 
0749     int i = 2;
0750 
0751     QString namePart = name;
0752 
0753     while (layoutExists(name)) {
0754         name = namePart + " - " + QString::number(i);
0755         i++;
0756     }
0757 
0758     return name;
0759 }
0760 
0761 Latte::MultipleLayouts::Status Importer::multipleLayoutsStatus()
0762 {
0763     QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
0764     if (!QFileInfo(linkedFilePath).exists()) {
0765         return Latte::MultipleLayouts::Uninitialized;
0766     }
0767 
0768     KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
0769     KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
0770     return static_cast<Latte::MultipleLayouts::Status>(multipleSettings.readEntry("status", (int)Latte::MultipleLayouts::Uninitialized));
0771 }
0772 
0773 void Importer::setMultipleLayoutsStatus(const Latte::MultipleLayouts::Status &status)
0774 {
0775     QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
0776 
0777     if (!QFileInfo(linkedFilePath).exists()) {
0778         return;
0779     }
0780 
0781     if (multipleLayoutsStatus() == status) {
0782         return;
0783     }
0784 
0785     qDebug() << " MULTIPLE LAYOUTS changed status:" << status;
0786 
0787     KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
0788     KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
0789     multipleSettings.writeEntry("status", (int)(status));
0790     multipleSettings.sync();
0791 }
0792 
0793 QStringList Importer::checkRepairMultipleLayoutsLinkedFile()
0794 {
0795     QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
0796     KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
0797     KConfigGroup linkedContainments = KConfigGroup(filePtr, "Containments");
0798 
0799     //! layoutName and its Containments
0800     QHash<QString, QStringList> linkedLayoutContainmentGroups;
0801 
0802     for(const auto &cId : linkedContainments.groupList()) {
0803         QString layoutName = linkedContainments.group(cId).readEntry("layoutId", QString());
0804 
0805         if (!layoutName.isEmpty()) {
0806             qDebug() << layoutName;
0807             linkedLayoutContainmentGroups[layoutName].append(cId);
0808             linkedContainments.group(cId).writeEntry("layoutId", QString());
0809         }
0810     }
0811 
0812     QStringList updatedLayouts;
0813 
0814     for(const auto &layoutName : linkedLayoutContainmentGroups.uniqueKeys()) {
0815         if (layoutName != Layout::MULTIPLELAYOUTSHIDDENNAME && layoutExists(layoutName)) {
0816             updatedLayouts << layoutName;
0817             KSharedConfigPtr layoutFilePtr = KSharedConfig::openConfig(layoutUserFilePath(layoutName));
0818             KConfigGroup origLayoutContainments = KConfigGroup(layoutFilePtr, "Containments");
0819 
0820             //Clear old containments
0821             origLayoutContainments.deleteGroup();
0822 
0823             //Update containments
0824             for(const auto &cId : linkedLayoutContainmentGroups[layoutName]) {
0825                 KConfigGroup newContainment = origLayoutContainments.group(cId);
0826                 linkedContainments.group(cId).copyTo(&newContainment);
0827                 linkedContainments.group(cId).deleteGroup();
0828             }
0829 
0830             origLayoutContainments.sync();
0831         }
0832     }
0833 
0834     //! clear all remaining ghost containments
0835     for(const auto &cId : linkedContainments.groupList()) {
0836         linkedContainments.group(cId).deleteGroup();
0837     }
0838 
0839     linkedContainments.sync();
0840 
0841     return updatedLayouts;
0842 }
0843 
0844 }
0845 }