We now have a current svn snapshot of libqxt in our contrib dir, and
[quassel.git] / src / contrib / libqxt-2007-10-24 / src / web / qxthtmltemplate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtWeb  module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 **
21 ** <http://libqxt.org>  <foundation@libqxt.org>
22 **
23 ****************************************************************************/
24
25 /*!
26         \class QxtHtmlTemplate QxtHtmlTemplate
27         \ingroup QxtWeb
28         \brief Basic Html Template Engine
29
30         open a file containing html code and php style variables.
31         use the square bracket operators to assign content for a variable
32
33         \code
34         QxtHtmlTemplate index;
35         if(!index.open)
36                 return 404;
37         index["content"]="hello world";
38         echo()<<index.render();
39         \endcode
40         the realatet html code would look like:
41         \code
42         <html>
43         <head>
44                 <title>Test Page</title>
45         </head>
46                 <?=content?>
47         </html>
48         \endcode
49
50         funny storry: whe are using this class to make our documentation (eat your own dogfood, you know ;).  
51         but when we where parsing exactly this file you read right now the first time, QxtHtmlTemplate got stuck in an infinite loop. guess why. becouse of that example above :D
52         So be warned: when you assign content to a variable that contains the variable name itself, render() will never return.
53                   
54
55 */
56
57 /*!
58         \fn QxtHtmlTemplate::open(const QString& filename)
59         Returns true on sucess and false on failure.
60         note that it will also return false for an empty html file.
61
62         \fn QString QxtHtmlTemplate::render() const
63         Uses the variables you set and renders the opened file.
64         returns an empty string on failure.
65         Does NOT take care of not assigned variables, they will remain in the returned string
66  */
67
68 #include "qxthtmltemplate.h"
69 #include <QFile>
70 #include <QStringList>
71
72 QxtHtmlTemplate::QxtHtmlTemplate() : QMap<QString,QString>()
73 {}
74
75 void QxtHtmlTemplate::load(const QString& d)
76 {
77     data=d;
78 }
79
80 bool QxtHtmlTemplate::open(const QString& filename)
81 {
82     QFile f(filename);
83     f.open(QIODevice::ReadOnly);
84     data = QString::fromLocal8Bit(f.readAll());
85     f.close();
86     if (data.isEmpty())
87         {
88         qWarning("QxtHtmlTemplate::open(\"%s\") empty or non existant",qPrintable(filename));
89         return false;
90         }
91     return true;
92 }
93
94 QString QxtHtmlTemplate::render() const
95 {
96     ///try to preserve indention by parsing char by char and saving the last non-space character
97
98
99     QString output = data;
100     int lastnewline=0;
101
102
103     for (int i=0;i<output.count();i++)
104     {
105         if (output.at(i)=='\n')
106         {
107             lastnewline=i;
108         }
109
110         if (output.at(i)=='<' && output.at(i+1)=='?'  && output.at(i+2)=='=')
111         {
112             int j=i+3;
113             QString var;
114
115             for (int jj=j;jj<output.count();jj++)
116             {
117                 if (output.at(jj)=='?' && output.at(jj+1)=='>')
118                 {
119                     j=jj;
120                     break;
121                 }
122                 var+=output.at(jj);
123             }
124
125
126             if (j==i)
127             {
128                 qWarning("QxtHtmlTemplate::render()  unterminated <?= ");
129                 continue;
130             }
131
132
133             if(!contains(var))
134             {
135                 qWarning("QxtHtmlTemplate::render()  unused variable \"%s\"",qPrintable(var));
136                 continue;
137             }
138             output.replace(i,j-i+2,QString(value(var)).replace("\n","\n"+QString(i-lastnewline-1,QChar(' '))));
139
140         }
141
142
143     }
144
145     return output;
146 }
147