Updated templateengine base code to 1.6.5

This commit is contained in:
Luis Ángel San Martín 2016-06-17 19:56:55 +02:00
parent 5ae7e9fd3f
commit 3675aebdc5
7 changed files with 142 additions and 67 deletions

View File

@ -7,131 +7,174 @@
#include <QFileInfo> #include <QFileInfo>
Template::Template(QString source, QString sourceName) Template::Template(QString source, QString sourceName)
: QString(source) { : QString(source)
{
this->sourceName=sourceName; this->sourceName=sourceName;
this->warnings=false; this->warnings=false;
} }
Template::Template(QFile& file, QTextCodec* textCodec) { Template::Template(QFile& file, QTextCodec* textCodec)
{
this->warnings=false; this->warnings=false;
sourceName=QFileInfo(file.fileName()).baseName(); sourceName=QFileInfo(file.fileName()).baseName();
if (!file.isOpen()) { if (!file.isOpen())
{
file.open(QFile::ReadOnly | QFile::Text); file.open(QFile::ReadOnly | QFile::Text);
} }
QByteArray data=file.readAll(); QByteArray data=file.readAll();
file.close(); file.close();
if (data.size()==0 || file.error()) { if (data.size()==0 || file.error())
{
qCritical("Template: cannot read from %s, %s",qPrintable(sourceName),qPrintable(file.errorString())); qCritical("Template: cannot read from %s, %s",qPrintable(sourceName),qPrintable(file.errorString()));
}
else
{
append(textCodec->toUnicode(data)); append(textCodec->toUnicode(data));
} }
} }
int Template::setVariable(QString name, QString value) { int Template::setVariable(QString name, QString value)
{
int count=0; int count=0;
QString variable="{"+name+"}"; QString variable="{"+name+"}";
int start=indexOf(variable); int start=indexOf(variable);
while (start>=0) { while (start>=0)
{
replace(start, variable.length(), value); replace(start, variable.length(), value);
count++; count++;
start=indexOf(variable,start+value.length()); start=indexOf(variable,start+value.length());
} }
if (count==0 && warnings) { if (count==0 && warnings)
{
qWarning("Template: missing variable %s in %s",qPrintable(variable),qPrintable(sourceName)); qWarning("Template: missing variable %s in %s",qPrintable(variable),qPrintable(sourceName));
} }
return count; return count;
} }
int Template::setCondition(QString name, bool value) { int Template::setCondition(QString name, bool value)
{
int count=0; int count=0;
QString startTag=QString("{if %1}").arg(name); QString startTag=QString("{if %1}").arg(name);
QString elseTag=QString("{else %1}").arg(name); QString elseTag=QString("{else %1}").arg(name);
QString endTag=QString("{end %1}").arg(name); QString endTag=QString("{end %1}").arg(name);
// search for if-else-end // search for if-else-end
int start=indexOf(startTag); int start=indexOf(startTag);
while (start>=0) { while (start>=0)
{
int end=indexOf(endTag,start+startTag.length()); int end=indexOf(endTag,start+startTag.length());
if (end>=0) { if (end>=0)
{
count++; count++;
int ellse=indexOf(elseTag,start+startTag.length()); int ellse=indexOf(elseTag,start+startTag.length());
if (ellse>start && ellse<end) { // there is an else part if (ellse>start && ellse<end)
if (value==true) { {
// there is an else part
if (value==true)
{
QString truePart=mid(start+startTag.length(), ellse-start-startTag.length()); QString truePart=mid(start+startTag.length(), ellse-start-startTag.length());
replace(start, end-start+endTag.length(), truePart); replace(start, end-start+endTag.length(), truePart);
} }
else { // value==false else
{
// value==false
QString falsePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length()); QString falsePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length());
replace(start, end-start+endTag.length(), falsePart); replace(start, end-start+endTag.length(), falsePart);
} }
} }
else if (value==true) { // and no else part else if (value==true)
{
// and no else part
QString truePart=mid(start+startTag.length(), end-start-startTag.length()); QString truePart=mid(start+startTag.length(), end-start-startTag.length());
replace(start, end-start+endTag.length(), truePart); replace(start, end-start+endTag.length(), truePart);
} }
else { // value==false and no else part else
{
// value==false and no else part
replace(start, end-start+endTag.length(), ""); replace(start, end-start+endTag.length(), "");
} }
start=indexOf(startTag,start); start=indexOf(startTag,start);
} }
else { else
{
qWarning("Template: missing condition end %s in %s",qPrintable(endTag),qPrintable(sourceName)); qWarning("Template: missing condition end %s in %s",qPrintable(endTag),qPrintable(sourceName));
} }
} }
// search for ifnot-else-end // search for ifnot-else-end
QString startTag2="{ifnot "+name+"}"; QString startTag2="{ifnot "+name+"}";
start=indexOf(startTag2); start=indexOf(startTag2);
while (start>=0) { while (start>=0)
{
int end=indexOf(endTag,start+startTag2.length()); int end=indexOf(endTag,start+startTag2.length());
if (end>=0) { if (end>=0)
{
count++; count++;
int ellse=indexOf(elseTag,start+startTag2.length()); int ellse=indexOf(elseTag,start+startTag2.length());
if (ellse>start && ellse<end) { // there is an else part if (ellse>start && ellse<end)
if (value==false) { {
// there is an else part
if (value==false)
{
QString falsePart=mid(start+startTag2.length(), ellse-start-startTag2.length()); QString falsePart=mid(start+startTag2.length(), ellse-start-startTag2.length());
replace(start, end-start+endTag.length(), falsePart); replace(start, end-start+endTag.length(), falsePart);
} }
else { // value==true else
{
// value==true
QString truePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length()); QString truePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length());
replace(start, end-start+endTag.length(), truePart); replace(start, end-start+endTag.length(), truePart);
} }
} }
else if (value==false) { // and no else part else if (value==false)
{
// and no else part
QString falsePart=mid(start+startTag2.length(), end-start-startTag2.length()); QString falsePart=mid(start+startTag2.length(), end-start-startTag2.length());
replace(start, end-start+endTag.length(), falsePart); replace(start, end-start+endTag.length(), falsePart);
} }
else { // value==true and no else part else
{
// value==true and no else part
replace(start, end-start+endTag.length(), ""); replace(start, end-start+endTag.length(), "");
} }
start=indexOf(startTag2,start); start=indexOf(startTag2,start);
} }
else { else
{
qWarning("Template: missing condition end %s in %s",qPrintable(endTag),qPrintable(sourceName)); qWarning("Template: missing condition end %s in %s",qPrintable(endTag),qPrintable(sourceName));
} }
} }
if (count==0 && warnings) { if (count==0 && warnings)
{
qWarning("Template: missing condition %s or %s in %s",qPrintable(startTag),qPrintable(startTag2),qPrintable(sourceName)); qWarning("Template: missing condition %s or %s in %s",qPrintable(startTag),qPrintable(startTag2),qPrintable(sourceName));
} }
return count; return count;
} }
int Template::loop(QString name, int repetitions) { int Template::loop(QString name, int repetitions)
//Q_ASSERT(repetitions>=0); {
Q_ASSERT(repetitions>=0);
int count=0; int count=0;
QString startTag="{loop "+name+"}"; QString startTag="{loop "+name+"}";
QString elseTag="{else "+name+"}"; QString elseTag="{else "+name+"}";
QString endTag="{end "+name+"}"; QString endTag="{end "+name+"}";
// search for loop-else-end // search for loop-else-end
int start=indexOf(startTag); int start=indexOf(startTag);
while (start>=0) { while (start>=0)
{
int end=indexOf(endTag,start+startTag.length()); int end=indexOf(endTag,start+startTag.length());
if (end>=0) { if (end>=0)
{
count++; count++;
int ellse=indexOf(elseTag,start+startTag.length()); int ellse=indexOf(elseTag,start+startTag.length());
if (ellse>start && ellse<end) { // there is an else part if (ellse>start && ellse<end)
if (repetitions>0) { {
// there is an else part
if (repetitions>0)
{
QString loopPart=mid(start+startTag.length(), ellse-start-startTag.length()); QString loopPart=mid(start+startTag.length(), ellse-start-startTag.length());
QString insertMe; QString insertMe;
for (int i=0; i<repetitions; ++i) { for (int i=0; i<repetitions; ++i)
{
// number variables, conditions and sub-loop within the loop // number variables, conditions and sub-loop within the loop
QString nameNum=name+QString::number(i); QString nameNum=name+QString::number(i);
QString s=loopPart; QString s=loopPart;
@ -145,15 +188,20 @@ int Template::loop(QString name, int repetitions) {
} }
replace(start, end-start+endTag.length(), insertMe); replace(start, end-start+endTag.length(), insertMe);
} }
else { // repetitions==0 else
{
// repetitions==0
QString elsePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length()); QString elsePart=mid(ellse+elseTag.length(), end-ellse-elseTag.length());
replace(start, end-start+endTag.length(), elsePart); replace(start, end-start+endTag.length(), elsePart);
} }
} }
else if (repetitions>0) { // and no else part else if (repetitions>0)
{
// and no else part
QString loopPart=mid(start+startTag.length(), end-start-startTag.length()); QString loopPart=mid(start+startTag.length(), end-start-startTag.length());
QString insertMe; QString insertMe;
for (int i=0; i<repetitions; ++i) { for (int i=0; i<repetitions; ++i)
{
// number variables, conditions and sub-loop within the loop // number variables, conditions and sub-loop within the loop
QString nameNum=name+QString::number(i); QString nameNum=name+QString::number(i);
QString s=loopPart; QString s=loopPart;
@ -167,22 +215,27 @@ int Template::loop(QString name, int repetitions) {
} }
replace(start, end-start+endTag.length(), insertMe); replace(start, end-start+endTag.length(), insertMe);
} }
else { // repetitions==0 and no else part else
{
// repetitions==0 and no else part
replace(start, end-start+endTag.length(), ""); replace(start, end-start+endTag.length(), "");
} }
start=indexOf(startTag,start); start=indexOf(startTag,start);
} }
else { else
{
qWarning("Template: missing loop end %s in %s",qPrintable(endTag),qPrintable(sourceName)); qWarning("Template: missing loop end %s in %s",qPrintable(endTag),qPrintable(sourceName));
} }
} }
if (count==0 && warnings) { if (count==0 && warnings)
{
qWarning("Template: missing loop %s in %s",qPrintable(startTag),qPrintable(sourceName)); qWarning("Template: missing loop %s in %s",qPrintable(startTag),qPrintable(sourceName));
} }
return count; return count;
} }
void Template::enableWarnings(bool enable) { void Template::enableWarnings(bool enable)
{
warnings=enable; warnings=enable;
} }

View File

@ -12,6 +12,7 @@
#include <QTextCodec> #include <QTextCodec>
#include <QFile> #include <QFile>
#include <QString> #include <QString>
#include "templateglobal.h"
/** /**
Enhanced version of QString for template processing. Templates Enhanced version of QString for template processing. Templates
@ -37,7 +38,7 @@
Example code to fill this template: Example code to fill this template:
<p><code><pre> <p><code><pre>
Template t(QFile("test.tpl"),QTextCode::codecForName("UTF-8")); Template t(QFile("test.tpl"),QTextCode::codecForName("UTF-8"));
t.setVariable("user", "Stefan"); t.setVariable("username", "Stefan");
t.setCondition("locked",false); t.setCondition("locked",false);
t.loop("user",2); t.loop("user",2);
t.setVariable("user0.name,"Markus"); t.setVariable("user0.name,"Markus");
@ -86,7 +87,7 @@
@see TemplateCache @see TemplateCache
*/ */
class Template : public QString { class DECLSPEC Template : public QString {
public: public:
/** /**

View File

@ -11,12 +11,14 @@ TemplateCache::TemplateCache(QSettings* settings, QObject* parent)
qDebug("TemplateCache: timeout=%i, size=%i",cacheTimeout,cache.maxCost()); qDebug("TemplateCache: timeout=%i, size=%i",cacheTimeout,cache.maxCost());
} }
QString TemplateCache::tryFile(QString localizedName) { QString TemplateCache::tryFile(QString localizedName)
{
qint64 now=QDateTime::currentMSecsSinceEpoch(); qint64 now=QDateTime::currentMSecsSinceEpoch();
// search in cache // search in cache
qDebug("TemplateCache: trying cached %s",qPrintable(localizedName)); qDebug("TemplateCache: trying cached %s",qPrintable(localizedName));
CacheEntry* entry=cache.object(localizedName); CacheEntry* entry=cache.object(localizedName);
if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) { if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout))
{
return entry->document; return entry->document;
} }
// search on filesystem // search on filesystem

View File

@ -1,8 +1,9 @@
#ifndef TEMPLATECACHE_H #ifndef TEMPLATECACHE_H
#define TEMPLATECACHE_H #define TEMPLATECACHE_H
#include "templateloader.h"
#include <QCache> #include <QCache>
#include "templateglobal.h"
#include "templateloader.h"
/** /**
Caching template loader, reduces the amount of I/O and improves performance Caching template loader, reduces the amount of I/O and improves performance
@ -25,7 +26,7 @@
<p> <p>
The following settings are required: The following settings are required:
<code><pre> <code><pre>
path=. path=../templates
suffix=.tpl suffix=.tpl
encoding=UTF-8 encoding=UTF-8
cacheSize=1000000 cacheSize=1000000
@ -38,9 +39,9 @@
@see TemplateLoader @see TemplateLoader
*/ */
class TemplateCache : public TemplateLoader { class DECLSPEC TemplateCache : public TemplateLoader {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(TemplateCache); Q_DISABLE_COPY(TemplateCache)
public: public:
/** /**

View File

@ -1,7 +1,11 @@
INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD DEPENDPATH += $$PWD
HEADERS += $$PWD/template.h $$PWD/templateloader.h $$PWD/templatecache.h HEADERS += $$PWD/templateglobal.h
SOURCES += $$PWD/template.cpp $$PWD/templateloader.cpp $$PWD/templatecache.cpp HEADERS += $$PWD/template.h
HEADERS += $$PWD/templateloader.h
HEADERS += $$PWD/templatecache.h
OTHER_FILES += $$PWD/../doc/readme.txt SOURCES += $$PWD/template.cpp
SOURCES += $$PWD/templateloader.cpp
SOURCES += $$PWD/templatecache.cpp

View File

@ -32,18 +32,22 @@ TemplateLoader::TemplateLoader(QSettings* settings, QObject* parent)
} }
fileNameSuffix=settings->value("suffix",".tpl").toString(); fileNameSuffix=settings->value("suffix",".tpl").toString();
QString encoding=settings->value("encoding").toString(); QString encoding=settings->value("encoding").toString();
if (encoding.isEmpty()) { if (encoding.isEmpty())
{
textCodec=QTextCodec::codecForLocale(); textCodec=QTextCodec::codecForLocale();
} }
else { else
{
textCodec=QTextCodec::codecForName(encoding.toLocal8Bit()); textCodec=QTextCodec::codecForName(encoding.toLocal8Bit());
} }
qDebug("TemplateLoader: path=%s, codec=%s",qPrintable(templatePath),textCodec->name().data()); qDebug("TemplateLoader: path=%s, codec=%s",qPrintable(templatePath),textCodec->name().data());
} }
TemplateLoader::~TemplateLoader() {} TemplateLoader::~TemplateLoader()
{}
QString TemplateLoader::tryFile(QString localizedName) { QString TemplateLoader::tryFile(QString localizedName)
{
QString fileName=templatePath+"/"+localizedName+fileNameSuffix; QString fileName=templatePath+"/"+localizedName+fileNameSuffix;
qDebug("TemplateCache: trying file %s",qPrintable(fileName)); qDebug("TemplateCache: trying file %s",qPrintable(fileName));
QFile file(fileName); QFile file(fileName);
@ -51,28 +55,33 @@ QString TemplateLoader::tryFile(QString localizedName) {
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QString document=textCodec->toUnicode(file.readAll()); QString document=textCodec->toUnicode(file.readAll());
file.close(); file.close();
if (file.error()) { if (file.error())
{
qCritical("TemplateLoader: cannot load file %s, %s",qPrintable(fileName),qPrintable(file.errorString())); qCritical("TemplateLoader: cannot load file %s, %s",qPrintable(fileName),qPrintable(file.errorString()));
return ""; return "";
} }
else { else
{
return document; return document;
} }
} }
return ""; return "";
} }
Template TemplateLoader::getTemplate(QString templateName, QString locales) { Template TemplateLoader::getTemplate(QString templateName, QString locales)
{
mutex.lock(); mutex.lock();
QSet<QString> tried; // used to suppress duplicate attempts QSet<QString> tried; // used to suppress duplicate attempts
QStringList locs=locales.split(',',QString::SkipEmptyParts); QStringList locs=locales.split(',',QString::SkipEmptyParts);
// Search for exact match // Search for exact match
foreach (QString loc,locs) { foreach (QString loc,locs)
{
loc.replace(QRegExp(";.*"),""); loc.replace(QRegExp(";.*"),"");
loc.replace('-','_'); loc.replace('-','_');
QString localizedName=templateName+"-"+loc.trimmed(); QString localizedName=templateName+"-"+loc.trimmed();
if (!tried.contains(localizedName)) { if (!tried.contains(localizedName))
{
QString document=tryFile(localizedName); QString document=tryFile(localizedName);
if (!document.isEmpty()) { if (!document.isEmpty()) {
mutex.unlock(); mutex.unlock();
@ -83,12 +92,15 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales) {
} }
// Search for correct language but any country // Search for correct language but any country
foreach (QString loc,locs) { foreach (QString loc,locs)
{
loc.replace(QRegExp("[;_-].*"),""); loc.replace(QRegExp("[;_-].*"),"");
QString localizedName=templateName+"-"+loc.trimmed(); QString localizedName=templateName+"-"+loc.trimmed();
if (!tried.contains(localizedName)) { if (!tried.contains(localizedName))
{
QString document=tryFile(localizedName); QString document=tryFile(localizedName);
if (!document.isEmpty()) { if (!document.isEmpty())
{
mutex.unlock(); mutex.unlock();
return Template(document,localizedName); return Template(document,localizedName);
} }
@ -98,7 +110,8 @@ Template TemplateLoader::getTemplate(QString templateName, QString locales) {
// Search for default file // Search for default file
QString document=tryFile(templateName); QString document=tryFile(templateName);
if (!document.isEmpty()) { if (!document.isEmpty())
{
mutex.unlock(); mutex.unlock();
return Template(document,templateName); return Template(document,templateName);
} }

View File

@ -9,8 +9,9 @@
#include <QString> #include <QString>
#include <QSettings> #include <QSettings>
#include <QTextCodec> #include <QTextCodec>
#include "template.h"
#include <QMutex> #include <QMutex>
#include "templateglobal.h"
#include "template.h"
/** /**
Loads localized versions of template files. If the caller requests a file with the Loads localized versions of template files. If the caller requests a file with the
@ -25,7 +26,7 @@
The following settings are required: The following settings are required:
<code><pre> <code><pre>
path=. path=../templates
suffix=.tpl suffix=.tpl
encoding=UTF-8 encoding=UTF-8
</pre></code> </pre></code>
@ -34,9 +35,9 @@
@see TemplateCache @see TemplateCache
*/ */
class TemplateLoader : public QObject { class DECLSPEC TemplateLoader : public QObject {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(TemplateLoader); Q_DISABLE_COPY(TemplateLoader)
public: public:
/** /**