ODT rendering from XML - new template format
authorKonrad Rosenbaum <konrad@silmor.de>
Sun, 5 Feb 2012 20:44:09 +0000 (21:44 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Sun, 5 Feb 2012 20:44:09 +0000 (21:44 +0100)
12 files changed:
elam
src/dialogs/eventsummary.cpp
src/dialogs/eventsummary.h
src/dialogs/orderwin.cpp
src/dialogs/orderwin.h
src/misc/misc.pri
src/misc/msengine.cpp [new file with mode: 0644]
src/misc/msengine.h [new file with mode: 0644]
src/templates/odfedit.cpp
src/templates/odfedit.h
src/templates/odtrender.cpp
src/templates/odtrender.h

diff --git a/elam b/elam
index 8eed1dd..f0c1627 160000 (submodule)
--- a/elam
+++ b/elam
@@ -1 +1 @@
-Subproject commit 8eed1dd9716f2db330d915bf6f4c5bff52b5069e
+Subproject commit f0c16272d5ec1cb313175ede04afb135c1472702
index d30ddeb..be77d22 100644 (file)
@@ -174,9 +174,9 @@ void MEventSummary::print()
                return;
        }
        MOdtSignalRenderer rend(tf);
-       connect(&rend,SIGNAL(getVariable(QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getVariable(QString,MOdtRenderer::VarType&,QVariant&)));
+       connect(&rend,SIGNAL(getVariable(QString,QVariant&)), this,SLOT(getVariable(QString,QVariant&)));
        connect(&rend,SIGNAL(getLoopIterations(QString,int&)),this,SLOT(getLoopIterations(QString,int&)));
-       connect(&rend,SIGNAL(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)));
+       connect(&rend,SIGNAL(setLoopIteration(QString,int)), this,SLOT(setLoopIteration(QString,int)));
        rend.renderToPrinter();
 }
 
@@ -200,13 +200,13 @@ void MEventSummary::saveas()
                fname=fn[0];
        }
        MOdtSignalRenderer rend(tf);
-       connect(&rend,SIGNAL(getVariable(QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getVariable(QString,MOdtRenderer::VarType&,QVariant&)));
-       connect(&rend,SIGNAL(getLoopIterations(QString,int&)),this,SLOT(getLoopIterations(QString,int&)));
-       connect(&rend,SIGNAL(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)));
+       connect(&rend,SIGNAL(getVariable(QString,QVariant&)), this,SLOT(getVariable(QString,QVariant&)));
+       connect(&rend,SIGNAL(getLoopIterations(QString,int&)), this,SLOT(getLoopIterations(QString,int&)));
+       connect(&rend,SIGNAL(setLoopIteration(QString,int)), this,SLOT(setLoopIteration(QString,int)));
        rend.renderToFile(fname);
 }
 
-void MEventSummary::getVariable(QString varname,MOdtRenderer::VarType&av,QVariant&value)
+void MEventSummary::getVariable(QString varname,QVariant&value)
 {
        if(varname=="TITLE")
                value=event.title().value();
@@ -219,55 +219,49 @@ void MEventSummary::getVariable(QString varname,MOdtRenderer::VarType&av,QVarian
        else
        if(varname=="START"){
                value=event.start().value();
-               av=MOdtRenderer::DateTimeVar;
        }else
        if(varname=="CAPACITY"){
                value=event.capacity().value();
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="RESERVED"){
                value=nreserved;
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="BOUGHT"){
                value=ntotaltickets;
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="USED"){
                int nused=0;
                for(int i=0;i<tickets.size();i++)nused+=tickets[i].used;
                value=nused;
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="UNUSED"){
                int nunused=0;
                for(int i=0;i<tickets.size();i++)nunused+=tickets[i].unused;
                value=nunused;
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="CANCELLED"){
                value=ncancelled;
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="TOTALMONEY"){
                value=ntotalmoney;
-               av=MOdtRenderer::MoneyVar;
        }else
        if(varname=="TICKETS"){
                value=tickets.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="COMMENTS"){
                value=comments.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="ORDERS"){
                value=orderids.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(varname=="EVENTPRICE"){
                value=/*event.defaultprice().value()*/(int)1;
-               av=MOdtRenderer::MoneyVar;
+       }else{
+               if(varname.contains(':')){
+                       QStringList sl=varname.split(':');
+                       if(!loopiter.contains(sl[0]))return;
+                       getLoopVariable(sl[0],loopiter[sl[0]],sl[1],value);
+               }
        }
 }
 
@@ -276,30 +270,33 @@ void MEventSummary::getLoopIterations(QString loopname,int&iterations)
        if(loopname=="TICKETS")iterations=tickets.size();else
        if(loopname=="COMMENTS")iterations=comments.size();else
        if(loopname=="ORDERS")iterations=orderids.size();
-       else
-               iterations=0;
 }
 
-void MEventSummary::getLoopVariable(QString loopname,int iteration,QString varname,MOdtRenderer::VarType&av,QVariant&value)
+void MEventSummary::setLoopIteration(QString lv, int it)
+{
+       if(it<0)return;
+       int max=-1;
+       getLoopIterations(lv,max);
+       if(it>=max)return;
+       loopiter.insert(lv,it);
+}
+
+void MEventSummary::getLoopVariable(QString loopname,int iteration,QString varname,QVariant&value)
 {
        if(loopname=="TICKETS"){
                if(iteration<0 || iteration>=tickets.size())return;
                
                if(varname=="PRICE"){
                        value=tickets[iteration].price;
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(varname=="BOUGHT"){
                        value=tickets[iteration].bought;
-                       av=MOdtRenderer::IntVar;
                }else
                if(varname=="USED"){
                        value=tickets[iteration].used;
-                       av=MOdtRenderer::IntVar;
                }else
                if(varname=="UNUSED"){
                        value=tickets[iteration].unused;
-                       av=MOdtRenderer::IntVar;
                }
        }else
        if(loopname=="COMMENTS"){
@@ -327,12 +324,10 @@ void MEventSummary::getLoopVariable(QString loopname,int iteration,QString varna
                if(varname=="CUSTOMER")value=orders[oid].customer().value().fullName();else
                if(varname=="FULLPRICE"){
                        value=orders[oid].totalprice().value();
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(varname=="SHIPPING")value=orders[oid].shippingtype().value().description().value();else
                if(varname=="SHIPPINGCOST"){
                        value=orders[oid].shippingcosts().value();
-                       av=MOdtRenderer::MoneyVar;
                }else{
                        QList<MOTicket>ticks=orders[oid].tickets();
                        QList<MOTicket>eticks;
@@ -350,32 +345,27 @@ void MEventSummary::getLoopVariable(QString loopname,int iteration,QString varna
                                                ua++;
                                //calculate weighted amount
                                value=orders[oid].shippingcosts()*eticks.size()/ua;
-                               av=MOdtRenderer::MoneyVar;
                        }else
                        if(varname=="SHIPPINGCOSTIFFIRST"){
                                if(first==event.start())
                                        value=orders[oid].shippingcosts().value();
                                else
                                        value=0;
-                               av=MOdtRenderer::MoneyVar;
                        }else
                        if(varname=="SHIPPINGCOSTIFLAST"){
                                if(last==event.start())
                                        value=orders[oid].shippingcosts().value();
                                else
                                        value=0;
-                               av=MOdtRenderer::MoneyVar;
                        }else
                        if(varname=="NUMTICKETS"){
                                value=eticks.size();
-                               av=MOdtRenderer::IntVar;
                        }else
                        if(varname=="TICKETPRICE"){
                                int prc=0;
                                for(int i=0;i<eticks.size();i++)
                                        prc+=eticks[i].price();
                                value=prc;
-                               av=MOdtRenderer::MoneyVar;
                        }
                }
        }
index fd5a6a8..bc511bd 100644 (file)
@@ -41,9 +41,10 @@ class MEventSummary:public QDialog
                void saveas();
                
                //used for ODT rendering:
-               void getVariable(QString,MOdtRenderer::VarType&,QVariant&);
+               void getVariable(QString,QVariant&);
                void getLoopIterations(QString,int&);
-               void getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&);
+               void getLoopVariable(QString,int,QString,QVariant&);
+               void setLoopIteration(QString,int);
                
        private:
                qint64 eventid;
@@ -62,6 +63,7 @@ class MEventSummary:public QDialog
                QList<int>orderids;
                QMap<int,MOOrder>orders;
                QMap<int,MOCustomerInfo>customers;
+               QMap<QString,int>loopiter;
                
                //get summary
                void getSummaryData();
index 82fa970..fe16a96 100644 (file)
@@ -414,9 +414,9 @@ void MOrderWindow::printBill()
        //print bill
        initPrintBuffer();
        MOdtSignalRenderer rend(tf);
-       connect(&rend,SIGNAL(getVariable(QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getVariable(QString,MOdtRenderer::VarType&,QVariant&)));
-       connect(&rend,SIGNAL(getLoopIterations(QString,int&)),this,SLOT(getLoopIterations(QString,int&)));
-       connect(&rend,SIGNAL(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)));
+       connect(&rend,SIGNAL(getVariable(QString,QVariant&)), this,SLOT(getVariable(QString,QVariant&)));
+       connect(&rend,SIGNAL(getLoopIterations(QString,int&)), this,SLOT(getLoopIterations(QString,int&)));
+       connect(&rend,SIGNAL(setLoopIteration(QString,int)), this,SLOT(setLoopIteration(QString,int)));
        rend.renderToPrinter();
        donePrintBuffer();
 }
@@ -452,30 +452,26 @@ void MOrderWindow::saveBill()
        //render bill
        initPrintBuffer();
        MOdtSignalRenderer rend(tf);
-       connect(&rend,SIGNAL(getVariable(QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getVariable(QString,MOdtRenderer::VarType&,QVariant&)));
-       connect(&rend,SIGNAL(getLoopIterations(QString,int&)),this,SLOT(getLoopIterations(QString,int&)));
-       connect(&rend,SIGNAL(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)),this,SLOT(getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&)));
+       connect(&rend,SIGNAL(getVariable(QString,QVariant&)), this,SLOT(getVariable(QString,QVariant&)));
+       connect(&rend,SIGNAL(getLoopIterations(QString,int&)), this,SLOT(getLoopIterations(QString,int&)));
+       connect(&rend,SIGNAL(setLoopIteration(QString,int)), this,SLOT(setLoopIteration(QString,int&)));
        rend.renderToFile(fname);
        donePrintBuffer();
 }
 
-void MOrderWindow::getVariable(QString vn,MOdtRenderer::VarType& av,QVariant&value)
+void MOrderWindow::getVariable(QString vn,QVariant&value)
 {
        if(vn=="ORDERDATE"){
                value=m_order.ordertime().value();
-               av=MOdtRenderer::DateVar;
        }else
        if(vn=="ORDERDATETIME"){
                value=m_order.ordertime().value();
-               av=MOdtRenderer::DateTimeVar;
        }else
        if(vn=="SENTDATE"){
                value=m_order.senttime().value();
-               av=MOdtRenderer::DateVar;
        }else
        if(vn=="SENTDATETIME"){
                value=m_order.senttime().value();
-               av=MOdtRenderer::DateTimeVar;
        }else
        if(vn=="CUSTOMERID")value=QString::number(m_order.customerid());else
        if(vn=="ORDERID")value=QString::number(m_order.orderid());else
@@ -486,42 +482,40 @@ void MOrderWindow::getVariable(QString vn,MOdtRenderer::VarType& av,QVariant&val
        if(vn=="FINALADDRESS")value=m_order.fullDeliveryAddress();else
        if(vn=="TOTALPRICE"){
                value=m_order.totalprice().value();
-               av=MOdtRenderer::MoneyVar;
        }else
        if(vn=="AMOUNTPAID"){
                value=m_order.amountpaid().value();
-               av=MOdtRenderer::MoneyVar;
        }else
        if(vn=="SELLER")value=m_order.soldby().value();else
        if(vn=="COMMENT")value=m_order.comments().value();else
        if(vn=="AMOUNTTOPAY"){
                value=m_order.amountToPay();
-               av=MOdtRenderer::MoneyVar;
        }else
        if(vn=="AMOUNTTOREFUND"){
                value=m_order.amountToRefund();
-               av=MOdtRenderer::MoneyVar;
        }else
        if(vn=="TICKETS"){
                value=printBuffer.tickets.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(vn=="ACCTICKETS"){
                value=printBuffer.tickinfo.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(vn=="VOUCHERS"){
                value=printBuffer.vouchers.size();
-               av=MOdtRenderer::IntVar;
        }else
        if(vn=="ADDRESSLINES"){
                value=m_order.fullInvoiceAddress().split("\n").size();
-               av=MOdtRenderer::IntVar;
        }else
        if(vn=="SHIPPING")value=m_order.shippingtype().value().description().value();else
        if(vn=="SHIPPINGPRICE"){
                value=m_order.shippingtype().value().cost().value();
-               av=MOdtRenderer::MoneyVar;
+       }else{
+               if(vn.contains(':')){
+                       QStringList sl=vn.split(':');
+                       int it=-1;
+                       if(m_loopiter.contains(sl[0]))it=m_loopiter[sl[0]];
+                       getLoopVariable(sl[0],it,sl[1],value);
+               }
        }
 }
 
@@ -532,7 +526,18 @@ void MOrderWindow::getLoopIterations(QString loopname,int&iterations)
        if(loopname=="VOUCHERS")iterations=printBuffer.vouchers.size();
        if(loopname=="ADDRESSLINES")iterations=m_order.fullInvoiceAddress().split("\n").size();
 }
-void MOrderWindow::getLoopVariable(QString loopname,int it,QString vn,MOdtRenderer::VarType& av,QVariant&value)
+
+void MOrderWindow::setLoopIteration(QString loopname, int iteration)
+{
+       int max=-1;
+       if(iteration<0)return;
+       getLoopIterations(loopname,max);
+       if(iteration>=max)return;
+       m_loopiter.insert(loopname,iteration);
+}
+
+
+void MOrderWindow::getLoopVariable(QString loopname,int it,QString vn,QVariant&value)
 {
        if(loopname=="TICKETS"){
                QList<MOTicket> &tickets=printBuffer.tickets;
@@ -540,22 +545,18 @@ void MOrderWindow::getLoopVariable(QString loopname,int it,QString vn,MOdtRender
                
                if(vn=="PRICE"){
                        value=tickets[it].price().value();
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(vn=="ID")value=tickets[it].ticketid().value();else
                if(vn=="TITLE")value=tickets[it].event().title().value();else
                if(vn=="ARTIST")value=tickets[it].event().artist().value().name().value();else
                if(vn=="DATE"){
                        value=tickets[it].event().start().value();
-                       av=MOdtRenderer::DateVar;
                }else
                if(vn=="STARTTIME"){
                        value=tickets[it].event().start().value();
-                       av=MOdtRenderer::DateTimeVar;
                }else
                if(vn=="ENDTIME"){
                        value=tickets[it].event().end().value();
-                       av=MOdtRenderer::DateTimeVar;
                }else
                if(vn=="ROOM")value=tickets[it].event().room().value();
        }else if(loopname=="ACCTICKETS"){
@@ -564,41 +565,33 @@ void MOrderWindow::getLoopVariable(QString loopname,int it,QString vn,MOdtRender
                
                if(vn=="PRICE"){
                        value=tickets[it].proto.price().value();
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(vn=="FULLPRICE"){
                        value=tickets[it].proto.price().value()*tickets[it].amount;
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(vn=="TITLE")value=tickets[it].proto.event().title().value();else
                if(vn=="ARTIST")value=tickets[it].proto.event().artist().value().name().value();else
                if(vn=="DATE"){
                        value=tickets[it].proto.event().start().value();
-                       av=MOdtRenderer::DateVar;
                }else
                if(vn=="STARTTIME"){
                        value=tickets[it].proto.event().start().value();
-                       av=MOdtRenderer::DateTimeVar;
                }else
                if(vn=="ENDTIME"){
                        value=tickets[it].proto.event().end().value();
-                       av=MOdtRenderer::DateTimeVar;
                }else
                if(vn=="ROOM")value=tickets[it].proto.event().room().value();else
                if(vn=="AMOUNT"){
                        value=tickets[it].amount;
-                       av=MOdtRenderer::IntVar;
                }
        }else if(loopname=="VOUCHERS"){
                if(it<0 || it>=printBuffer.vouchers.size())return;
                
                if(vn=="PRICE"){
                        value=printBuffer.vouchers[it].price().value();
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(vn=="VALUE"){
                        value=printBuffer.vouchers[it].value().value();
-                       av=MOdtRenderer::MoneyVar;
                }else
                if(vn=="ID")value=printBuffer.vouchers[it].voucherid().value();
        }else if(loopname=="ADDRESSLINES"){
index 02da7ac..50b7e19 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <QDialog>
 #include <QMainWindow>
+#include <QMap>
+
 #include "odtrender.h"
 
 #include "MOOrder"
@@ -56,11 +58,13 @@ class MOrderWindow:public QMainWindow
                /**save the bill as file*/
                void saveBill();
                /**callback for bill generator: variables; see MOdtSignalRenderer for details*/
-               void getVariable(QString,MOdtRenderer::VarType&,QVariant&);
+               void getVariable(QString,QVariant&);
                /**callback for bill generator: loops; see MOdtSignalRenderer for details*/
                void getLoopIterations(QString loopname,int&iterations);
+               /**callback to set values of a specific loop iteration*/
+               void setLoopIteration(QString loopname,int iteration);
                /**callback for bill generator: loop variables; see MOdtSignalRenderer for details*/
-               void getLoopVariable(QString,int,QString,MOdtRenderer::VarType&,QVariant&);
+               void getLoopVariable(QString,int,QString,QVariant&);
 
                /**received payment*/
                void payment();
@@ -112,6 +116,7 @@ class MOrderWindow:public QMainWindow
                QTableView *m_table;
                QStandardItemModel *m_model;
                QAction*m_res2order,*m_cancel,*m_ship,*m_pay,*m_payv,*m_refund;
+               QMap<QString,int>m_loopiter;
                
                //printing buffer
                struct TickInfo{
index 35bca43..0793c37 100644 (file)
@@ -1,18 +1,20 @@
 HEADERS += \
-       misc/debug.h \
-       misc/misc.h \
-       misc/waitcursor.h \
-       misc/sclock.h \
-       misc/formula.h \
-       misc/lambda.h
+       $$PWD/debug.h \
+       $$PWD/misc.h \
+       $$PWD/waitcursor.h \
+       $$PWD/sclock.h \
+       $$PWD/formula.h \
+       $$PWD/lambda.h \
+       $$PWD/msengine.h
 
 SOURCES += \
-       misc/code39.cpp \
-       misc/debug.cpp \
-       misc/misc.cpp \
-       misc/waitcursor.cpp \
-       misc/sclock.cpp \
-       misc/formula.cpp
+       $$PWD/code39.cpp \
+       $$PWD/debug.cpp \
+       $$PWD/misc.cpp \
+       $$PWD/waitcursor.cpp \
+       $$PWD/sclock.cpp \
+       $$PWD/formula.cpp \
+       $$PWD/msengine.cpp
 
-INCLUDEPATH += ./misc
+INCLUDEPATH += $$PWD
 QMAKE_CXXFLAGS += -std=gnu++0x
\ No newline at end of file
diff --git a/src/misc/msengine.cpp b/src/misc/msengine.cpp
new file mode 100644 (file)
index 0000000..b8d5425
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// C++ Implementation: MSmoke ELAM Engine
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2012
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "msengine.h"
+
+#include "misc.h"
+
+using namespace ELAM;
+
+MSEngine::MSEngine(QObject* parent)
+       :Engine(parent)
+{
+       IntEngine::configureIntEngine(*this);
+       StringEngine::configureStringEngine(*this);
+       BoolEngine::configureBoolEngine(*this);
+       BoolEngine::configureLogicEngine(*this);
+       FloatEngine::configureFloatEngine(*this);
+       setFunction("cent2str",[](const QList<QVariant>&args,Engine&)->QVariant{
+               if(args.size()!=1)
+                       return Exception(Exception::ArgumentListError,"expected one argument to cent2str");
+               else
+                       return cent2str(args[0].toInt());
+       });
+       setFunction("str2cent",[](const QList<QVariant>&args,Engine&)->QVariant{
+               if(args.size()!=1)
+                       return Exception(Exception::ArgumentListError,"expected one argument to str2cent");
+               else
+                       return str2cent(args[0].toString());
+       });
+       setFunction("unix2time",[](const QList<QVariant>&args,Engine&)->QVariant{
+               if(args.size()!=1)
+                       return Exception(Exception::ArgumentListError,"expected one argument to unix2time");
+               else
+                       return unix2time(args[0].toInt());
+       });
+       setFunction("unix2date",[](const QList<QVariant>&args,Engine&)->QVariant{
+               if(args.size()!=1)
+                       return Exception(Exception::ArgumentListError,"expected one argument to unix2date");
+               else
+                       return unix2date(args[0].toInt());
+       });
+       setFunction("unix2dateTime",[](const QList<QVariant>&args,Engine&)->QVariant{
+               if(args.size()!=1)
+                       return Exception(Exception::ArgumentListError,"expected one argument to unix2dateTime");
+               else
+                       return unix2dateTime(args[0].toInt());
+       });
+}
+
+void MSEngine::enableLoopVars()
+{
+       CharacterClassSettings ccs=characterClasses();
+       //simplify assignment
+       ccs.setAssignmentChars('\0','=');
+       //remove :. from operators
+       QString str=ccs.operatorClass();
+       str.remove(':');str.remove('.');
+       ccs.setOperatorClass(str);
+       //add :. to variables
+       QPair<QString,QString>nc=ccs.nameClass();
+       if(!nc.second.contains(':'))nc.second+=":";
+       if(!nc.second.contains('.'))nc.second+=".";
+       ccs.setNameClass(nc);
+}
diff --git a/src/misc/msengine.h b/src/misc/msengine.h
new file mode 100644 (file)
index 0000000..d420b7b
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// C++ Interface: MSmoke Elam Engine with specialized functions
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2012
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_MSENGINE_H
+#define MAGICSMOKE_MSENGINE_H
+
+#include <elam.h>
+
+///convenience ELAM engine that comes preconfigured for all types and with special MSmoke functions
+class MSEngine:public ELAM::Engine
+{
+       public:
+               ///instantiate the engine
+               explicit MSEngine(QObject*parent=0);
+               
+               ///moves the ":." chars from the operator class to the variable class to enable the
+               ///loop variable syntax, assignment becomes a simple "="
+               void enableLoopVars();
+};
+
+#endif
index faed04e..13da05e 100644 (file)
 #include <QUnZip>
 #include <QZip>
 
-#define HRECT 1
-#define HFONT 2
-#define HFILE 4
-#define HALIGN 8
-#define HSMOOTH 0x10
-#define HCONTENT 0x20
-
-class MOEExampleDelegate:public QItemDelegate
-{
-       public:
-               MOEExampleDelegate(QObject *parent = 0):QItemDelegate(parent){}
-
-               QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
-                       const QModelIndex &index) const
-               {
-                       if(index.column()!=1)return 0;
-                       QString tp=index.model()->data(index,Qt::UserRole).toString();
-                       if(tp=="string")return new QLineEdit(parent);
-                       if(tp=="money")return new MCentSpinBox(parent);
-                       if(tp=="date")return new QDateTimeEdit(parent);
-                       return 0;
-               }
-
-               void setEditorData(QWidget *editor, const QModelIndex &index) const
-               {
-                       const QAbstractItemModel*model=index.model();
-                       QString tp=index.model()->data(index,Qt::UserRole).toString();
-                       if(tp=="string")
-                               ((QLineEdit*)editor)->setText(model->data(index).toString());
-                       if(tp=="money")
-                               ((MCentSpinBox*)editor)->setValue(str2cent(model->data(index).toString()));
-                       if(tp=="date")
-                               ((QDateTimeEdit*)editor)->setDateTime(QDateTime::fromString(model->data(index).toString(),Qt::ISODate));
-                       
-               }
-               void setModelData(QWidget *editor, QAbstractItemModel *model,
-                       const QModelIndex &index) const
-               {
-                       QString tp=index.model()->data(index,Qt::UserRole).toString();
-                       if(tp=="string")
-                               model->setData(index, ((QLineEdit*)editor)->text());
-                       if(tp=="money")
-                               model->setData(index, cent2str(((MCentSpinBox*)editor)->value()));
-                       if(tp=="date")
-                               model->setData(index, ((QDateTimeEdit*)editor)->dateTime().toString(Qt::ISODate));
-               }
-
-               void updateEditorGeometry(QWidget *editor,
-                       const QStyleOptionViewItem &option, const QModelIndex &) const
-               {editor->setGeometry(option.rect);}
-};
 
 class DPTR_CLASS_NAME(MOdfEditor)
 {
@@ -110,182 +59,66 @@ class DPTR_CLASS_NAME(MOdfEditor)
                //template file
                QString mFileName;
                //file contents
-               QMap<QString,QByteArray>mFiles;
-               QString mUnit;
-               QSizeF mSize;
-               enum Type{
-                       Unknown=0,
-                       LoadFont=0x100|HFILE,
-                       Picture=0x200|HFILE|HRECT|HSMOOTH,
-                       Text=0x300|HFONT|HRECT|HALIGN|HCONTENT,
-                       Barcode=0x400|HRECT,
-               };
-               struct Line_s{
-                       Line_s(){type=Unknown;smooth=false;fontsize=0;align=Qt::AlignCenter;}
-                       Line_s(int t){type=(Type)t;smooth=false;fontsize=0;align=Qt::AlignCenter;}
+               struct File{
+                       QString name;
+                       enum class Type{None,Directory,FlatFile};
                        Type type;
-                       QSizeF size;
-                       QPointF offset;
-                       QString file;
-                       bool smooth;
-                       QString font;
-                       double fontsize;
-                       Qt::Alignment align;
-                       QString content;
+                       QByteArray content;
+                       File(){type=Type::None;}
+                       File(QString n,Type t,const QByteArray&c):name(n),type(t),content(c){}
                };
-               QList<Line_s>mLines;
+               QList<File> mFiles;
+               //content.xml
+               QDomDocument mContent;
                //widgets
-               QDoubleSpinBox*labelwidth,*labelheight;
-               QComboBox*unitbox;
-               QTableView*itemtable,*filetable,*expltable;
-               QStandardItemModel*itemmodel,*filemodel,*explmodel;
-               QLabel*ticketpicture;
-               QSlider*zoomslide;
 };
 
 DEFINE_DPTR(MOdfEditor);
 
 MOdfEditor::MOdfEditor(QWidget* parent, Qt::WindowFlags f): QMainWindow(parent, f)
 {
-       setWindowTitle(tr("Label Editor"));
+       setWindowTitle(tr("ODF Template Editor"));
        //menu
        QMenuBar*mb=menuBar();
        QMenu*m=mb->addMenu(tr("&File"));
-       m->addAction(tr("&Open File..."), this, SLOT(openFile()), tr("Ctrl+O","open file shortcut"));
+       m->addAction(tr("&Open Template File..."), this, SLOT(openFile()), tr("Ctrl+O","open file shortcut"));
+       m->addAction(tr("&Import ODF File..."), this, SLOT(openFile2()), tr("Ctrl+Shift+O","import ODF file shortcut"));
        m->addAction(tr("&Save"), this, SLOT(saveFile()), tr("Ctrl+S","save file shortcut"));
        m->addAction(tr("Save &as..."),this,SLOT(saveFileAs()));
        m->addSeparator();
        m->addAction(tr("&Close"),this,SLOT(close()));
+       
        m=mb->addMenu(tr("&Edit"));
-       QMenu *aim=m->addMenu(tr("&Add Item"));
+       m->addAction(tr("Insert &Calculation"));
+       m->addAction(tr("Insert C&ondition"));
+       m->addAction(tr("Insert &Else"));
+       m->addAction(tr("Insert &Loop"));
+       m->addSeparator();
        m->addAction(tr("&Remove Item"),this,SLOT(delItem()));
+       
+       m=mb->addMenu(tr("&Data"));
+       m->addAction(tr("Import from Order..."));
        m->addSeparator();
-       m->addAction(tr("Add &File"),this,SLOT(addFile()));
-       m->addAction(tr("Remove F&ile"),this,SLOT(delFile()));
-       QSignalMapper*map=new QSignalMapper(this);
-       map->setMapping(aim->addAction(tr("Add &Text Item"),map,SLOT(map())),(int)Private::Text);
-       map->setMapping(aim->addAction(tr("Add &Picture Item"),map,SLOT(map())),(int)Private::Picture);
-       map->setMapping(aim->addAction(tr("Add &Barcode Item"),map,SLOT(map())),(int)Private::Barcode);
-       map->setMapping(aim->addAction(tr("Add &Load Font Item"),map,SLOT(map())),(int)Private::LoadFont);
-       connect(map,SIGNAL(mapped(int)),this,SLOT(addItem(int)));
+       m->addAction(tr("Test Printing..."));
+       m->addAction(tr("Save Test Document..."));
        
        //central
        QSplitter*central=new QSplitter(Qt::Vertical);
        setCentralWidget(central);
-       QWidget*w=new QWidget;
-       central->addWidget(w);
        QVBoxLayout*vl,*vl2;
        QHBoxLayout*hl,*hl2;
        QPushButton*p;
-       w->setLayout(vl=new QVBoxLayout);
-       vl->addLayout(hl=new QHBoxLayout,0);
-       //basic data line
-       hl->addWidget(new QLabel(tr("Label Size:")));
-       hl->addWidget(d->labelwidth=new QDoubleSpinBox);
-       hl->addWidget(new QLabel("x"));
-       hl->addWidget(d->labelheight=new QDoubleSpinBox);
-       hl->addWidget(d->unitbox=new QComboBox);
-       d->unitbox->addItem(tr("Millimeter"),"mm");
-       d->unitbox->addItem(tr("Inch"),"in");
-       hl->addStretch(1);
-       //item table
-       vl->addWidget(w=new QWidget);
-       w->setLayout(vl2=new QVBoxLayout);
-       vl2->addWidget(d->itemtable=new QTableView,1);
-       d->itemtable->setModel(d->itemmodel=new QStandardItemModel(this));
-       d->itemtable->horizontalHeader()->show();
-       d->itemtable->verticalHeader()->hide();
-       d->itemtable->setItemDelegate(new MOELabelDelegate(this));
-       vl2->addLayout(hl2=new QHBoxLayout,0);
-       hl2->addStretch(1);
-       hl2->addWidget(p=new QPushButton(QIcon(":/arrowup.png"),tr("Move up")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(upItem()));
-       hl2->addWidget(p=new QPushButton(QIcon(":/arrowdown.png"),tr("Move down")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(downItem()));
-       hl2->addSpacing(10);
-       hl2->addWidget(p=new QPushButton(tr("Add Item")),0);
-       p->setMenu(aim);
-       hl2->addWidget(p=new QPushButton(tr("Remove Item")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(delItem()));
-       //bottom
-       QSplitter*split;
-       central->addWidget(split=new QSplitter);
-       //file table
-       split->addWidget(w=new QWidget);
-       w->setLayout(vl2=new QVBoxLayout);
-       vl2->addWidget(d->filetable=new QTableView,1);
-       d->filetable->setModel(d->filemodel=new QStandardItemModel(this));
-       d->filetable->horizontalHeader()->show();
-       d->filetable->verticalHeader()->hide();
-       d->filetable->setEditTriggers(QAbstractItemView::NoEditTriggers);
-       vl2->addLayout(hl2=new QHBoxLayout,0);
-       hl2->addStretch(1);
-       hl2->addWidget(p=new QPushButton(tr("Add File")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(addFile()));
-       hl2->addWidget(p=new QPushButton(tr("Remove File")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(delFile()));
-       //label display
-       QTabWidget*tab;
-       split->addWidget(tab=new QTabWidget);
-       tab->addTab(w=new QWidget,tr("As Label"));
-       w->setLayout(vl=new QVBoxLayout);
-       vl->addLayout(hl=new QHBoxLayout,0);
-       hl->addWidget(new QLabel(tr("Zoom:")),0);
-       hl->addWidget(d->zoomslide=new QSlider,1);
-       d->zoomslide->setOrientation(Qt::Horizontal);
-       d->zoomslide->setRange(-10,10);
-       d->zoomslide->setTickPosition(QSlider::TicksBothSides);
-       connect(d->zoomslide,SIGNAL(valueChanged(int)),this,SLOT(rerender()));
-       hl->addWidget(p=new QPushButton(tr("Refresh")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(rerender()));
-       QScrollArea*sa;
-       vl->addWidget(sa=new QScrollArea,1);
-       sa->setWidget(d->ticketpicture=new QLabel);
-       sa->setWidgetResizable(true);
-       d->ticketpicture->setScaledContents(false);
-       d->ticketpicture->setAlignment(Qt::AlignCenter);
-       tab->addTab(d->expltable=new QTableView,tr("Example Data"));
-       d->expltable->setModel(d->explmodel=new QStandardItemModel(this));
-       d->expltable->setItemDelegate(new MOEExampleDelegate(this));
-       d->expltable->horizontalHeader()->show();
-       d->expltable->verticalHeader()->hide();
+       
        
        //statusbar
        statusBar()->setSizeGripEnabled(true);
        setAttribute(Qt::WA_DeleteOnClose);
-       loadExampleData();
-}
-
-const QString example(
-"BARCODE\tABCDEFGHIJK\tstring\n"
-"PRICE\t12.34\tmoney\n"
-"ROOM\tThe invisible Cabinet\tstring\n"
-"TITLE\tSome title, this is.\tstring\n"
-"DATETIME\t2023-01-23T19:54\tdate\n"
-"ARTIST\tHenry the Drycleaner\tstring\n"
-"PRICECATEGORY\tExpensive\tstring\n"
-"PRICECATEGORYABBR\texp\tstring\n"
-"VALUE\t12.00\tmoney");
-
-void MOdfEditor::loadExampleData()
-{
-       d->explmodel->clear();
-       d->explmodel->setHorizontalHeaderLabels(QStringList()<<tr("Variable")<<tr("Content"));
-       QStringList ex1=example.split("\n");
-       d->explmodel->insertRows(0,ex1.size());
-       QSettings set;
-       set.beginGroup("labeleditor/examples");
-       for(int i=0;i<ex1.size();i++){
-               QStringList ex2=ex1[i].split("\t");
-               d->explmodel->setData(d->explmodel->index(i,0),ex2[0]);
-               d->explmodel->setData(d->explmodel->index(i,1), set.value(ex2[0],ex2[1]));
-               d->explmodel->setData(d->explmodel->index(i,1), ex2[2], Qt::UserRole);
-       }
 }
 
 
 void MOdfEditor::loadFile(QString fn)
 {
+       qDebug()<<"loading ODF template file"<<fn;
        //try to open the file
        if(fn=="")return;
        QFile fd(fn);
@@ -300,7 +133,7 @@ void MOdfEditor::loadFile(QString fn)
        }
        //clear cache
        d->mFiles.clear();
-       d->mLines.clear();
+       d->mFileName=fn;
        //read data
        unz.gotoFirstFile();
        do{
@@ -308,116 +141,23 @@ void MOdfEditor::loadFile(QString fn)
                unz.getCurrentFileInfo(ifn,0);
                QBuffer buf;buf.open(QIODevice::ReadWrite);
                unz.getCurrentFile(buf);
-               if(ifn=="template.xml")
+               if(ifn=="content.xml")
                        parseTemplate(buf.data());
                else
-                       d->mFiles.insert(ifn,buf.data());
+                       d->mFiles<<Private::File(ifn,Private::File::Type::FlatFile,buf.data());
        }while(unz.gotoNextFile());
        //update display
        updateDisplay();
 }
 
-static inline QSizeF str2size(QString s)
-{
-       QStringList sl=s.trimmed().split(" ");
-       if(sl.size()!=2)return QSizeF();
-       return QSizeF(sl[0].toDouble(),sl[1].toDouble());
-}
-
-static inline QString size2str(QSizeF s)
-{
-       return QString("%1 %2").arg(s.width()).arg(s.height());
-}
-
-static inline QPointF str2point(QString s)
-{
-       QStringList sl=s.trimmed().split(" ");
-       if(sl.size()!=2)return QPointF();
-       return QPointF(sl[0].toDouble(),sl[1].toDouble());
-}
-
-static inline QString point2str(QPointF p)
-{
-       return QString("%1 %2").arg(p.x()).arg(p.y());
-}
-
-static inline QString align2str(Qt::Alignment a)
-{
-       switch(a){
-               case Qt::AlignTop:
-                       return QCoreApplication::translate("MOdfEditor","top");
-               case Qt::AlignBottom:
-                       return QCoreApplication::translate("MOdfEditor","bottom");
-               case Qt::AlignHCenter:
-               case Qt::AlignVCenter:
-                       return QCoreApplication::translate("MOdfEditor","center");
-               case Qt::AlignLeft:
-                       return QCoreApplication::translate("MOdfEditor","left");
-               case Qt::AlignRight:
-                       return QCoreApplication::translate("MOdfEditor","right");
-               default:
-                       return QCoreApplication::translate("MOdfEditor","align (%1)").arg((int)a);
-       }
-}
-
-static inline QString align2xml(Qt::Alignment a)
-{
-       switch(a){
-               case Qt::AlignTop:
-                       return "top";
-               case Qt::AlignBottom:
-                       return "bottom";
-               case Qt::AlignHCenter:
-               case Qt::AlignVCenter:
-                       return "center";
-               case Qt::AlignLeft:
-                       return "left";
-               case Qt::AlignRight:
-                       return "right";
-               default:
-                       return "";
-       }
-}
 
 void MOdfEditor::parseTemplate(QByteArray bytes)
 {
-       QDomDocument doc;
-       if(!doc.setContent(bytes)){
+       if(!d->mContent.setContent(bytes)){
                QMessageBox::warning(this,tr("Warning"),tr("Unable to interpret template data."));
                return;
        }
-       QDomElement root=doc.documentElement();
-       d->mSize=str2size(root.attribute("size"));
-       d->mUnit=root.attribute("unit","mm");
-       QDomNodeList nl=root.childNodes();
-       for(int i=0;i<nl.size();i++){
-               QDomElement el=nl.at(i).toElement();
-               if(el.isNull())continue;
-               QString tn=el.tagName();
-               Private::Line_s line;
-               if(tn=="LoadFont")line.type=Private::LoadFont;else
-               if(tn=="Picture")line.type=Private::Picture;else
-               if(tn=="Text")line.type=Private::Text;else
-               if(tn=="Barcode")line.type=Private::Barcode;
-               else line.type=Private::Unknown;
-               line.file=el.attribute("file");
-               line.font=el.attribute("font");
-               line.fontsize=el.attribute("fontsize","10").toDouble();
-               line.offset=str2point(el.attribute("offset"));
-               line.size=str2size(el.attribute("size"));
-               line.smooth=el.attribute("smoot")=="1";
-               line.align=0;
-               tn=el.attribute("align");
-               if(tn=="left")line.align=Qt::AlignLeft;else
-               if(tn=="right")line.align=Qt::AlignRight;else
-               if(tn=="center")line.align=Qt::AlignHCenter;
-               tn=el.attribute("valign");
-               if(tn=="top")line.align|=Qt::AlignTop;else
-               if(tn=="bottom")line.align|=Qt::AlignBottom;else
-               if(tn=="center")line.align|=Qt::AlignVCenter;
-               line.content=el.text();
-               d->mLines.append(line);
-       }
+       //TODO: converter V1->V2
 }
 
 void MOdfEditor::openFile()
@@ -462,286 +202,6 @@ void MOdfEditor::updateDisplay()
        else
                setWindowTitle(tr("Label Template Editor [%1]").arg(d->mFileName));
        //basics
-       d->labelwidth->setValue(d->mSize.width());
-       d->labelheight->setValue(d->mSize.height());
-       for(int i=0;i<d->unitbox->count();i++)
-               if(d->unitbox->itemData(i).toString()==d->mUnit)
-                       d->unitbox->setCurrentIndex(i);
-       //files
-       d->filemodel->clear();
-       if(d->filemodel->columnCount()<2)
-               d->filemodel->insertColumns(0,2);
-       d->filemodel->insertRows(0,d->mFiles.size());
-       d->filemodel->setHorizontalHeaderLabels(QStringList()<<tr("File Name")<<tr("Size"));
-       QStringList fnames=d->mFiles.keys();
-       for(int i=0;i<d->mFiles.size();i++){
-               d->filemodel->setData(d->filemodel->index(i,0),fnames[i]);
-               d->filemodel->setData(d->filemodel->index(i,1),d->mFiles[fnames[i]].size());
-       }
-       d->filetable->resizeColumnsToContents();
-       //items
-       d->itemmodel->clear();
-       d->itemmodel->insertRows(0,d->mLines.size());
-       d->itemmodel->setHorizontalHeaderLabels(QStringList()
-               <<tr("Type")
-               <<tr("Offset")
-               <<tr("Size")
-               <<tr("File/Font")
-               <<tr("Font Size")
-               <<tr("Scaling")
-               <<tr("Horiz. Alignment")
-               <<tr("Vert. Alignment")
-               <<tr("Text Data")
-       );
-       for(int i=0;i<d->mLines.size();i++){
-               QString tp;
-               Private::Type tpe=d->mLines[i].type;
-               switch(tpe){
-                       case Private::LoadFont:tp=tr("Load Font File");break;
-                       case Private::Picture:tp=tr("Show Picture");break;
-                       case Private::Text:tp=tr("Show Text Line");break;
-                       case Private::Barcode:tp=tr("Show Barcode");break;
-                       default:tp=tr("Unknown");break;
-               }
-               d->itemmodel->setData(d->itemmodel->index(i,0),tp);
-               d->itemmodel->setData(d->itemmodel->index(i,0),(int)tpe,Qt::UserRole);
-               if(tpe&HRECT){
-                       d->itemmodel->setData(d->itemmodel->index(i,2), size2str(d->mLines[i].size));
-                       d->itemmodel->setData(d->itemmodel->index(i,1), point2str(d->mLines[i].offset));
-               }
-               if(tpe&HFONT){
-                       d->itemmodel->setData(d->itemmodel->index(i,3),d->mLines[i].font);
-                       d->itemmodel->setData(d->itemmodel->index(i,4),d->mLines[i].fontsize);
-               }
-               if(tpe&HFILE)
-                       d->itemmodel->setData(d->itemmodel->index(i,3),d->mLines[i].file);
-               if(tpe&HSMOOTH)
-                       d->itemmodel->setData(d->itemmodel->index(i,5), d->mLines[i].smooth?tr("smooth"):tr("edged"));
-               if(tpe&HALIGN){
-                       d->itemmodel->setData(d->itemmodel->index(i,6), align2str(d->mLines[i].align&Qt::AlignHorizontal_Mask));
-                       d->itemmodel->setData(d->itemmodel->index(i,7), align2str(d->mLines[i].align&Qt::AlignVertical_Mask));
-               }
-               if(tpe&HCONTENT)
-                       d->itemmodel->setData(d->itemmodel->index(i,8), d->mLines[i].content);
-       }
-       d->itemtable->resizeColumnsToContents();
-       //do rendering
-       rerender();
-}
-
-QWidget* MOELabelDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& , const QModelIndex& index) const
-{
-       //get type
-       int tp=index.model()->data(index.model()->index(index.row(),0),Qt::UserRole).toInt();
-       switch(index.column()){
-               case 0:
-                       return 0;
-               case 1:case 2:
-                       if(tp&HRECT){
-                               QLineEdit*ed=new QLineEdit(parent);
-                               ed->setValidator(new QRegExpValidator(QRegExp("^(-?)[0-9\\.]+ (-?)[0-9\\.]+"),ed));
-                               return ed;
-                       }else return 0;
-               case 3:
-                       if(tp&HFONT || tp&HFILE)
-                               return new QComboBox(parent);
-                       else return 0;
-               case 4:
-                       if(tp&HFONT)
-                               return new QDoubleSpinBox(parent);
-                       else return 0;
-               case 5:
-                       if(tp&HSMOOTH)
-                               return new QComboBox(parent);
-                       else return 0;
-               case 6:case 7:
-                       if(tp&HALIGN)
-                               return new QComboBox(parent);
-                       else return 0;
-               case 8:
-                       if(tp&HCONTENT)
-                               return new QLineEdit(parent);
-                       else return 0;
-               default: return 0;
-       }
-}
-
-void MOELabelDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
-{
-       const QAbstractItemModel*model=index.model();
-       int tp=model->data(model->index(index.row(),0),Qt::UserRole).toInt();
-       int line=index.row();
-       QComboBox*cb;
-       switch(index.column()){
-               case 1:case 2:case 8:
-                       ((QLineEdit*)editor)->setText(model->data(index).toString());
-                       break;
-               case 3:{
-                       cb=(QComboBox*)editor;
-                       QStringList k=mParent->d->mFiles.keys();
-                       qSort(k);
-                       QString c=model->data(index).toString();
-                       if(tp&HFONT){
-                               for(int i=0;i<k.size();i++)
-                                       cb->addItem("@"+k[i]);
-                               k=QFontDatabase().families();
-                               qSort(k);
-                               cb->addItems(k);
-                               for(int i=0;i<cb->count();i++)
-                                       if(cb->itemText(i)==c)
-                                               cb->setCurrentIndex(i);
-                       }else{
-                               cb->addItems(k);
-                               for(int i=0;i<k.size();i++)
-                                       if(c==k[i])
-                                               cb->setCurrentIndex(i);
-                       }
-                       break;
-               }
-               case 4:
-                       ((QDoubleSpinBox*)editor)->setValue(model->data(index).toDouble());
-                       break;
-               case 5:
-                       cb=(QComboBox*)editor;
-                       cb->addItem(tr("edged"));
-                       cb->addItem(tr("smooth"));
-                       cb->setCurrentIndex(mParent->d->mLines[line].smooth?1:0);
-                       break;
-               case 6:
-                       cb=(QComboBox*)editor;
-                       cb->addItem(align2str(Qt::AlignLeft),Qt::AlignLeft);
-                       cb->addItem(align2str(Qt::AlignHCenter),Qt::AlignHCenter);
-                       cb->addItem(align2str(Qt::AlignRight),Qt::AlignRight);
-                       switch(mParent->d->mLines[line].align&Qt::AlignHorizontal_Mask){
-                               case Qt::AlignHCenter:cb->setCurrentIndex(1);break;
-                               case Qt::AlignRight:cb->setCurrentIndex(2);break;
-                               default:break;
-                       }
-                       break;
-               case 7:
-                       cb=(QComboBox*)editor;
-                       cb->addItem(align2str(Qt::AlignTop),Qt::AlignTop);
-                       cb->addItem(align2str(Qt::AlignVCenter),Qt::AlignVCenter);
-                       cb->addItem(align2str(Qt::AlignBottom),Qt::AlignBottom);
-                       switch(mParent->d->mLines[line].align&Qt::AlignVertical_Mask){
-                               case Qt::AlignVCenter:cb->setCurrentIndex(1);break;
-                               case Qt::AlignBottom:cb->setCurrentIndex(2);break;
-                               default:break;
-                       }
-                       break;
-               default:break;
-       }
-}
-
-void MOELabelDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
-{
-       int tp=index.model()->data(index.model()->index(index.row(),0),Qt::UserRole).toInt();
-       QString s;
-       int line=index.row();
-       QComboBox*cb;
-       switch(index.column()){
-               case 1:
-                       s=((QLineEdit*)editor)->text();
-                       mParent->d->mLines[line].offset=str2point(s);
-                       model->setData(index,point2str(mParent->d->mLines[line].offset));
-                       break;
-               case 2:
-                       s=((QLineEdit*)editor)->text();
-                       mParent->d->mLines[line].size=str2size(s);
-                       model->setData(index,size2str(mParent->d->mLines[line].size));
-                       break;
-               case 3:
-                       cb=(QComboBox*)editor;
-                       if(tp&HFONT){
-                               mParent->d->mLines[line].font=cb->currentText();
-                       }else{
-                               mParent->d->mLines[line].file=cb->currentText();
-                       }
-                       model->setData(index,cb->currentText());
-                       break;
-               case 4:
-                       mParent->d->mLines[line].fontsize=((QDoubleSpinBox*)editor)->value();
-                       model->setData(index,mParent->d->mLines[line].fontsize);
-                       break;
-               case 5:
-                       mParent->d->mLines[line].smooth=((QComboBox*)editor)->currentIndex()!=0;
-                       model->setData(index,((QComboBox*)editor)->currentText());
-                       break;
-               case 6:
-                       cb=((QComboBox*)editor);
-                       mParent->d->mLines[line].align&=Qt::AlignVertical_Mask;
-                       mParent->d->mLines[line].align|=Qt::AlignmentFlag(cb->itemData(cb->currentIndex()).toInt());
-                       model->setData(index,cb->currentText());
-                       break;
-               case 7:
-                       cb=((QComboBox*)editor);
-                       mParent->d->mLines[line].align&=Qt::AlignHorizontal_Mask;
-                       mParent->d->mLines[line].align|=Qt::AlignmentFlag(cb->itemData(cb->currentIndex()).toInt());
-                       model->setData(index,cb->currentText());
-                       break;
-               case 8:
-                       s=((QLineEdit*)editor)->text();
-                       mParent->d->mLines[line].content=s;
-                       model->setData(index,s);
-                       break;
-               default:break;
-       }
-       mParent->rerender();
-}
-
-
-class MTELabel:public MLabel
-{
-       QMap<QString,QString>exdata;
-       public:
-               MTELabel(QMap<QString,QString>dt)
-               {
-                       exdata=dt;
-                       exdata.insert("TICKETID",dt["BARCODE"]);
-                       exdata.insert("VOUCHERID",dt["BARCODE"]);
-               }
-               QString getVariable(QString s)const
-               {
-                       QString ret=exdata.value(s);
-                       if(s=="PRICE"||s=="VALUE")
-                               ret=cent2str(str2cent(ret));
-                       else if(s=="DATETIME")
-                               ret=unix2dateTime(QDateTime::fromString(ret,Qt::ISODate).toTime_t());
-                       return ret;
-               }
-};
-
-void MOdfEditor::rerender()
-{
-       QMap<QString,QString>exdata;
-       for(int i=0;i<d->explmodel->rowCount();i++){
-               exdata.insert(
-                       d->explmodel->data(d->explmodel->index(i,0)).toString(),
-                       d->explmodel->data(d->explmodel->index(i,1)).toString()
-               );
-       }
-       MTELabel label(exdata);
-       //calculate scaling factor
-       int zfi=d->zoomslide->value();
-       qreal zff=1.0;
-       if(zfi!=0){
-               for(int i=0;i<zfi;i++)zff*=1.2;
-               for(int i=0;i>zfi;i--)zff/=1.2;
-       }
-       //render ticket
-       QTemporaryFile tfile(QDir::tempPath()+"/templateXXXXXX.xtt");
-       tfile.open();
-       saveTemplate(tfile);
-       MLabelRenderer rend(tfile.fileName());
-       QSize size(rend.labelSize(*d->ticketpicture).toSize());
-       QImage tick=QPixmap(size*zff).toImage();
-       tick.setDotsPerMeterX(tick.dotsPerMeterX()*zff);
-       tick.setDotsPerMeterY(tick.dotsPerMeterY()*zff);
-       tick.fill(0xffffffff);
-       if(!rend.render(label,tick))
-               qDebug("unable to render");
-       //scale and display
-       d->ticketpicture->setPixmap(QPixmap::fromImage(tick));
 }
 
 void MOdfEditor::saveTemplate(QFile& fd)
@@ -750,14 +210,14 @@ void MOdfEditor::saveTemplate(QFile& fd)
        zip.open(&fd);
        {QBuffer buf;buf.open(QIODevice::ReadWrite);
        saveXmlPart(buf);buf.seek(0);
-       zip.storeFile("template.xml",buf);}
-       QStringList k=d->mFiles.keys();
-       for(int i=0;i<k.size();i++){
+       zip.storeFile("content.xml",buf);}
+       for(int i=0;i<d->mFiles.size();i++){
+               if(d->mFiles[i].type!=Private::File::Type::FlatFile)continue;
                QBuffer buf;
                buf.open(QIODevice::ReadWrite);
-               buf.write(d->mFiles[k[i]]);
+               buf.write(d->mFiles[i].content);
                buf.seek(0);
-               zip.storeFile(k[i],buf);
+               zip.storeFile(d->mFiles[i].name,buf);
        }
        zip.close();
        fd.flush();
@@ -765,119 +225,6 @@ void MOdfEditor::saveTemplate(QFile& fd)
 
 void MOdfEditor::saveXmlPart(QIODevice& fd)
 {
-       QDomDocument doc;
-       QDomElement root=doc.createElement("LabelTemplate");
-       root.setAttribute("size",size2str(d->mSize));
-       root.setAttribute("unit",d->mUnit);
-       for(int i=0;i<d->mLines.size();i++){
-               Private::Line_s ln=d->mLines[i];
-               QDomElement el;
-               switch(ln.type){
-                       case Private::LoadFont:el=doc.createElement("LoadFont");break;
-                       case Private::Picture:el=doc.createElement("Picture");break;
-                       case Private::Text:el=doc.createElement("Text");break;
-                       case Private::Barcode:el=doc.createElement("Barcode");break;
-                       default:continue;
-               }
-               if(ln.type&HRECT){
-                       el.setAttribute("size",size2str(ln.size));
-                       el.setAttribute("offset",point2str(ln.offset));
-               }
-               if(ln.type&HFILE)
-                       el.setAttribute("file",ln.file);
-               if(ln.type&HFONT){
-                       el.setAttribute("font",ln.font);
-                       el.setAttribute("fontsize",ln.fontsize);
-               }
-               if(ln.type&HSMOOTH)
-                       el.setAttribute("smooth",ln.smooth?"1":"0");
-               if(ln.type&HALIGN){
-                       el.setAttribute("align",align2xml(ln.align&Qt::AlignHorizontal_Mask));
-                       el.setAttribute("valign",align2xml(ln.align&Qt::AlignVertical_Mask));
-               }
-               if(ln.type&HCONTENT)
-                       el.appendChild(doc.createTextNode(ln.content));
-               root.appendChild(el);
-       }
-       doc.appendChild(root);
        //save
-       fd.write(doc.toByteArray());
-}
-
-
-void MOdfEditor::addFile()
-{
-       QString fn=QFileDialog::getOpenFileName(this,tr("Add File to Label"));
-       if(fn=="")return;
-       //try to read it
-       QFile fd(fn);
-       if(!fd.open(QIODevice::ReadOnly)){
-               QMessageBox::warning(this,tr("Warning"),tr("Unable to read file %1").arg(fn));
-               return;
-       }
-       QByteArray fdata=fd.readAll();
-       fd.close();
-       //ask for internal name
-       fn=QFileInfo(fn).fileName();
-       fn=QInputDialog::getText(this,tr("File Name"),tr("Please enter the internal file name:"),QLineEdit::Normal,fn);
-       if(fn=="")return;
-       fn=QFileInfo(fn).fileName();
-       if(fn=="")return;
-       //append
-       d->mFiles.insert(fn,fdata);
-       updateDisplay();
-}
-
-void MOdfEditor::delFile()
-{
-       //get file name
-       QModelIndex idx=d->filetable->currentIndex();
-       if(!idx.isValid())return;
-       QString fn=d->filemodel->data(d->filemodel->index(idx.row(),0)).toString();
-       if(fn=="")return;
-       //ask
-       if(QMessageBox::question(this,tr("Really delete?"),tr("Really remove file '%1' from the label?").arg(fn),QMessageBox::No|QMessageBox::Yes)!=QMessageBox::Yes)
-               return;
-       //delete
-       d->mFiles.remove(fn);
-       updateDisplay();
-}
-
-void MOdfEditor::addItem(int type)
-{
-       d->mLines.append(Private::Line_s(type));
-       updateDisplay();
-}
-
-void MOdfEditor::delItem()
-{
-       QModelIndex idx=d->itemtable->currentIndex();
-       if(!idx.isValid())return;
-       d->mLines.removeAt(idx.row());
-       updateDisplay();
-}
-
-void MOdfEditor::downItem()
-{
-       QModelIndex idx=d->itemtable->currentIndex();
-       if(!idx.isValid())return;
-       int r=idx.row();
-       if(r>=(d->mLines.size()-1))return;
-       Private::Line_s tmp=d->mLines[r];
-       d->mLines[r]=d->mLines[r+1];
-       d->mLines[r+1]=tmp;
-       updateDisplay();
-       d->itemtable->setCurrentIndex(d->itemmodel->index(r+1,idx.column()));
-}
-void MOdfEditor::upItem()
-{
-       QModelIndex idx=d->itemtable->currentIndex();
-       if(!idx.isValid())return;
-       int r=idx.row();
-       if(r<=0)return;
-       Private::Line_s tmp=d->mLines[r];
-       d->mLines[r]=d->mLines[r-1];
-       d->mLines[r-1]=tmp;
-       updateDisplay();
-       d->itemtable->setCurrentIndex(d->itemmodel->index(r-1,idx.column()));
+       fd.write(d->mContent.toByteArray());
 }
index f7c9d1c..4688e44 100644 (file)
@@ -26,7 +26,6 @@ class MOdfEditor:public QMainWindow
 {
        Q_OBJECT
        DECLARE_DPTR(d);
-       friend class MOELabelDelegate;
        public:
                ///instantiates the editor
                MOdfEditor(QWidget* parent = 0, Qt::WindowFlags f = 0);
@@ -43,47 +42,14 @@ class MOdfEditor:public QMainWindow
                ///helper for saveFile and upload
                void saveFile(QString);
        private slots:
-               ///renders the label
-               void rerender();
                ///parses the XML part of the template file and fills internal ressources
                void parseTemplate(QByteArray);
                ///pushes all data from internal ressources to the display
                void updateDisplay();
-               ///add a specific kind of item line
-               void addItem(int);
-               ///delete currently selected item line
-               void delItem();
-               ///move selected item up
-               void upItem();
-               ///move selected item down
-               void downItem();
-               ///add a file (image/font) to the template
-               void addFile();
-               ///delete the selected file from the template
-               void delFile();
-               ///used by constructor to load example data for the example label
-               void loadExampleData();
                ///saves all data to the file (must be open ReadWrite)
                void saveTemplate(QFile&);
                ///helper: saves the XML part of the template (device must be writable)
                void saveXmlPart(QIODevice&);
 };
 
-/// \internal helper for the ticket editor
-class MOELabelDelegate:public QItemDelegate
-{
-       Q_OBJECT
-       MOdfEditor*mParent;
-       public:
-               MOELabelDelegate(MOdfEditor *parent):QItemDelegate(parent) 
-               {mParent=parent;}
-               QWidget *createEditor(QWidget *, const QStyleOptionViewItem &,
-                       const QModelIndex &) const;
-               void setEditorData(QWidget *, const QModelIndex &) const;
-               void setModelData(QWidget *, QAbstractItemModel *,
-                       const QModelIndex &) const ;
-               void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, 
-                         const QModelIndex &) const {editor->setGeometry(option.rect);}
-};
-
 #endif
index 7938cf2..086c359 100644 (file)
 #include <QSettings>
 #include <QTemporaryFile>
 
-#include "QUnZip"
-#include "QZip"
+#include <QUnZip>
+#include <QZip>
 
+#include "msengine.h"
+using namespace ELAM;
+
+class MOdfEngine:public MSEngine
+{
+       MOdtRenderer*parent;
+       public:
+               MOdfEngine(MOdtRenderer* pa):parent(pa){}
+               bool hasConstant(QString v)const
+               {
+                       if(parent->getVariable(v).isValid())
+                               return true;
+                       else
+                               return MSEngine::hasConstant(v);
+               }
+               QVariant getConstant(QString v)const
+               {
+                       QVariant vv=parent->getVariable(v);
+                       if(vv.isValid())
+                               return vv;
+                       else
+                               return MSEngine::getConstant(v);
+               }
+};
 
 class MOdtRendererPrivate
 {
@@ -43,47 +67,45 @@ class MOdtRendererPrivate
                
        private:
                //methods that the parent does not call
+               
+               ///overall rendering: copies the templates content, calls render()
                void render(QIODevice*);
                
-               QString render(QString);
+               ///content.xml rendering
+               QList<QDomNode> render(QDomNode node);
                
-               QString renderLine(QString,QString,int);
+               ///scan string and replace variable values
+               QString renderString(QString);
                
+               ///gets a scalar variable
                QString getVariable(QString varname);
-               QString getLoopVariable(QString loopname,int iteration,QString varname);
-               
-               qint64 intToken(QString,QString,int);
-               void setLocalVar(QString,qint64);
-               void setLocalVarError(QString);
                
                //data the parent does not access
+               //parent
                MOdtRenderer*parent;
+               //the template file
                QUnZip temp;
                QFile tfile;
-               QString newline;
-               bool inif,iftrue;
+               //xml representation of the content.xml file in the template
                QDomDocument cdoc;
                
-               struct LocalVar{
-                       MOdtRenderer::VarType type;
-                       QVariant value;
-               };
-               QMap<QString,LocalVar>localvars;
+               //local variables and calculation engine
+               Engine *calc;
 };
 
 MOdtRenderer::MOdtRenderer(MTemplate file)
 {
        d=new MOdtRendererPrivate(file.cacheFileName(),this);
        d->extension=file.targetExtension();
+       d->calc=new MOdfEngine(this);
 }
 
 const QString OdfTemplateNS("http://smoke.silmor.de/odftemplate/namespace");
+const QString OdfTemplatePrefix("msmoketpl");
 MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p)
        :tfile(file)
 {
        parent=p;
-       newline=" ";
-       inif=iftrue=true;
        //open ZIP
        if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile);
        else {
@@ -102,14 +124,15 @@ MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p)
        temp.getCurrentFile(buffer);
        QString err;int errln,errcl;
        bool dov1=false;
-       if(!cdoc.setContent(&buffer,true,&err,&errln,&errcl)){
+       const QString tpename=OdfTemplatePrefix+":template";
+       if(!cdoc.setContent(&buffer,false,&err,&errln,&errcl)){
                qDebug()<<"Hmm, not XML, trying version 1 converter...";
                qDebug()<<" Info: line ="<<errln<<"column ="<<errcl<<"error ="<<err;
                dov1=true;
        }else{
                //check for template element
                QDomElement de=cdoc.documentElement();
-               if(de.isNull()||de.tagName()!="Template"||de.namespaceURI()!=OdfTemplateNS){
+               if(de.isNull()||de.tagName()!=tpename){
                        qDebug()<<"Template is not v2, trying to convert...";
                        dov1=true;
                        cdoc.clear();
@@ -118,7 +141,7 @@ MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p)
        //conversion process
        if(!dov1)return;
        //try again
-       if(!cdoc.setContent(MOdtRenderer::convertV1toV2(buffer.data()),true,&err,&errln,&errcl)){
+       if(!cdoc.setContent(MOdtRenderer::convertV1toV2(buffer.data()),false,&err,&errln,&errcl)){
                qDebug()<<"Hmm, definitely not XML - even after conversion, aborting...";
                qDebug()<<" Info: line ="<<errln<<"column ="<<errcl<<"error ="<<err;
                return;
@@ -128,6 +151,8 @@ MOdtRendererPrivate::MOdtRendererPrivate(QString file,MOdtRenderer*p)
 
 MOdtRenderer::~MOdtRenderer()
 {
+       if(d==nullptr)return;
+       if(d->calc!=nullptr)delete d->calc;
        delete d;
        d=0;
 }
@@ -182,8 +207,14 @@ void MOdtRenderer::renderToPrinter()
 void MOdtRendererPrivate::render(QIODevice*out)
 {
        //sanity check
-       if(!temp.isOpen())return;
-       if(!out->isWritable())return;
+       if(!temp.isOpen()){
+               qDebug()<<"ODF Renderer: I don't have a valid template, cannot render.";
+               return;
+       }
+       if(!out->isWritable()){
+               qDebug()<<"ODF Renderer Ooops: output device not writeable when trying to render.";
+               return;
+       }
        //rewind input
        if(!temp.gotoFirstFile())return;
        //create output
@@ -195,14 +226,10 @@ void MOdtRendererPrivate::render(QIODevice*out)
                QDateTime tstamp;
                temp.getCurrentFileInfo(cname,&tstamp);
                if(cname=="content.xml"){
-                       //get content
-                       QBuffer buffer;
-                       buffer.open(QBuffer::ReadWrite);
-                       temp.getCurrentFile(buffer);
                        //render
-                       QByteArray cont=render(QString::fromUtf8(buffer.data())).toUtf8();
+                       QByteArray cont=render(cdoc.cloneNode()).value(0).toDocument().toByteArray();
                        //write
-                       buffer.close();
+                       QBuffer buffer;
                        buffer.setData(cont);
                        buffer.open(QBuffer::ReadWrite);
                        buffer.seek(0);
@@ -221,201 +248,136 @@ void MOdtRendererPrivate::render(QIODevice*out)
        ozip.close();
 }
 
-QString MOdtRendererPrivate::render(QString s)
-{
-       //buffer for the whole file
-       QStringList fbuf=s.split("\n");
-       //buffer for loops
-       QStringList lbuf;
-       QString lname;
-       //buffer for return value
-       QString ret;
-       //go through all lines
-       bool isloop=false;
-       for(int i=0;i<fbuf.size();i++){
-               //are we inside a loop?
-               if(isloop){
-                       //is this the end of the loop?
-                       if(fbuf[i].trimmed()=="#ENDLOOP"){
-                               //get iterations
-                               int lcnt=parent->getLoopIterations(lname);
-                               //render the loop...
-                               for(int j=0;j<lcnt;j++){
-                                       //...line by line
-                                       for(int k=0;k<lbuf.size();k++){
-                                               ret+=renderLine(lbuf[k],lname,j);
-                                       }
-                               }
-                               //reset state
-                               isloop=false;
-                               lbuf.clear();
-                               lname="";
-                       }else{//not finished yet
-                               //collect lines
-                               lbuf<<fbuf[i];
-                       }
-               }else{//not inside a loop
-                       //is this the start of a loop?
-                       if(fbuf[i].trimmed().startsWith("#LOOP:")){
-                               lname=fbuf[i].trimmed().mid(6).trimmed();
-                               isloop=true;
-                       }else{//not a loop or statement
-                               //convert line
-                               ret+=renderLine(fbuf[i],"",-1);
-                       }
-               }
-       }
-       //return result
+static inline QList<QDomNode> n2q(const QDomNodeList&nl){
+       QList<QDomNode>ret;
+       for(int i=0;i<nl.size();i++)ret<<nl.at(i);
        return ret;
 }
 
-QString MOdtRendererPrivate::renderLine(QString line,QString loop,int lpos)
+QList<QDomNode> MOdtRendererPrivate::render(QDomNode node)
 {
-       QString ret,vname;
-       bool isvar=false;
-       static QString vc="ABCDEFGHIJKLMNOPQRSTUVWXYZ:+-0123456789$#";
-       //check for conditionals
-       if(line.trimmed().startsWith("#IF:")){
-               QString stmt=line.trimmed().mid(4).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 "";
-               }
-               qDebug("???????????????? If(%lli %s %lli) evaluates to: %s",op1,stl[1].toAscii().data(),op2,iftrue?"true":"false");
-               return "";
-       }else
-       if(line.trimmed()=="#ELSE"){
-               iftrue=!iftrue;
-               return "";
-       }else
-       if(line.trimmed()=="#ENDIF"){
-               inif=false;
-               return "";
+       //trivial cases
+       if(node.isComment()||node.isDocumentType()||node.isNotation()||node.isProcessingInstruction()){
+               qDebug()<<"trivial type"<<(int)node.nodeType()<<node.nodeName();
+               return QList<QDomNode>()<<node.cloneNode();
        }
-       //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
-               QString stmt=line.trimmed().mid(6).trimmed();
-               qDebug("????????????????Calculation: %s",stmt.toAscii().data());
-               //split out var name
-               int p=stmt.indexOf(':');
-               if(p<1)return "";
-               QString var=stmt.left(p).trimmed();
-               //get list of statement tokens
-               QStringList stl=stmt.mid(p+1).trimmed().split(" ");
-               //go through
-               qint64 res=intToken(stl[0],loop,lpos);
-//             qDebug("??????????CalcInit: %lli",res);
-               for(int i=1;i<stl.size();i+=2){
-                       if((i+1)>=stl.size()){
-                               setLocalVarError(var);
-                               qDebug("??????????CalcError: missing last operand");
-                               return "";
+       //buffer for sub-nodes
+       QDomNodeList nl=node.childNodes();
+       //handle the document itself
+       if(node.isDocument()){
+               QDomDocument doc=node.cloneNode(false).toDocument();
+               foreach(QDomNode nd,n2q(nl))
+                       foreach(QDomNode rnd,render(nd)){
+                               if(doc.appendChild(rnd).isNull())
+                                       qDebug()<<"!!!!!!!! Error: document appending node type"<<(int)rnd.nodeType()<<rnd.nodeName()<<(rnd.isNull()?"is null":"not null")<<" while doc"<<(doc.isNull()?"is null":"not null");
                        }
-                       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 "";
+               return QList<QDomNode>()<<doc;
+       }
+       //handle elements - with special routines
+       if(node.isElement()){
+               QDomElement el=node.toElement();
+               //handle special commands
+               QStringList tnl=el.tagName().split(":");
+               if(tnl.value(0)==OdfTemplatePrefix){
+                       QList<QDomNode>ret;
+                       if(tnl.value(1)=="if"){
+//                             qDebug()<<"????????it's a bit iffy"<<el.attribute("select");
+                               QVariant res=calc->evaluate(el.attribute("select"));
+                               if(!res.canConvert<bool>()){
+                                       qDebug()<<"!!!!!!!! ODF Engine error: if has been called with instructions that do not convert to bool"<<el.attribute("select");
+                                       qDebug()<<"         Skipping this statement altogether.";
+                                       return ret;
                                }
-                       }else
-                       if(stl[i]=="%"){
-                               if(op2!=0)res%=op2;
-                               else{
-                                       qDebug("??????????CalcError: modulo operand %s is zero",stl[i+1].toAscii().data());
-                                       return "";
+                               bool istrue=res.toBool();
+                               foreach(QDomNode nd,n2q(nl)){
+                                       if(!nd.isElement())continue;
+                                       QDomElement el2=nd.toElement();
+                                       if(el2.tagName()==(OdfTemplatePrefix+":else"))istrue=!istrue;
+                                       if(istrue)ret<<render(el2);
                                }
-                       }else {
-                               setLocalVarError(var);
-                               qDebug("??????????CalcError: unknown operator %s",stl[i].toAscii().data());
-                               return "";
-                       }
+                       }else if(tnl.value(1)=="else"){
+                               qDebug()<<"!!!!!!!! Unexpected <else/> tag found, ignoring it.";
+                       }else if(tnl.value(1)=="calculate"){
+//                             qDebug()<<"????????calculatin'"<<el.attribute("exec");
+                               QString form=el.attribute("exec");
+                               QVariant res=calc->evaluate(form);
+                               qDebug()<<"!!!!!!!! ODF Engine Calculation"<<form<<"yields"<<res;
+                       }else if(tnl.value(1)=="loop"){
+                               QString lvn=el.attribute("variable").trimmed();
+                               int max=parent->getLoopIterations(lvn);
+                               qDebug()<<"!!!!!!!! entering loop"<<lvn<<"with"<<max<<"iterations";
+                               //iterate
+                               for(int i=0;i<max;i++){
+                                       parent->setLoopIteration(lvn,i);
+                                       foreach(QDomNode nd,n2q(nl))
+                                               if(nd.isElement())
+                                                       ret<<render(nd);
+                               }
+                               //end of loop
+                               qDebug()<<"!!!!!!!! leaving loop"<<lvn;
+                       }else if(tnl.value(1)=="template"){
+//                             qDebug()<<"template found... processing...";
+                               for(int i=0;i<nl.size();i++){
+                                       if(!nl.at(i).isElement())continue;
+                                       ret<<render(nl.at(i));
+                               }
+                       }else
+                               qDebug()<<"!!!!!!!!! Unknown special tag found, ignoring it:"<<el.tagName();
+                       return ret;
                }
-               qDebug("????????????????CalcResult: %s <= %lli",var.toAscii().data(),res);
-               setLocalVar(var,res);
-               return "";
+               //handle all others
+               QDomElement ret=el.cloneNode(false).toElement();
+//             qDebug()<<"normal tag"<<el.tagName()<<ret.isNull();
+               for(int i=0;i<nl.size();i++)
+                       foreach(QDomNode nd,render(nl.at(i))){
+//                             qDebug()<<"appending to normal tag tyope"<<(int)nd.nodeType()<<nd.nodeName()<<"is null?"<<ret.isNull();
+                               if(ret.appendChild(nd).isNull())
+                                       qDebug()<<"!!!!!!!! Error appending normal tag"<<nd.nodeName()<<(nd.isNull()?"is null":"not null")<<" to normal tag"<<ret.nodeName()<<(ret.isNull()?"is null":"not null");
+                       }
+               return QList<QDomNode>()<<ret;
        }
+       //text
+       if(node.isText()||node.isCDATASection()){
+               QString line=renderString(node.nodeValue());
+               QList<QDomNode>ret;
+               if(node.isText())
+                       ret<<node.ownerDocument().createTextNode(line);
+               else if(node.isCDATASection())
+                       ret<<node.ownerDocument().createCDATASection(line);
+               return ret;
+       }
+       //fallback
+       qDebug()<<"!! ODF renderer, hmm why didn't I catch node type"<<(int)node.nodeType()<<"with name"<<node.nodeName();
+       return QList<QDomNode>()<<node.cloneNode();
+}
+
+QString MOdtRendererPrivate::renderString(QString line)
+{
        //scan characters
-       for(int i=0;i<line.size();i++){
+       bool isvar=false;
+       QString vname,ret;
+       foreach(QChar c,line){
                //are we currently inside a variable name?
                if(isvar){
                        //end of var?
-                       if(line[i]=='@'){
-                               if(vname==""){
+                       if(c=='@'){
+                               if(vname.size()>0)
+                                       ret+=calc->evaluate(vname).toString();
+                               else
                                        ret+="@";
-                               }else{
-                                       QStringList vl=vname.split(":");
-                                       if(vl.size()>2){
-                                               //this was a mistake, reset
-                                               ret+="@";
-                                               ret+=vname+"@";
-                                       }else
-                                       if(vl.size()==2){
-                                               //this is a loop variable, 
-                                               //check that it is the right loop
-                                               //or any loop at all...
-                                               if(loop!="" && (loop==vl[0] || ("$"+loop)==vl[0])){
-                                                       //get value
-                                                       ret+=xmlize(getLoopVariable(vl[0],lpos,vl[1]).trimmed(),newline);
-                                               }
-                                       }else
-                                               //this is a normal variable, get valie
-                                               ret+=xmlize(getVariable(vname).trimmed(),newline);
-                               }
                                //reset mode
                                isvar=false;
                                vname="";
                        }else
-                       //continuation of var?
-                       if(vc.contains(line[i])){
-                               //valid var-name-letter, add
-                               vname+=line[i];
-                       }else{//not a valid var-name-letter
-                               //reset
-                               isvar=false;
-                               ret+="@";
-                               ret+=vname;
-                               vname="";
-                       }
+                       //continuation of var
+                       vname+=c;
                }else{//not inside variable name
                        //is this the start of a var?
-                       if(line[i]=='@'){
+                       if(c=='@'){
                                isvar=true;
                                vname="";
                        }else{
-                               ret+=line[i];
+                               ret+=c;
                        }
                }
        }
@@ -425,7 +387,7 @@ QString MOdtRendererPrivate::renderLine(QString line,QString loop,int lpos)
                ret+="@"+vname;
        }
        //return transformed line
-       return ret + "\n";
+       return ret;
 }
 
 QByteArray MOdtRenderer::convertV1toV2(const QByteArray& old)
@@ -499,155 +461,6 @@ QByteArray MOdtRenderer::convertV1toV2(const QByteArray& old)
        return nba;
 }
 
-static inline QString formatVar(QVariant r,MOdtRenderer::VarType tp,bool loc,int offset)
-{
-       switch(tp){
-               case MOdtRenderer::StringVar:
-                       return r.toString();
-               case MOdtRenderer::IntVar:
-                       return QString::number(r.toInt()+offset);
-               case MOdtRenderer::MoneyVar:
-                       return cent2str(r.toInt()+offset,loc);
-               case MOdtRenderer::DateVar:
-                       return unix2date(r.toInt()+offset,loc);
-               case MOdtRenderer::TimeVar:
-                       return unix2time(r.toInt()+offset,loc);
-               case MOdtRenderer::DateTimeVar:
-                       return unix2dateTime(r.toInt()+offset,loc);
-       }
-       return "";
-}
-
-QString MOdtRendererPrivate::getVariable(QString varname)
-{
-       //split out calculation
-       int offset=0;
-       int p=varname.indexOf('+');
-       if(p>0){
-               offset=varname.mid(p+1).toInt();
-               varname=varname.left(p);
-       }
-       p=varname.indexOf('-');
-       if(p>0){
-               offset=varname.mid(p).toInt();
-               varname=varname.left(p);
-       }
-       //split out $-sign
-       bool localize=true;
-       if(varname[0]=='$'){
-               localize=false;
-               varname=varname.mid(1);
-       }
-       //get variable
-       MOdtRenderer::VarType tp=MOdtRenderer::StringVar;
-       QVariant r;
-       if(varname=="TODAY"){
-               r=QDateTime::currentDateTime().toTime_t();
-               tp=MOdtRenderer::DateVar;
-       }else if(varname=="NOW"){
-               r=QDateTime::currentDateTime().toTime_t();
-               tp=MOdtRenderer::TimeVar;
-       }else if(varname[0]=='#'){
-               if(localvars.contains(varname.mid(1))){
-                       r=localvars[varname.mid(1)].value;
-                       tp=localvars[varname.mid(1)].type;
-               }
-       }else{
-               r=parent->getVariable(varname,tp);
-       }
-       return formatVar(r,tp,localize,offset);
-}
-
-QString MOdtRendererPrivate::getLoopVariable(QString loopname,int iteration,QString varname)
-{
-       //split out calculation
-       int offset=0;
-       int p=varname.indexOf('+');
-       if(p>0){
-               offset=varname.mid(p+1).toInt();
-               varname=varname.left(p);
-       }
-       p=varname.indexOf('-');
-       if(p>0){
-               offset=varname.mid(p).toInt();
-               varname=varname.left(p);
-       }
-       //split out $-sign
-       bool localize=true;
-       if(loopname[0]=='$'){
-               localize=false;
-               loopname=loopname.mid(1);
-       }
-       qDebug("!!!!!!!!!!getting loop var '%s' : '%s' localized=%s offset=%i",loopname.toAscii().data(),varname.toAscii().data(),(localize?"yes":"no"),offset);
-       //get variable
-       MOdtRenderer::VarType tp=MOdtRenderer::StringVar;
-       QVariant r;
-       if(varname=="ITERATION"){
-               r=iteration;
-               tp=MOdtRenderer::IntVar;
-       }else
-               r=parent->getLoopVariable(loopname,iteration,varname,tp);
-       return formatVar(r,tp,localize,offset);
-}
-
-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){
-               //local var?
-               if(vnl[0][0]=='#'){
-                       if(localvars.contains(vnl[0].mid(1)))
-                               return localvars[vnl[0].mid(1)].value.toLongLong();
-                       return 0;
-               }
-               //special var?
-               if(vname=="TODAY" || vname=="NOW")
-                       return QDateTime::currentDateTime().toTime_t();
-               //get from parent
-               MOdtRenderer::VarType tp;
-               return parent->getVariable(vnl[0],tp).toLongLong();
-       }else{
-               //correct loop?
-               if(vnl[0]!=loop)return 0;
-               //iteration?
-               if(vnl[1]=="ITERATION")return lpos;
-               //get from parent
-               MOdtRenderer::VarType tp;
-               return parent->getLoopVariable(loop,lpos,vnl[1],tp).toLongLong();
-       }
-}
-
-void MOdtRendererPrivate::setLocalVar(QString vn,qint64 va)
-{
-       //split vname/type
-       QStringList vnl=vn.split("/");
-       MOdtRenderer::VarType tp=MOdtRenderer::IntVar;
-       if(vnl.size()>1){
-               if(vnl[1]=="MONEY")tp=MOdtRenderer::MoneyVar;else
-               if(vnl[1]=="DATE")tp=MOdtRenderer::DateVar;else
-               if(vnl[1]=="TIME")tp=MOdtRenderer::TimeVar;else
-               if(vnl[1]=="DATETIME")tp=MOdtRenderer::DateTimeVar;
-       }
-       //store
-       LocalVar lv;
-       lv.type=tp;
-       lv.value=va;
-       localvars.insert(vnl[0],lv);
-}
-
-void MOdtRendererPrivate::setLocalVarError(QString vn)
-{
-       QStringList vnl=vn.split("/");
-       LocalVar lv;
-       lv.type=MOdtRenderer::StringVar;
-       lv.value="error";
-       localvars.insert(vnl[0],lv);
-}
 
 /********************************************************************/
 
@@ -658,25 +471,16 @@ MOdtSignalRenderer::MOdtSignalRenderer(MTemplate file)
 
 MOdtSignalRenderer::~MOdtSignalRenderer(){}
 
-QVariant MOdtSignalRenderer::getVariable(QString varname,MOdtRenderer::VarType&av)
+QVariant MOdtSignalRenderer::getVariable(QString varname)
 {
        QVariant ret;
-       av=MOdtRenderer::StringVar;
-       emit getVariable(varname,av,ret);
+       emit getVariable(varname,ret);
        return ret;
 }
 
 int MOdtSignalRenderer::getLoopIterations(QString loopname)
 {
-       int ret=0;
+       int ret=-1;
        emit getLoopIterations(loopname,ret);
        return ret;
 }
-
-QVariant MOdtSignalRenderer::getLoopVariable(QString loopname,int iteration,QString varname,MOdtRenderer::VarType&av)
-{
-       QVariant ret="notfound";
-       av=MOdtRenderer::StringVar;
-       emit getLoopVariable(loopname,iteration,varname,av,ret);
-       return ret;
-}
index dc17e42..ef19414 100644 (file)
@@ -22,6 +22,7 @@ class MOdtRendererPrivate;
 class QFile;
 
 extern const QString OdfTemplateNS;
+extern const QString OdfTemplatePrefix;
 
 /**abstract base class for all ODT rendering classes*/
 class MOdtRenderer
@@ -41,35 +42,20 @@ class MOdtRenderer
                /**starts the internal rendering routine and outputs to printer (calls OpenOffice to print)*/
                virtual void renderToPrinter();
                
-               /**variable type*/
-               enum VarType{
-                       /**default: uninterpreted string*/
-                       StringVar,
-                       /**simple integer value*/
-                       IntVar,
-                       /**money value*/
-                       MoneyVar,
-                       /**unix timestamp: format as date*/
-                       DateVar,
-                       /**unix timestamp: format as time*/
-                       TimeVar,
-                       /**unix timestamp: format as date+time*/
-                       DateTimeVar
-               };
-               
                ///helper routine: converts a V1 template to V2
                static QByteArray convertV1toV2(const QByteArray&);
                
        protected:
                friend class MOdtRendererPrivate;
+               friend class MOdfEngine;
                /**implement this to return the value of a variable during rendering; should return empty string if the variable does not exist*/
-               virtual QVariant getVariable(QString varname,VarType&)=0;
+               virtual QVariant getVariable(QString varname)=0;
                
                /**implement this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/
                virtual int getLoopIterations(QString loopname)=0;
                
-               /**implement this to return a specific instance of a loop internal variable; should return empty string if the request is not valid*/
-               virtual QVariant getLoopVariable(QString loopname,int iteration,QString varname,VarType&)=0;
+               /**implement this to populate the variables used in a specific iteration of the loop*/
+               virtual void setLoopIteration(QString loopname, int interation)=0;
        private:
                MOdtRendererPrivate*d;
 };
@@ -86,18 +72,16 @@ class MOdtSignalRenderer:public QObject,public MOdtRenderer
        
        signals:
                /**connect this to return the value of a variable during rendering; should return empty string if the variable does not exist*/
-               void getVariable(QString varname,MOdtRenderer::VarType&,QVariant&value);
+               void getVariable(QString varname,QVariant&value);
                
                /**connect this to return the amount of iterations for a defined loop; should return 0 if the loop does not exist*/
                void getLoopIterations(QString loopname,int&iterations);
                
-               /**connect this to return a specific instance of a loop internal variable; should return empty string if the request is not valid*/
-               void getLoopVariable(QString loopname,int iteration,QString varname,MOdtRenderer::VarType&,QVariant&value);
+               void setLoopIteration(QString loopname, int interation);
        
        protected:
-               QVariant getVariable(QString varname,MOdtRenderer::VarType&);
+               QVariant getVariable(QString varname);
                int getLoopIterations(QString loopname);
-               QVariant getLoopVariable(QString loopname,int iteration,QString varname,MOdtRenderer::VarType&);
 };
 
 #endif