File indexing completed on 2025-02-09 04:28:40

0001 /*
0002   This file is part of the KTextTemplate library
0003 
0004   SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
0005 
0006   SPDX-License-Identifier: LGPL-2.1-or-later
0007 
0008 */
0009 
0010 #include "templateloader.h"
0011 
0012 #include "engine.h"
0013 #include "exception.h"
0014 #include "nulllocalizer_p.h"
0015 
0016 #include <QDir>
0017 #include <QFile>
0018 #include <QFileInfo>
0019 
0020 using namespace KTextTemplate;
0021 
0022 AbstractTemplateLoader::~AbstractTemplateLoader() = default;
0023 
0024 namespace KTextTemplate
0025 {
0026 class FileSystemTemplateLoaderPrivate
0027 {
0028     FileSystemTemplateLoaderPrivate(FileSystemTemplateLoader *loader, QSharedPointer<AbstractLocalizer> localizer)
0029         : q_ptr(loader)
0030         , m_localizer(localizer ? localizer : QSharedPointer<AbstractLocalizer>(new NullLocalizer))
0031     {
0032     }
0033     Q_DECLARE_PUBLIC(FileSystemTemplateLoader)
0034     FileSystemTemplateLoader *const q_ptr;
0035 
0036     QString m_themeName;
0037     QStringList m_templateDirs;
0038     const QSharedPointer<AbstractLocalizer> m_localizer;
0039 };
0040 }
0041 
0042 FileSystemTemplateLoader::FileSystemTemplateLoader(const QSharedPointer<AbstractLocalizer> localizer)
0043     : AbstractTemplateLoader()
0044     , d_ptr(new FileSystemTemplateLoaderPrivate(this, localizer))
0045 {
0046 }
0047 
0048 FileSystemTemplateLoader::~FileSystemTemplateLoader()
0049 {
0050     for (const QString &dir : templateDirs())
0051         d_ptr->m_localizer->unloadCatalog(dir + QLatin1Char('/') + themeName());
0052     delete d_ptr;
0053 }
0054 
0055 InMemoryTemplateLoader::InMemoryTemplateLoader()
0056     : AbstractTemplateLoader()
0057 {
0058 }
0059 
0060 InMemoryTemplateLoader::~InMemoryTemplateLoader() = default;
0061 
0062 void FileSystemTemplateLoader::setTheme(const QString &themeName)
0063 {
0064     Q_D(FileSystemTemplateLoader);
0065     for (const QString &dir : templateDirs())
0066         d->m_localizer->unloadCatalog(dir + QLatin1Char('/') + d->m_themeName);
0067     d->m_themeName = themeName;
0068     for (const QString &dir : templateDirs())
0069         d->m_localizer->loadCatalog(dir + QLatin1Char('/') + themeName, themeName);
0070 }
0071 
0072 QString FileSystemTemplateLoader::themeName() const
0073 {
0074     Q_D(const FileSystemTemplateLoader);
0075     return d->m_themeName;
0076 }
0077 
0078 void FileSystemTemplateLoader::setTemplateDirs(const QStringList &dirs)
0079 {
0080     Q_D(FileSystemTemplateLoader);
0081 
0082     for (const QString &dir : templateDirs())
0083         d->m_localizer->unloadCatalog(dir + QLatin1Char('/') + d->m_themeName);
0084     d->m_templateDirs = dirs;
0085     for (const QString &dir : templateDirs())
0086         d->m_localizer->loadCatalog(dir + QLatin1Char('/') + d->m_themeName, d->m_themeName);
0087 }
0088 
0089 QStringList FileSystemTemplateLoader::templateDirs() const
0090 {
0091     Q_D(const FileSystemTemplateLoader);
0092     return d->m_templateDirs;
0093 }
0094 
0095 bool FileSystemTemplateLoader::canLoadTemplate(const QString &name) const
0096 {
0097     Q_D(const FileSystemTemplateLoader);
0098     auto i = 0;
0099     QFile file;
0100 
0101     while (!file.exists()) {
0102         if (i >= d->m_templateDirs.size())
0103             break;
0104 
0105         file.setFileName(d->m_templateDirs.at(i) + QLatin1Char('/') + d->m_themeName + QLatin1Char('/') + name);
0106         ++i;
0107     }
0108 
0109     if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0110         return false;
0111     }
0112     file.close();
0113     return true;
0114 }
0115 
0116 Template FileSystemTemplateLoader::loadByName(const QString &fileName, Engine const *engine) const
0117 {
0118     Q_D(const FileSystemTemplateLoader);
0119     auto i = 0;
0120     QFile file;
0121 
0122     while (!file.exists()) {
0123         if (i >= d->m_templateDirs.size())
0124             break;
0125 
0126         file.setFileName(d->m_templateDirs.at(i) + QLatin1Char('/') + d->m_themeName + QLatin1Char('/') + fileName);
0127         const QFileInfo fi(file);
0128 
0129         if (file.exists() && !fi.canonicalFilePath().contains(QDir(d->m_templateDirs.at(i)).canonicalPath()))
0130             return {};
0131         ++i;
0132     }
0133 
0134     if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0135         return {};
0136     }
0137 
0138     QTextStream fstream(&file);
0139     fstream.setEncoding(QStringConverter::Utf8);
0140     const auto fileContent = fstream.readAll();
0141 
0142     return engine->newTemplate(fileContent, fileName);
0143 }
0144 
0145 std::pair<QString, QString> FileSystemTemplateLoader::getMediaUri(const QString &fileName) const
0146 {
0147     Q_D(const FileSystemTemplateLoader);
0148     auto i = 0;
0149     QFile file;
0150     while (!file.exists()) {
0151         if (i >= d->m_templateDirs.size())
0152             break;
0153 
0154         file.setFileName(d->m_templateDirs.at(i) + QLatin1Char('/') + d->m_themeName + QLatin1Char('/') + fileName);
0155 
0156         const QFileInfo fi(file);
0157         if (!fi.canonicalFilePath().contains(QDir(d->m_templateDirs.at(i)).canonicalPath())) {
0158             ++i;
0159             continue;
0160         }
0161 
0162         if (file.exists()) {
0163             auto path = fi.absoluteFilePath();
0164             path.chop(fileName.size());
0165             return std::make_pair(path, fileName);
0166         }
0167         ++i;
0168     }
0169     return {};
0170 }
0171 
0172 void InMemoryTemplateLoader::setTemplate(const QString &name, const QString &content)
0173 {
0174     m_namedTemplates.insert(name, content);
0175 }
0176 
0177 bool InMemoryTemplateLoader::canLoadTemplate(const QString &name) const
0178 {
0179     return m_namedTemplates.contains(name);
0180 }
0181 
0182 Template InMemoryTemplateLoader::loadByName(const QString &name, Engine const *engine) const
0183 {
0184     const auto it = m_namedTemplates.constFind(name);
0185     if (it != m_namedTemplates.constEnd()) {
0186         return engine->newTemplate(it.value(), name);
0187     }
0188     throw KTextTemplate::Exception(TagSyntaxError, QStringLiteral("Couldn't load template %1. Template does not exist.").arg(name));
0189 }
0190 
0191 std::pair<QString, QString> InMemoryTemplateLoader::getMediaUri(const QString &fileName) const
0192 {
0193     Q_UNUSED(fileName)
0194     // This loader doesn't make any media available yet.
0195     return {};
0196 }