Cutelee 6.1.0
cycle.cpp
1/*
2 This file is part of the Cutelee template system.
3
4 Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either version
9 2.1 of the Licence, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#include "cycle.h"
22
23#include "../lib/exception.h"
24#include "parser.h"
25#include "rendercontext.h"
26#include "util.h"
27
28static const char _namedCycleNodes[] = "_namedCycleNodes";
29
30CycleNodeFactory::CycleNodeFactory() {}
31
32Node *CycleNodeFactory::getNode(const QString &tagContent, Parser *p) const
33{
34 auto expr = smartSplit(tagContent);
35
36 if (expr.size() < 2) {
38 TagSyntaxError,
39 QStringLiteral("%1 expects at least one argument").arg(expr.first()));
40 }
41
42 if (expr.at(1).contains(QLatin1Char(','))) {
43 auto csvlist = expr.at(1).split(QLatin1Char(','));
44 expr.removeAt(1);
45 for (auto i = 0; i < csvlist.size(); ++i) {
46 expr.insert(i + 1, QChar::fromLatin1('"') + csvlist.at(i)
47 + QChar::fromLatin1('"'));
48 }
49 }
50
51 if (expr.size() == 2) {
52 // {% cycle var %}
53 auto name = expr.at(1);
54 auto cycleNodes = p->property(_namedCycleNodes);
55 if (cycleNodes.userType() != qMetaTypeId<QVariantHash>()) {
57 TagSyntaxError,
58 QStringLiteral("No named cycles in template. '%1' is not defined")
59 .arg(name));
60 }
61 auto hash = cycleNodes.value<QVariantHash>();
62 if (!hash.contains(name)) {
63 throw Cutelee::Exception(TagSyntaxError,
64 QStringLiteral("Node not found: %1").arg(name));
65 }
66 auto nodeVariant = hash.value(name);
67 Q_ASSERT(nodeVariant.canConvert<Node *>());
68 return nodeVariant.value<Node *>();
69 }
70
71 auto exprSize = expr.size();
72 if (exprSize > 4 && expr.at(exprSize - 2) == QStringLiteral("as")) {
73 // {% cycle "foo" "bar" "bat" as var %}
74 auto name = expr.at(exprSize - 1);
75 auto list = expr.mid(1, exprSize - 3);
76 auto node = new CycleNode(getFilterExpressionList(list, p), name, p);
77 auto hashVariant = p->property(_namedCycleNodes);
78 QVariantHash hash;
79 if (hashVariant.userType() == qMetaTypeId<QVariantHash>()) {
80 hash = hashVariant.value<QVariantHash>();
81 }
82 hash.insert(name, QVariant::fromValue(node));
83 p->setProperty(_namedCycleNodes, QVariant(hash));
84 return node;
85 } else {
86 auto list = expr.mid(1, exprSize - 1);
87 return new CycleNode(getFilterExpressionList(list, p), QString(), p);
88 }
89}
90
91CycleNode::CycleNode(const QList<FilterExpression> &list, const QString &name,
92 QObject *parent)
93 : Node(parent), m_list(list), m_variableIterator(list), m_name(name)
94{
95}
96
97void CycleNode::render(OutputStream *stream, Context *c) const
98{
99 QVariant &variant = c->renderContext()->data(this);
100
102
103 if (variant.isValid())
104 rotator = variant.value<FilterExpressionRotator>();
105 else
106 rotator = FilterExpressionRotator(m_list);
107
108 QString value;
109 QTextStream textStream(&value);
110 auto temp = stream->clone(&textStream);
111
112 rotator.next().resolve(temp.get(), c).toString();
113
114 variant.setValue(rotator);
115
116 if (!m_name.isEmpty()) {
117 c->insert(m_name, value);
118 }
119 (*stream) << value;
120}
QList< FilterExpression > getFilterExpressionList(const QStringList &list, Parser *p) const
Definition node.cpp:192
Q_INVOKABLE QStringList smartSplit(const QString &str) const
Definition node.cpp:202
The Context class holds the context to render a Template with.
Definition context.h:119
RenderContext * renderContext() const
Definition context.cpp:214
void insert(const QString &name, QObject *object)
Definition context.cpp:145
An exception for use when implementing template tags.
Definition exception.h:85
QVariant resolve(OutputStream *stream, Context *c) const
Base class for all nodes.
Definition node.h:78
The OutputStream class is used to render templates to a QTextStream.
virtual std::shared_ptr< OutputStream > clone(QTextStream *stream) const
The Parser class processes a string template into a tree of nodes.
Definition parser.h:49
QVariant & data(const Node *const scopeNode)
Node * getNode(const QString &tagContent, Parser *p) const override
Definition cycle.cpp:32
void render(OutputStream *stream, Context *c) const override
Definition cycle.cpp:97
T next()
Definition cycle.h:56
Utility functions used throughout Cutelee.