From 542b3952af2eb4663617e40e21fb892a7ed10187 Mon Sep 17 00:00:00 2001 From: Konrad Rosenbaum Date: Sun, 5 Feb 2012 21:44:09 +0100 Subject: [PATCH] ODT rendering from XML - new template format --- elam | 2 +- src/dialogs/eventsummary.cpp | 54 ++-- src/dialogs/eventsummary.h | 6 +- src/dialogs/orderwin.cpp | 59 ++-- src/dialogs/orderwin.h | 9 +- src/misc/misc.pri | 28 +- src/misc/msengine.cpp | 71 ++++ src/misc/msengine.h | 28 ++ src/templates/odfedit.cpp | 725 ++--------------------------------------- src/templates/odfedit.h | 34 -- src/templates/odtrender.cpp | 528 ++++++++++--------------------- src/templates/odtrender.h | 32 +-- 12 files changed, 384 insertions(+), 1192 deletions(-) create mode 100644 src/misc/msengine.cpp create mode 100644 src/misc/msengine.h diff --git a/elam b/elam index 8eed1dd..f0c1627 160000 --- a/elam +++ b/elam @@ -1 +1 @@ -Subproject commit 8eed1dd9716f2db330d915bf6f4c5bff52b5069e +Subproject commit f0c16272d5ec1cb313175ede04afb135c1472702 diff --git a/src/dialogs/eventsummary.cpp b/src/dialogs/eventsummary.cpp index d30ddeb..be77d22 100644 --- a/src/dialogs/eventsummary.cpp +++ b/src/dialogs/eventsummary.cpp @@ -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=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{ QListticks=orders[oid].tickets(); QListeticks; @@ -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;iorderids; QMaporders; QMapcustomers; + QMaploopiter; //get summary void getSummaryData(); diff --git a/src/dialogs/orderwin.cpp b/src/dialogs/orderwin.cpp index 82fa970..fe16a96 100644 --- a/src/dialogs/orderwin.cpp +++ b/src/dialogs/orderwin.cpp @@ -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 &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"){ diff --git a/src/dialogs/orderwin.h b/src/dialogs/orderwin.h index 02da7ac..50b7e19 100644 --- a/src/dialogs/orderwin.h +++ b/src/dialogs/orderwin.h @@ -15,6 +15,8 @@ #include #include +#include + #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; + QMapm_loopiter; //printing buffer struct TickInfo{ diff --git a/src/misc/misc.pri b/src/misc/misc.pri index 35bca43..0793c37 100644 --- a/src/misc/misc.pri +++ b/src/misc/misc.pri @@ -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 index 0000000..b8d5425 --- /dev/null +++ b/src/misc/msengine.cpp @@ -0,0 +1,71 @@ +// +// C++ Implementation: MSmoke ELAM Engine +// +// +// Author: Konrad Rosenbaum , (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&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&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&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&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&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 + QPairnc=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 index 0000000..d420b7b --- /dev/null +++ b/src/misc/msengine.h @@ -0,0 +1,28 @@ +// +// C++ Interface: MSmoke Elam Engine with specialized functions +// +// +// Author: Konrad Rosenbaum , (C) 2012 +// +// Copyright: See README/COPYING.GPL files that come with this distribution +// +// + +#ifndef MAGICSMOKE_MSENGINE_H +#define MAGICSMOKE_MSENGINE_H + +#include + +///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 diff --git a/src/templates/odfedit.cpp b/src/templates/odfedit.cpp index faed04e..13da05e 100644 --- a/src/templates/odfedit.cpp +++ b/src/templates/odfedit.cpp @@ -52,57 +52,6 @@ #include #include -#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 - QMapmFiles; - 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){} }; - QListmLines; + QList 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()<explmodel->insertRows(0,ex1.size()); - QSettings set; - set.beginGroup("labeleditor/examples"); - for(int i=0;iexplmodel->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"<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<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;imLines.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;iunitbox->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()<mFiles.keys(); - for(int i=0;imFiles.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() - <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;iaddItem("@"+k[i]); - k=QFontDatabase().families(); - qSort(k); - cb->addItems(k); - for(int i=0;icount();i++) - if(cb->itemText(i)==c) - cb->setCurrentIndex(i); - }else{ - cb->addItems(k); - for(int i=0;isetCurrentIndex(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 -{ - QMapexdata; - public: - MTELabel(QMapdt) - { - 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() -{ - QMapexdata; - for(int i=0;iexplmodel->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;izfi;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;imFiles.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;imLines.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()); } diff --git a/src/templates/odfedit.h b/src/templates/odfedit.h index f7c9d1c..4688e44 100644 --- a/src/templates/odfedit.h +++ b/src/templates/odfedit.h @@ -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 diff --git a/src/templates/odtrender.cpp b/src/templates/odtrender.cpp index 7938cf2..086c359 100644 --- a/src/templates/odtrender.cpp +++ b/src/templates/odtrender.cpp @@ -23,9 +23,33 @@ #include #include -#include "QUnZip" -#include "QZip" +#include +#include +#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 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; - }; - QMaplocalvars; + //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 ="<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;igetLoopIterations(lname); - //render the loop... - for(int j=0;j n2q(const QDomNodeList&nl){ + QListret; + for(int i=0;i 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")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()<()<=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()< '%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()<ret; + if(tnl.value(1)=="if"){ +// qDebug()<<"????????it's a bit iffy"<evaluate(el.attribute("select")); + if(!res.canConvert()){ + qDebug()<<"!!!!!!!! ODF Engine error: if has been called with instructions that do not convert to bool"< tag found, ignoring it."; + }else if(tnl.value(1)=="calculate"){ +// qDebug()<<"????????calculatin'"<evaluate(form); + qDebug()<<"!!!!!!!! ODF Engine Calculation"<getLoopIterations(lvn); + qDebug()<<"!!!!!!!! entering loop"<setLoopIteration(lvn,i); + foreach(QDomNode nd,n2q(nl)) + if(nd.isElement()) + ret<()<ret; + if(node.isText()) + ret<()<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; -} diff --git a/src/templates/odtrender.h b/src/templates/odtrender.h index dc17e42..ef19414 100644 --- a/src/templates/odtrender.h +++ b/src/templates/odtrender.h @@ -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 -- 1.7.2.5