File indexing completed on 2022-12-06 15:16:21

0001 /*
0002     SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "templatesmanager.h"
0007 
0008 // local
0009 #include "../layout/abstractlayout.h"
0010 #include "../layout/centrallayout.h"
0011 #include "../layouts/importer.h"
0012 #include "../layouts/manager.h"
0013 #include "../layouts/storage.h"
0014 #include "../tools/commontools.h"
0015 #include "../view/view.h"
0016 
0017 // Qt
0018 #include <QDir>
0019 
0020 // KDE
0021 #include <KDirWatch>
0022 #include <KLocalizedString>
0023 
0024 namespace Latte {
0025 namespace Templates {
0026 
0027 Manager::Manager(Latte::Corona *corona)
0028     : QObject(corona),
0029       m_corona(corona)
0030 {
0031     KDirWatch::self()->addDir(Latte::configPath() + "/latte/templates", KDirWatch::WatchFiles);
0032     connect(KDirWatch::self(), &KDirWatch::created, this, &Manager::onCustomTemplatesCountChanged);
0033     connect(KDirWatch::self(), &KDirWatch::deleted, this, &Manager::onCustomTemplatesCountChanged);
0034     connect(KDirWatch::self(), &KDirWatch::dirty, this, &Manager::onCustomTemplatesCountChanged);
0035 }
0036 
0037 Manager::~Manager()
0038 {
0039 }
0040 
0041 void Manager::init()
0042 {
0043     connect(this, &Manager::viewTemplatesChanged, m_corona->layoutsManager(), &Latte::Layouts::Manager::viewTemplatesChanged);
0044 
0045     initLayoutTemplates();
0046     initViewTemplates();
0047 }
0048 
0049 void Manager::initLayoutTemplates()
0050 {
0051     m_layoutTemplates.clear();
0052     initLayoutTemplates(m_corona->kPackage().filePath("templates"));
0053     initLayoutTemplates(Latte::configPath() + "/latte/templates");
0054     emit layoutTemplatesChanged();
0055 }
0056 
0057 void Manager::initViewTemplates()
0058 {
0059     m_viewTemplates.clear();
0060     initViewTemplates(m_corona->kPackage().filePath("templates"));
0061     initViewTemplates(Latte::configPath() + "/latte/templates");
0062     emit viewTemplatesChanged();
0063 }
0064 
0065 void Manager::initLayoutTemplates(const QString &path)
0066 {
0067     QDir templatesDir(path);
0068     QStringList filter;
0069     filter.append(QString("*.layout.latte"));
0070     QStringList templates = templatesDir.entryList(filter, QDir::Files | QDir::Hidden | QDir::NoSymLinks);
0071 
0072     for (int i=0; i<templates.count(); ++i) {
0073         QString templatePath = templatesDir.path() + "/" + templates[i];
0074         if (!m_layoutTemplates.containsId(templatePath)) {
0075             CentralLayout layouttemplate(this, templatePath);
0076 
0077             Data::Layout tdata = layouttemplate.data();
0078             tdata.isTemplate = true;
0079 
0080             if (tdata.name == DEFAULTLAYOUTTEMPLATENAME || tdata.name == EMPTYLAYOUTTEMPLATENAME) {
0081                 QByteArray templateNameChars = tdata.name.toUtf8();
0082                 tdata.name = i18n(templateNameChars);
0083             }
0084 
0085             m_layoutTemplates << tdata;
0086         }
0087     }
0088 }
0089 
0090 void Manager::initViewTemplates(const QString &path)
0091 {
0092     bool istranslated = (m_corona->kPackage().filePath("templates") == path);
0093 
0094     QDir templatesDir(path);
0095     QStringList filter;
0096     filter.append(QString("*.view.latte"));
0097     QStringList templates = templatesDir.entryList(filter, QDir::Files | QDir::Hidden | QDir::NoSymLinks);
0098 
0099     for (int i=0; i<templates.count(); ++i) {
0100         QString templatePath = templatesDir.path() + "/" + templates[i];
0101 
0102         if (!m_viewTemplates.containsId(templatePath)) {
0103             Data::Generic vdata;
0104             vdata.id = templatePath;
0105             QString tname = QFileInfo(templatePath).baseName();
0106 
0107             if (istranslated) {
0108                 QByteArray tnamechars = tname.toUtf8();
0109                 vdata.name = i18nc("view template name", tnamechars);
0110             } else {
0111                 vdata.name = tname;
0112             }
0113 
0114             m_viewTemplates << vdata;
0115         }
0116     }
0117 }
0118 
0119 Data::Layout Manager::layoutTemplateForName(const QString &layoutName)
0120 {
0121     if (m_layoutTemplates.containsName(layoutName)) {
0122         QString layoutid = m_layoutTemplates.idForName(layoutName);
0123         return m_layoutTemplates[layoutid];
0124     }
0125 
0126     return Data::Layout();
0127 }
0128 
0129 Data::LayoutsTable Manager::layoutTemplates()
0130 {
0131     Data::LayoutsTable templates;
0132 
0133     QString id = m_layoutTemplates.idForName(i18n(DEFAULTLAYOUTTEMPLATENAME));
0134     templates << m_layoutTemplates[id];
0135     id = m_layoutTemplates.idForName(i18n(EMPTYLAYOUTTEMPLATENAME));
0136     templates << m_layoutTemplates[id];
0137 
0138     for (int i=0; i<m_layoutTemplates.rowCount(); ++i) {
0139         if ( m_layoutTemplates[i].name != i18n(DEFAULTLAYOUTTEMPLATENAME)
0140              && m_layoutTemplates[i].name != i18n(EMPTYLAYOUTTEMPLATENAME)
0141              && m_layoutTemplates[i].name != Layout::MULTIPLELAYOUTSHIDDENNAME) {
0142             templates << m_layoutTemplates[i];
0143         }
0144     }
0145 
0146     return templates;
0147 }
0148 
0149 Data::GenericBasicTable Manager::viewTemplates()
0150 {
0151     return m_viewTemplates;
0152 }
0153 
0154 QString Manager::newLayout(QString layoutName, QString layoutTemplate)
0155 {
0156     if (!m_layoutTemplates.containsName(layoutTemplate)) {
0157         return QString();
0158     }
0159 
0160     if (layoutName.isEmpty()) {
0161         layoutName = Layouts::Importer::uniqueLayoutName(layoutTemplate);
0162     } else {
0163         layoutName = Layouts::Importer::uniqueLayoutName(layoutName);
0164     }
0165 
0166     QString newLayoutPath = Layouts::Importer::layoutUserFilePath(layoutName);
0167 
0168     Data::Layout dlayout = layoutTemplateForName(layoutTemplate);
0169     QFile(dlayout.id).copy(newLayoutPath);
0170     qDebug() << "adding layout : " << layoutName << " based on layout template:" << layoutTemplate;
0171 
0172     emit newLayoutAdded(newLayoutPath);
0173 
0174     return newLayoutPath;
0175 }
0176 
0177 bool Manager::exportTemplate(const QString &originFile, const QString &destinationFile, const Data::AppletsTable &approvedApplets)
0178 {
0179     return Latte::Layouts::Storage::self()->exportTemplate(originFile, destinationFile, approvedApplets);
0180 }
0181 
0182 bool Manager::exportTemplate(const Latte::View *view, const QString &destinationFile, const Data::AppletsTable &approvedApplets)
0183 {
0184     return Latte::Layouts::Storage::self()->exportTemplate(view->layout(), view->containment(), destinationFile, approvedApplets);
0185 }
0186 
0187 void Manager::onCustomTemplatesCountChanged(const QString &file)
0188 {
0189     if (file.startsWith(Latte::configPath() + "/latte/templates")) {
0190         if (file.endsWith(".layout.latte")) {
0191             initLayoutTemplates();
0192         } else if (file.endsWith(".view.latte")) {
0193             initViewTemplates();
0194         }
0195     }
0196 }
0197 
0198 void Manager::importSystemLayouts()
0199 {
0200     for (int i=0; i<m_layoutTemplates.rowCount(); ++i) {
0201         if (m_layoutTemplates[i].isSystemTemplate()) {
0202             QString userLayoutPath = Layouts::Importer::layoutUserFilePath(m_layoutTemplates[i].name);
0203 
0204             if (!QFile(userLayoutPath).exists()) {
0205                 QFile(m_layoutTemplates[i].id).copy(userLayoutPath);
0206                 qDebug() << "adding layout : " << userLayoutPath << " based on layout template:" << m_layoutTemplates[i].name;
0207             }
0208         }
0209     }
0210 }
0211 
0212 QString Manager::proposedTemplateAbsolutePath(QString templateFilename)
0213 {
0214     QString tempfilename = templateFilename;
0215 
0216     if (tempfilename.endsWith(".layout.latte")) {
0217         QString clearedname = tempfilename.chopped(QString(".layout.latte").size());
0218         tempfilename = uniqueLayoutTemplateName(clearedname) + ".layout.latte";
0219     } else if (tempfilename.endsWith(".view.latte")) {
0220         QString clearedname = tempfilename.chopped(QString(".view.latte").size());
0221         tempfilename = uniqueViewTemplateName(clearedname) + ".view.latte";
0222     }
0223 
0224     return QString(Latte::configPath() + "/latte/templates/" + tempfilename);
0225 }
0226 
0227 bool Manager::hasCustomLayoutTemplate(const QString &templateName) const
0228 {
0229     for (int i=0; i<m_layoutTemplates.rowCount(); ++i) {
0230         if (m_layoutTemplates[i].name == templateName && !m_layoutTemplates[i].isSystemTemplate()) {
0231             return true;
0232         }
0233     }
0234 
0235     return false;
0236 }
0237 
0238 bool Manager::hasLayoutTemplate(const QString &templateName) const
0239 {
0240     return m_layoutTemplates.containsName(templateName);
0241 }
0242 
0243 bool Manager::hasViewTemplate(const QString &templateName) const
0244 {
0245     return m_viewTemplates.containsName(templateName);
0246 }
0247 
0248 QString Manager::viewTemplateFilePath(const QString templateName) const
0249 {
0250     if (m_viewTemplates.containsName(templateName)) {
0251         return m_viewTemplates.idForName(templateName);
0252     }
0253 
0254     return QString();
0255 }
0256 
0257 void Manager::installCustomLayoutTemplate(const QString &templateFilePath)
0258 {
0259     if (!templateFilePath.endsWith(".layout.latte")) {
0260         return;
0261     }
0262 
0263     QString layoutName = QFileInfo(templateFilePath).baseName();
0264 
0265     QString destinationFilePath = Latte::configPath() + "/latte/templates/" + layoutName + ".layout.latte";
0266 
0267     if (hasCustomLayoutTemplate(layoutName)) {
0268         QFile(destinationFilePath).remove();
0269     }
0270 
0271     QFile(templateFilePath).copy(destinationFilePath);
0272 }
0273 
0274 QString Manager::uniqueLayoutTemplateName(QString name) const
0275 {
0276     int pos_ = name.lastIndexOf(QRegExp(QString(" - [0-9]+")));
0277 
0278     if (hasLayoutTemplate(name) && pos_ > 0) {
0279         name = name.left(pos_);
0280     }
0281 
0282     int i = 2;
0283 
0284     QString namePart = name;
0285 
0286     while (hasLayoutTemplate(name)) {
0287         name = namePart + " - " + QString::number(i);
0288         i++;
0289     }
0290 
0291     return name;
0292 }
0293 
0294 QString Manager::uniqueViewTemplateName(QString name) const
0295 {
0296     int pos_ = name.lastIndexOf(QRegExp(QString(" - [0-9]+")));
0297 
0298     if (hasViewTemplate(name) && pos_ > 0) {
0299         name = name.left(pos_);
0300     }
0301 
0302     int i = 2;
0303 
0304     QString namePart = name;
0305 
0306     while (hasViewTemplate(name)) {
0307         name = namePart + " - " + QString::number(i);
0308         i++;
0309     }
0310 
0311     return name;
0312 }
0313 
0314 QString Manager::templateName(const QString &filePath)
0315 {
0316     int lastSlash = filePath.lastIndexOf("/");
0317     QString tempFilePath = filePath;
0318     QString templatename = tempFilePath.remove(0, lastSlash + 1);
0319 
0320     QString extension(".layout.latte");
0321     int ext = templatename.lastIndexOf(extension);
0322     if (ext>0) {
0323         templatename = templatename.remove(ext, extension.size());
0324     } else {
0325         extension = ".view.latte";
0326         ext = templatename.lastIndexOf(extension);
0327         templatename = templatename.remove(ext,extension.size());
0328     }
0329 
0330     return templatename;
0331 }
0332 
0333 //! it is used in order to provide translations for system templates
0334 void Manager::exposeTranslatedTemplateNames()
0335 {
0336     //! layout templates default names
0337     i18nc("default layout template name", "Default");
0338     i18nc("empty layout template name", "Empty");
0339 
0340     //! dock/panel templates default names
0341     i18nc("view template name", "Default Dock");
0342     i18nc("view template name", "Default Panel");
0343     i18nc("view template name", "Empty Panel");
0344 }
0345 
0346 }
0347 }