-Subproject commit 8eed1dd9716f2db330d915bf6f4c5bff52b5069e
+Subproject commit f0c16272d5ec1cb313175ede04afb135c1472702
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();
}
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();
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);
+ }
}
}
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"){
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;
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;
}
}
}
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;
QList<int>orderids;
QMap<int,MOOrder>orders;
QMap<int,MOCustomerInfo>customers;
+ QMap<QString,int>loopiter;
//get summary
void getSummaryData();
//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();
}
//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
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);
+ }
}
}
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;
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"){
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"){
#include <QDialog>
#include <QMainWindow>
+#include <QMap>
+
#include "odtrender.h"
#include "MOOrder"
/**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();
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{
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
--- /dev/null
+//
+// 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);
+}
--- /dev/null
+//
+// 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
#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)
{
//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);
}
//clear cache
d->mFiles.clear();
- d->mLines.clear();
+ d->mFileName=fn;
//read data
unz.gotoFirstFile();
do{
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()
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)
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();
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());
}
{
Q_OBJECT
DECLARE_DPTR(d);
- friend class MOELabelDelegate;
public:
///instantiates the editor
MOdfEditor(QWidget* parent = 0, Qt::WindowFlags f = 0);
///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
#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
{
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 {
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();
//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;
MOdtRenderer::~MOdtRenderer()
{
+ if(d==nullptr)return;
+ if(d->calc!=nullptr)delete d->calc;
delete d;
d=0;
}
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
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);
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;
}
}
}
ret+="@"+vname;
}
//return transformed line
- return ret + "\n";
+ return ret;
}
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);
-}
/********************************************************************/
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;
-}
class QFile;
extern const QString OdfTemplateNS;
+extern const QString OdfTemplatePrefix;
/**abstract base class for all ODT rendering classes*/
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;
};
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