Make the Grantlee::Node::render method const.
[grantlee:grantlee.git] / templates / defaulttags / ifchanged.cpp
1 /*
2   This file is part of the Grantlee 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 "ifchanged.h"
22
23 #include "parser.h"
24
25 #include <QtCore/QDateTime>
26
27
28 IfChangedNodeFactory::IfChangedNodeFactory()
29 {
30
31 }
32
33 Node* IfChangedNodeFactory::getNode( const QString &tagContent, Parser *p ) const
34 {
35   QStringList expr = tagContent.split( QLatin1Char( ' ' ), QString::SkipEmptyParts );
36
37   expr.takeAt( 0 );
38   IfChangedNode *n =  new IfChangedNode( getFilterExpressionList( expr, p ), p );
39
40   NodeList trueList = p->parse( n, QStringList() << QLatin1String( "else" ) << QLatin1String( "endifchanged" ) );
41   n->setTrueList( trueList );
42   NodeList falseList;
43
44   if ( p->takeNextToken().content.trimmed() == QLatin1String( "else" ) ) {
45     falseList = p->parse( n, QLatin1String( "endifchanged" ) );
46     n->setFalseList( falseList );
47     p->removeNextToken();
48   }
49
50   return n;
51 }
52
53 IfChangedNode::IfChangedNode( QList<FilterExpression> feList, QObject *parent )
54     : Node( parent ), m_filterExpressions( feList )
55 {
56   m_lastSeen = QVariant();
57   m_id = QString::number( reinterpret_cast<qint64>( this ) );
58 }
59
60 void IfChangedNode::setTrueList( NodeList trueList )
61 {
62   m_trueList = trueList;
63 }
64
65 void IfChangedNode::setFalseList( NodeList falseList )
66 {
67   m_falseList = falseList;
68 }
69
70 void IfChangedNode::render( OutputStream *stream, Context *c ) const
71 {
72   if ( c->lookup( QLatin1String( "forloop" ) ).isValid() && ( !c->lookup( QLatin1String( "forloop" ) ).toHash().contains( m_id ) ) ) {
73     m_lastSeen = QVariant();
74     QVariantHash hash = c->lookup( QLatin1String( "forloop" ) ).toHash();
75     hash.insert( m_id, 1 );
76     c->insert( QLatin1String( "forloop" ), hash );
77   }
78
79   QString watchedString;
80   QTextStream watchedTextStream( &watchedString );
81   QSharedPointer<OutputStream> watchedStream = stream->clone( &watchedTextStream );
82   if ( m_filterExpressions.size() == 0 ) {
83     m_trueList.render( watchedStream.data(), c );
84   }
85   QListIterator<FilterExpression> i( m_filterExpressions );
86   QVariantList watchedVars;
87   while ( i.hasNext() ) {
88     QVariant var = i.next().resolve( c );
89     if ( !var.isValid() ) {
90       // silent error
91       return;
92     }
93     watchedVars.append( var );
94   }
95
96   // At first glance it looks like m_last_seen will always be invalid,
97   // But it will change because render is called multiple times by the parent
98   // {% for %} loop in the template.
99   if (( watchedVars != m_lastSeen.toList() )
100       || ( !watchedString.isEmpty() && ( watchedString != m_lastSeen.toString() ) ) ) {
101     bool firstLoop = !m_lastSeen.isValid();
102     if ( !watchedString.isNull() )
103       m_lastSeen = watchedString;
104     else
105       m_lastSeen = watchedVars;
106     c->push();
107     QVariantHash hash;
108     // TODO: Document this.
109     hash.insert( QLatin1String( "firstloop" ), firstLoop );
110     c->insert( QLatin1String( "ifchanged" ), hash );
111     m_trueList.render( stream, c );
112     c->pop();
113   } else if ( !m_falseList.isEmpty() ) {
114     m_falseList.render( stream, c );
115   }
116 }
117