1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
/*
This file is part of the Grantlee template system.
Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version
2 of the Licence, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "regroup.h"
#include <QtCore/QStringList>
#include "parser.h"
#include "exception.h"
#include "util.h"
RegroupNodeFactory::RegroupNodeFactory()
{
}
Node* RegroupNodeFactory::getNode( const QString &tagContent, Parser *p ) const
{
QStringList expr = tagContent.split( QLatin1Char( ' ' ) );
if ( expr.size() != 6 ) {
throw Grantlee::Exception( TagSyntaxError, QLatin1String( "widthratio takes five arguments" ) );
}
FilterExpression target( expr.at( 1 ), p );
if ( expr.at( 2 ) != QLatin1String( "by" ) ) {
throw Grantlee::Exception( TagSyntaxError, QLatin1String( "second argument must be 'by'" ) );
}
if ( expr.at( 4 ) != QLatin1String( "as" ) ) {
throw Grantlee::Exception( TagSyntaxError, QLatin1String( "fourth argument must be 'as'" ) );
}
FilterExpression expression( QLatin1String( "\"" ) + expr.at( 3 ) + QLatin1String( "\"" ), p );
QString name = expr.at( 5 );
return new RegroupNode( target, expression, name, p );
}
RegroupNode::RegroupNode( FilterExpression target, FilterExpression expression, const QString &varName, QObject *parent )
: Node( parent ), m_target( target ), m_expression( expression ), m_varName( varName )
{
}
void RegroupNode::render( OutputStream *stream, Context *c )
{
Q_UNUSED( stream )
QVariantList objList = m_target.resolve( c ).toList();
if ( objList.isEmpty() ) {
c->insert( m_varName, QVariantHash() );
return;
}
// What's going on?
//
// objList is a flat list of objects with a common parameter. For example, Person objects with
// a name parameter. The list is already sorted.
// Say the objList contains ["David Beckham", "David Blain", "Keira Nightly"] etc.
// We want to regroup the list into separate lists of people with the same first name.
// ie objHash should be: {"David": ["David Beckham", "David Blain"], "Keira": ["Keira Nightly"]}
//
// We then insert the objHash into the Context ready for rendering later in a for loop.
QVariantList list;
QVariantHash objHash;
QVariantList contextList;
QString hashKey;
QString lastKey;
QString keyName = getSafeString( m_expression.resolve( c ) );
QListIterator<QVariant> i( objList );
while ( i.hasNext() ) {
QVariant var = i.next();
c->push();
c->insert( QLatin1String( "var" ), var );
QString key = getSafeString( FilterExpression( QLatin1String( "var." ) + keyName, 0 ).resolve( c ) );
c->pop();
QVariantHash hash;
if ( contextList.size() > 0 ) {
QVariant hashVar = contextList.last();
hash = hashVar.toHash();
}
if ( !hash.contains( QLatin1String( "grouper" ) ) || hash.value( QLatin1String( "grouper" ) ) != key ) {
QVariantHash newHash;
hash.insert( QLatin1String( "grouper" ), key );
hash.insert( QLatin1String( "list" ), QVariantList() );
contextList.append( newHash );
}
QVariantList list = hash.value( QLatin1String( "list" ) ).toList();
list.append( var );
hash.insert( QLatin1String( "list" ), list );
contextList[contextList.size() - 1] = hash;
}
c->insert( m_varName, contextList );
}
|