introduce conditions into odf
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 7 Dec 2008 13:20:00 +0000 (13:20 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 7 Dec 2008 13:20:00 +0000 (13:20 +0000)
git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@207 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

doc/prog_odttemplate.html
src/eventsummary.cpp
src/odtrender.cpp

index b025cfb..7291d71 100644 (file)
@@ -51,6 +51,37 @@ Loop variable names are enclosed in "@", and contain the loop name and the varia
 
 Loops cannot be nested.
 
+<h3>Conditional Output</h3>
+
+The output of parsed lines can be suppressed:
+
+<pre>
+#IF:MYVAR &lt; 66
+output if the value is smaller than 66
+#ELSE
+output otherwise
+#ENDIF
+</pre>
+
+A condition consists of exactly two values (both may be variables) and an operator. More complex expressions are not possible at the moment. If the condition evaluates to false, then the output and calculation of all lines until #ELSE or #ENDIF is suppressed.<p>
+
+At the moment the #ELSE statement reverses the output suppression between #IF and #ENDIF. Multiple #ELSEs are possible at the moment, but should not be relied upon in case the logic changes in subsequent versions.<p>
+
+Conditions cannot be nested, but conditions can be embedded in loops or be put around loops. If a condition is put around a loop, it does not prevent the processor from evaluating the loop, only the output and internal calculations are suppressed.<p>
+
+<table frame="1" border="1">
+<tr><td><b>Operator</b></td><td><b>Description</b></td></tr>
+<tr><td>&lt;</td><td>lighter than</td></tr>
+<tr><td>&lt;=</td><td>lighter or equal</td></tr>
+<tr><td>&gt;</td><td>greater than</td></tr>
+<tr><td>&gt;=</td><td>greater or equal</td></tr>
+<tr><td>&lt;&gt;</td><td>not equal</td></tr>
+<tr><td>!=</td><td>not equal</td></tr>
+<tr><td>=</td><td>equal</td></tr>
+<tr><td>==</td><td>equal</td></tr>
+</table>
+
+
 <h3>Calculations</h3>
 
 Numeric variables allow some very simple calculations in place:
@@ -67,13 +98,15 @@ For integer variables this works on the plain integer value. For money values it
 More complex calculations can be done with the #CALC statement:
 
 <pre>
-#CALC:TVAR/MONEY:@VAR1@ * @VAR2@ + 4
+#CALC:TVAR/MONEY:VAR1 * VAR2 + 4
 </pre>
 
-The above creates the temporary variable "@#TVAR@" that is the product of @VAR1@ and @VAR2@'s content plus 4. It is marked as a monetary value.<p>
+The above creates the temporary variable "@#TVAR@" that is the product of @VAR1@ and @VAR2@'s content plus 4. It is marked as a monetary value. Please note that the variables are not enclosed in "@".<p>
 
 Calculations are restricted to the operators below and are always done from left to right - more complex formulas require several lines. Tokens must be space separated. If no type or a non-existing type is requested INT is assumed. All calculations are done using 64bit signed integers. If the processor comes across an illegal token it sets the variable to "error".<p>
 
+Literals (above: "4") must be integers.<p>
+
 <table frame="1" border="1">
 <tr><td><b>Operator</b></td><td><b>Description</b></td></tr>
 <tr><td>+</td><td>adding</td></tr>
@@ -122,13 +155,16 @@ Per default all variables are localized before they get inserted into the docume
 
 File name: <tt>eventsummary.odtt</tt><p>
 
-Loop: <tt>TICKETS</tt> - this loop iterates over the ticket price categories.<p>
+Loops:<br/> 
+<tt>TICKETS</tt> - this loop iterates over the ticket price categories.<br/>
+<tt>ORDERS</tt> - this loop iterates over all orders that contain tickets for this event.<p>
 
 Variables:
 <table frame="1" border="1">
 <tr><td><b>Variable</b></td><td><b>Description</b></td></tr>
 <tr><td>@TITLE@</td><td>title of the event</td></tr>
 <tr><td>@ARTIST@</td><td>artist of the event</td></tr>
+<tr><td>@ROOM@</td><td>room of the event</td></tr>
 <tr><td>@START@</td><td>start date and time in the currently active locale</td></tr>
 <tr><td>@CAPACITY@</td><td>maximum amount of tickets that can be sold</td></tr>
 <tr><td>@RESERVED@</td><td>tickets that are currently reserved for a seller</td></tr>
@@ -170,9 +206,10 @@ File name: <tt>bill.odtt</tt><p>
 
 Loops: <br>
 <tt>TICKETS</tt> - this loop iterates over each ticket in the order.<br>
-<tt>ADDRESSLINES</tt> - this loop iterates over the lines of the address.<p>
+<tt>ACCTICKETS</tt> - this loop iterates over ticket categories in the order. Each category contains tickets for the same event with the same price.<br>
+<tt>ADDRESSLINES</tt> - this loop iterates over the lines of the address. (obsolete)<br>
+<tt>VOUCHERS</tt> - this loop iterates over all vouchers of the order.<p>
 
-(TODO: loop for vouchers)<p>
 
 Variables:
 <table frame="1" border="1">
@@ -218,8 +255,8 @@ Variables:
 <tr><td>@ACCTICKETS:ENDTIME@</td><td>the end date and time of the event for this ticket type</td></tr>
 <tr><td>@ACCTICKETS:ROOM@</td><td>the room/place of the event for this ticket type</td></tr>
 <tr/>
-<tr><td>@ADDRESSLINES@</td><td>amount of lines that the address has</td></tr>
-<tr><td>@ADDRESSLINES:LINE@</td><td>current line in the address loop</td></tr>
+<tr><td>@ADDRESSLINES@</td><td>amount of lines that the address has (obsolete)</td></tr>
+<tr><td>@ADDRESSLINES:LINE@</td><td>current line in the address loop (obsolete)</td></tr>
 <tr/>
 <tr><td>@VOUCHERS@</td><td>the amount of vouchers in the order</td></tr>
 <tr><td>@VOUCHERS:PRICE@</td><td>the price of this voucher</td></tr>
index 9f524d9..1b7b166 100644 (file)
@@ -213,6 +213,9 @@ void MEventSummary::getVariable(QString varname,MOdtRenderer::VarType&av,QVarian
        if(varname=="ARTIST")
                value=event.artist();
        else
+       if(varname=="ROOM")
+               value=event.room();
+       else
        if(varname=="START"){
                value=event.startTime();
                av=MOdtRenderer::DateTimeVar;
index f10961d..a27cd0c 100644 (file)
@@ -58,6 +58,7 @@ class MOdtRendererPrivate
                QUnZip temp;
                QFile tfile;
                QString newline;
+               bool inif,iftrue;
                
                struct LocalVar{
                        MOdtRenderer::VarType type;
@@ -77,6 +78,7 @@ MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p)
 {
        parent=p;
        newline=" ";
+       inif=iftrue=true;
        //open ZIP
        if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile);
        //TODO: make sure this is a valid ZIP file, preferably with some ODT content
@@ -200,7 +202,6 @@ QString MOdtRendererPrivate::render(QString s)
                                        //...line by line
                                        for(int k=0;k<lbuf.size();k++){
                                                ret+=renderLine(lbuf[k],lname,j);
-                                               ret+="\n";
                                        }
                                }
                                //reset state
@@ -219,7 +220,6 @@ QString MOdtRendererPrivate::render(QString s)
                        }else{//not a loop or statement
                                //convert line
                                ret+=renderLine(fbuf[i],"",-1);
-                               ret+="\n";
                        }
                }
        }
@@ -232,13 +232,50 @@ QString MOdtRendererPrivate::renderLine(QString line,QString loop,int lpos)
        QString ret,vname;
        bool isvar=false;
        static QString vc="ABCDEFGHIJKLMNOPQRSTUVWXYZ:+-0123456789$#";
-       //check for statements
+       //check for conditionals
+       if(line.trimmed().startsWith("#IF:")){
+               QString stmt=line.trimmed().mid(3).trimmed();
+               qDebug("????????????????If: %s",stmt.toAscii().data());
+               //split out var name
+               //get list of statement tokens
+               QStringList stl=stmt.split(" ");
+               if(stl.size()!=3){
+                       qDebug("???????????If failed, expected 3 tokens, got %i tokens",stl.size());
+                       return "";
+               }
+               iftrue=inif=true;
+               //go through
+               qint64 op1=intToken(stl[0],loop,lpos);
+               qint64 op2=intToken(stl[2],loop,lpos);
+               if(stl[1]=="<")iftrue=op1<op2;else
+               if(stl[1]==">")iftrue=op1>op2;else
+               if(stl[1]=="=" || stl[1]=="=")iftrue=op1==op2;else
+               if(stl[1]=="<=")iftrue=op1<=op2;else
+               if(stl[1]==">=")iftrue=op1>=op2;else
+               if(stl[1]=="<>" || stl[1]=="!=")iftrue=op1!=op2;
+               else {
+                       qDebug("??????????IfError: unknown operator");
+                       return "";
+               }
+               return "";
+       }else
+       if(line.trimmed()=="#ELSE"){
+               iftrue=!iftrue;
+               return "";
+       }else
+       if(line.trimmed()=="#ENDIF"){
+               inif=false;
+               return "";
+       }
+       //check if state
+       if(inif && !iftrue)return "";
+       //check for other statements
        if(line.trimmed().startsWith("#SETNEWLINE:")){
                //set a new newline translation
                newline=line.trimmed().mid(12).trimmed();
                if(newline=="")newline=" ";
                return "";
-       }
+       }else
        if(line.trimmed().startsWith("#CALC:")){
                //do a calculation
                //get full statement
@@ -252,22 +289,34 @@ QString MOdtRendererPrivate::renderLine(QString line,QString loop,int lpos)
                QStringList stl=stmt.mid(p+1).trimmed().split(" ");
                //go through
                qint64 res=intToken(stl[0],loop,lpos);
-               qDebug("??????????CalcInit: %lli",res);
+//             qDebug("??????????CalcInit: %lli",res);
                for(int i=1;i<stl.size();i+=2){
                        if((i+1)>=stl.size()){
                                setLocalVarError(var);
-                               qDebug("??????????CalcError: missing operand");
+                               qDebug("??????????CalcError: missing last operand");
                                return "";
                        }
-                       qDebug("??????????Calc: operator '%s' operand '%s' -> '%lli'",stl[i].toAscii().data(),stl[i+1].toAscii().data(),intToken(stl[i+1],loop,lpos));
-                       if(stl[i]=="+")res+=intToken(stl[i+1],loop,lpos);else
-                       if(stl[i]=="-")res-=intToken(stl[i+1],loop,lpos);else
-                       if(stl[i]=="*")res*=intToken(stl[i+1],loop,lpos);else
-                       if(stl[i]=="/")res/=intToken(stl[i+1],loop,lpos);else
-                       if(stl[i]=="%")res%=intToken(stl[i+1],loop,lpos);
-                       else {
+                       qint64 op2=intToken(stl[i+1],loop,lpos);
+//                     qDebug("??????????Calc: operator '%s' operand '%s' -> '%lli'",stl[i].toAscii().data(),stl[i+1].toAscii().data(),op2);
+                       if(stl[i]=="+")res+=op2;else
+                       if(stl[i]=="-")res-=op2;else
+                       if(stl[i]=="*")res*=op2;else
+                       if(stl[i]=="/"){
+                               if(op2!=0)res/=op2;
+                               else{
+                                       qDebug("??????????CalcError: division operand %s is zero",stl[i+1].toAscii().data());
+                                       return "";
+                               }
+                       }else
+                       if(stl[i]=="%"){
+                               if(op2!=0)res%=op2;
+                               else{
+                                       qDebug("??????????CalcError: modulo operand %s is zero",stl[i+1].toAscii().data());
+                                       return "";
+                               }
+                       }else {
                                setLocalVarError(var);
-                               qDebug("??????????CalcError: unknown operator");
+                               qDebug("??????????CalcError: unknown operator %s",stl[i].toAscii().data());
                                return "";
                        }
                }
@@ -332,7 +381,7 @@ QString MOdtRendererPrivate::renderLine(QString line,QString loop,int lpos)
                ret+="@"+vname;
        }
        //return transformed line
-       return ret;
+       return ret + "\n";
 }
 
 static inline QString formatVar(QVariant r,MOdtRenderer::VarType tp,bool loc,int offset)
@@ -428,6 +477,10 @@ QString MOdtRendererPrivate::getLoopVariable(QString loopname,int iteration,QStr
 
 qint64 MOdtRendererPrivate::intToken(QString vname,QString loop,int lpos)
 {
+       //check for literals
+       bool islit;
+       qint64 lit=vname.toLongLong(&islit);
+       if(islit)return lit;
        //split the variable
        QStringList vnl=vname.split(":");
        if(vnl.size()<2){