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

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 "context.h"
0011 
0012 #include "nulllocalizer_p.h"
0013 #include "rendercontext.h"
0014 #include "util.h"
0015 
0016 #include <QStringList>
0017 
0018 using namespace KTextTemplate;
0019 
0020 namespace KTextTemplate
0021 {
0022 class ContextPrivate
0023 {
0024     ContextPrivate(Context *context, const QVariantHash &variantHash)
0025         : q_ptr(context)
0026         , m_renderContext(new RenderContext)
0027         , m_localizer(new NullLocalizer)
0028     {
0029         m_variantHashStack.append(variantHash);
0030     }
0031 
0032     ~ContextPrivate()
0033     {
0034         delete m_renderContext;
0035     }
0036 
0037     Q_DECLARE_PUBLIC(Context)
0038     Context *const q_ptr;
0039 
0040     QList<QVariantHash> m_variantHashStack;
0041     bool m_autoescape = true;
0042     bool m_mutating = false;
0043     QList<std::pair<QString, QString>> m_externalMedia;
0044     Context::UrlType m_urlType = Context::AbsoluteUrls;
0045     QString m_relativeMediaPath;
0046     RenderContext *const m_renderContext;
0047     QSharedPointer<AbstractLocalizer> m_localizer;
0048 };
0049 }
0050 
0051 Context::Context()
0052     : d_ptr(new ContextPrivate(this, QVariantHash()))
0053 {
0054 }
0055 
0056 Context::Context(const QVariantHash &variantHash)
0057     : d_ptr(new ContextPrivate(this, variantHash))
0058 {
0059 }
0060 
0061 Context::Context(const Context &other)
0062     : d_ptr(new ContextPrivate(this, QVariantHash()))
0063 {
0064     *this = other;
0065 }
0066 
0067 Context &Context::operator=(const Context &other)
0068 {
0069     if (&other == this)
0070         return *this;
0071     d_ptr->m_autoescape = other.d_ptr->m_autoescape;
0072     d_ptr->m_externalMedia = other.d_ptr->m_externalMedia;
0073     d_ptr->m_mutating = other.d_ptr->m_mutating;
0074     d_ptr->m_variantHashStack = other.d_ptr->m_variantHashStack;
0075     d_ptr->m_urlType = other.d_ptr->m_urlType;
0076     d_ptr->m_relativeMediaPath = other.d_ptr->m_relativeMediaPath;
0077     return *this;
0078 }
0079 
0080 Context::~Context()
0081 {
0082     delete d_ptr;
0083 }
0084 
0085 bool Context::autoEscape() const
0086 {
0087     Q_D(const Context);
0088     return d->m_autoescape;
0089 }
0090 
0091 void Context::setAutoEscape(bool autoescape)
0092 {
0093     Q_D(Context);
0094     d->m_autoescape = autoescape;
0095 }
0096 
0097 QVariant Context::lookup(const QString &str) const
0098 {
0099     Q_D(const Context);
0100 
0101     // return a variant from the stack.
0102     for (const auto &h : d->m_variantHashStack) {
0103         auto it = h.constFind(str);
0104         if (it != h.constEnd()) {
0105             auto var = it.value();
0106             // If the user passed a string into the context, turn it into a
0107             // KTextTemplate::SafeString.
0108             if (var.userType() == qMetaTypeId<QString>()) {
0109                 var = QVariant::fromValue<KTextTemplate::SafeString>(getSafeString(var.value<QString>()));
0110             }
0111             return var;
0112         }
0113     }
0114 
0115     return {};
0116 }
0117 
0118 void Context::push()
0119 {
0120     Q_D(Context);
0121 
0122     const QHash<QString, QVariant> hash;
0123     d->m_variantHashStack.prepend(hash);
0124 }
0125 
0126 void Context::pop()
0127 {
0128     Q_D(Context);
0129 
0130     d->m_variantHashStack.removeFirst();
0131 }
0132 
0133 void Context::insert(const QString &name, const QVariant &variant)
0134 {
0135     Q_D(Context);
0136 
0137     d->m_variantHashStack[0].insert(name, variant);
0138 }
0139 
0140 void Context::insert(const QString &name, QObject *object)
0141 {
0142     Q_D(Context);
0143 
0144     d->m_variantHashStack[0].insert(name, QVariant::fromValue(object));
0145 }
0146 
0147 QHash<QString, QVariant> Context::stackHash(int depth) const
0148 {
0149     Q_D(const Context);
0150 
0151     return d->m_variantHashStack.value(depth);
0152 }
0153 
0154 bool Context::isMutating() const
0155 {
0156     Q_D(const Context);
0157     return d->m_mutating;
0158 }
0159 
0160 void Context::setMutating(bool mutating)
0161 {
0162     Q_D(Context);
0163     d->m_mutating = mutating;
0164 }
0165 
0166 void Context::addExternalMedia(const QString &absolutePart, const QString &relativePart)
0167 {
0168     Q_D(Context);
0169     d->m_externalMedia.append(std::make_pair(absolutePart, relativePart));
0170 }
0171 
0172 QList<std::pair<QString, QString>> Context::externalMedia() const
0173 {
0174     Q_D(const Context);
0175     return d->m_externalMedia;
0176 }
0177 
0178 void Context::clearExternalMedia()
0179 {
0180     Q_D(Context);
0181     d->m_externalMedia.clear();
0182 }
0183 
0184 void Context::setUrlType(Context::UrlType type)
0185 {
0186     Q_D(Context);
0187     d->m_urlType = type;
0188 }
0189 
0190 Context::UrlType Context::urlType() const
0191 {
0192     Q_D(const Context);
0193     return d->m_urlType;
0194 }
0195 
0196 void Context::setRelativeMediaPath(const QString &path)
0197 {
0198     Q_D(Context);
0199     d->m_relativeMediaPath = path;
0200 }
0201 
0202 QString Context::relativeMediaPath() const
0203 {
0204     Q_D(const Context);
0205     return d->m_relativeMediaPath;
0206 }
0207 
0208 RenderContext *Context::renderContext() const
0209 {
0210     Q_D(const Context);
0211     return d->m_renderContext;
0212 }
0213 
0214 void Context::setLocalizer(QSharedPointer<AbstractLocalizer> localizer)
0215 {
0216     Q_D(Context);
0217     if (!localizer) {
0218         d->m_localizer = QSharedPointer<AbstractLocalizer>(new NullLocalizer);
0219         return;
0220     }
0221     d->m_localizer = localizer;
0222 }
0223 
0224 QSharedPointer<AbstractLocalizer> Context::localizer() const
0225 {
0226     Q_D(const Context);
0227     return d->m_localizer;
0228 }