1 /*
2   SPDX-FileCopyrightText: 2013-2021 Laurent Montel <montel@kde.org>
3 
4   SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "templatemanager.h"
8 #include "pimcommon_debug.h"
9 #include "templatewidgets/templatelistwidget.h"
10 
11 #include <KDirWatch>
12 
13 #include <KConfig>
14 #include <KConfigGroup>
15 
16 #include <QDirIterator>
17 #include <QStandardPaths>
18 
19 using namespace PimCommon;
20 
21 class PimCommon::TemplateManagerPrivate
22 {
23 public:
24     QStringList mTemplatesDirectories;
25     PimCommon::TemplateListWidget *mTemplateListWidget = nullptr;
26     KDirWatch *mDirWatch = nullptr;
27 };
28 
TemplateManager(const QString & relativeTemplateDir,PimCommon::TemplateListWidget * templateListWidget)29 TemplateManager::TemplateManager(const QString &relativeTemplateDir, PimCommon::TemplateListWidget *templateListWidget)
30     : QObject(templateListWidget)
31     , d(new PimCommon::TemplateManagerPrivate)
32 {
33     d->mTemplateListWidget = templateListWidget;
34     d->mDirWatch = new KDirWatch(this);
35     initTemplatesDirectories(relativeTemplateDir);
36 
37     connect(d->mDirWatch, &KDirWatch::dirty, this, &TemplateManager::slotDirectoryChanged);
38     loadTemplates(true);
39 }
40 
41 TemplateManager::~TemplateManager() = default;
42 
slotDirectoryChanged()43 void TemplateManager::slotDirectoryChanged()
44 {
45     d->mTemplateListWidget->loadTemplates();
46     loadTemplates();
47 }
48 
initTemplatesDirectories(const QString & templatesRelativePath)49 void TemplateManager::initTemplatesDirectories(const QString &templatesRelativePath)
50 {
51     if (!templatesRelativePath.isEmpty()) {
52         d->mTemplatesDirectories = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, templatesRelativePath, QStandardPaths::LocateDirectory);
53         if (d->mTemplatesDirectories.count() < 2) {
54             // Make sure to add local directory
55             const QString localDirectory = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + templatesRelativePath;
56             if (!d->mTemplatesDirectories.contains(localDirectory)) {
57                 d->mTemplatesDirectories.append(localDirectory);
58             }
59         }
60     }
61 }
62 
loadTemplates(bool init)63 void TemplateManager::loadTemplates(bool init)
64 {
65     if (!init) {
66         if (!d->mTemplatesDirectories.isEmpty()) {
67             for (const QString &directory : std::as_const(d->mTemplatesDirectories)) {
68                 d->mDirWatch->removeDir(directory);
69             }
70         } else {
71             return;
72         }
73     }
74 
75     for (const QString &directory : std::as_const(d->mTemplatesDirectories)) {
76         QDirIterator dirIt(directory, QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot);
77         while (dirIt.hasNext()) {
78             dirIt.next();
79             TemplateInfo info = loadTemplate(dirIt.filePath(), QStringLiteral("template.desktop"));
80             if (info.isValid()) {
81                 d->mTemplateListWidget->addDefaultTemplate(info.name, info.script);
82             }
83         }
84         d->mDirWatch->addDir(directory);
85     }
86     d->mDirWatch->startScan();
87 }
88 
loadTemplate(const QString & themePath,const QString & defaultDesktopFileName)89 TemplateInfo TemplateManager::loadTemplate(const QString &themePath, const QString &defaultDesktopFileName)
90 {
91     TemplateInfo info;
92     const QString themeInfoFile = themePath + QLatin1Char('/') + defaultDesktopFileName;
93     KConfig config(themeInfoFile);
94     KConfigGroup group(&config, QStringLiteral("Desktop Entry"));
95 
96     info.name = group.readEntry("Name", QString());
97     const QString filename = group.readEntry("FileName", QString());
98     if (!filename.isEmpty()) {
99         QFile file(themePath + QLatin1Char('/') + filename);
100         if (file.exists()) {
101             if (file.open(QIODevice::ReadOnly)) {
102                 info.script = QString::fromUtf8(file.readAll());
103             }
104         }
105     }
106     return info;
107 }
108 
debug() const109 void TemplateInfo::debug() const
110 {
111     qCDebug(PIMCOMMON_LOG) << " name :" << name << " script :" << script;
112 }
113