23 #include "../lib/exception.h" 24 #include "metaenumvariable_p.h" 27 #include <QSequentialIterable> 29 ForNodeFactory::ForNodeFactory() =
default;
35 if (expr.size() < 4) {
38 QStringLiteral(
"'for' statements should have at least four words: %1")
44 int reversed = ForNode::IsNotReversed;
45 if (expr.last() == QStringLiteral(
"reversed")) {
46 reversed = ForNode::IsReversed;
50 if (expr.at(expr.size() - 2) != QStringLiteral(
"in")) {
53 QStringLiteral(
"'for' statements should use the form 'for x in y': %1")
58 const auto parts = expr.
mid(0, expr.size() - 2);
59 for (
const QString &arg : parts) {
60 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 61 const auto args = arg.split(
QLatin1Char(
','), QString::SkipEmptyParts);
65 for (
const QString &var : args) {
69 QStringLiteral(
"'for' tag received invalid argument"));
79 auto n =
new ForNode(vars, fe, reversed, p);
82 = p->
parse(n, {QStringLiteral(
"empty"), QStringLiteral(
"endfor")});
83 n->setLoopList(loopNodes);
87 emptyNodes = p->
parse(n, QStringLiteral(
"endfor"));
88 n->setEmptyList(emptyNodes);
98 :
Node(parent), m_loopVars(loopVars), m_filterExpression(fe),
99 m_isReversed(reversed)
103 void ForNode::setLoopList(
const NodeList &loopNodeList)
105 m_loopNodeList = loopNodeList;
108 void ForNode::setEmptyList(
const NodeList &emptyList)
110 m_emptyNodeList = emptyList;
113 static const char forloop[] =
"forloop";
114 static const char parentloop[] =
"parentloop";
116 void ForNode::insertLoopVariables(
Context *c,
int listSize,
int i)
118 auto forloopHash = c->
lookup(QStringLiteral(
"forloop")).
value<QVariantHash>();
120 forloopHash.insert(QStringLiteral(
"counter0"), i);
121 forloopHash.insert(QStringLiteral(
"counter"), i + 1);
122 forloopHash.insert(QStringLiteral(
"revcounter"), listSize - i);
123 forloopHash.insert(QStringLiteral(
"revcounter0"), listSize - i - 1);
124 forloopHash.insert(QStringLiteral(
"first"), (i == 0));
125 forloopHash.insert(QStringLiteral(
"last"), (i == listSize - 1));
131 for (
auto j = 0; j < m_loopNodeList.
size(); j++) {
132 m_loopNodeList[j]->
render(stream, c);
138 QVariantHash forloopHash;
141 if (parentLoopVariant.isValid()) {
143 forloopHash = parentLoopVariant.
value<QVariantHash>();
145 parentLoopVariant.value<QVariantHash>());
149 auto unpack = m_loopVars.
size() > 1;
153 auto varFE = m_filterExpression.
resolve(c);
155 if (varFE.userType() == qMetaTypeId<MetaEnumVariable>()) {
156 const auto mev = varFE.
value<MetaEnumVariable>();
158 if (mev.value != -1) {
160 return m_emptyNodeList.
render(stream, c);
164 for (
auto row = 0; row < mev.enumerator.keyCount(); ++row) {
170 if (!varFE.canConvert<QVariantList>()) {
172 return m_emptyNodeList.
render(stream, c);
176 const auto listSize = iter.
size();
181 return m_emptyNodeList.
render(stream, c);
185 for (
auto it = m_isReversed == IsReversed ? iter.end() - 1 : iter.begin();
186 m_isReversed == IsReversed ? it != iter.begin() - 1 : it != iter.end();
187 m_isReversed == IsReversed ? --it : ++it) {
189 insertLoopVariables(c, listSize, i);
192 if (v.userType() == qMetaTypeId<QVariantList>()) {
193 auto vList = v.value<QVariantList>();
194 auto varsSize = qMin(m_loopVars.
size(), vList.size());
196 for (; j < varsSize; ++j) {
197 c->
insert(m_loopVars.
at(j), vList.at(j));
201 for (; j < m_loopVars.
size(); ++j) {
212 for (
const QString &loopVar : m_loopVars) {
214 c->
insert(QStringLiteral(
"var"), v);
222 c->
insert(m_loopVars[0], v);
224 renderLoop(stream, c);
NodeList parse(Node *parent, const QStringList &stopAt={})
The Context class holds the context to render a Template with.
Node * getNode(const QString &tagContent, Parser *p) const override
QList::const_reference at(qsizetype i) const const
void render(OutputStream *stream, Context *c) const override
qsizetype size() const const
qsizetype size() const const
QString content
The content of this Token.
Base class for all nodes.
The OutputStream class is used to render templates to a QTextStream.
QVariant fromValue(const T &value)
QVariant resolve(OutputStream *stream, Context *c) const
The Parser class processes a string template into a tree of nodes.
QList< T > mid(qsizetype pos, qsizetype length) const const
A list of Nodes with some convenience API for rendering them.
A FilterExpression object represents a filter expression in a template.
Q_INVOKABLE QStringList smartSplit(const QString &str) const
virtual QVariant lookup(const QString &str) const
void insert(const QString &name, QObject *object)
void render(OutputStream *stream, Context *c) const
An exception for use when implementing template tags.