//
#include "ticketedit.h"
+#include "centbox.h"
+#include "misc.h"
+#include "ticketrender.h"
+
+#include "MOTicket"
#include<QAction>
#include<QBoxLayout>
#include<QComboBox>
+#include<QCoreApplication>
+#include<QDateTimeEdit>
#include<QDomDocument>
#include<QDomElement>
#include<QDoubleSpinBox>
#include<QFileDialog>
#include<QHeaderView>
+#include<QItemDelegate>
#include<QLabel>
+#include<QLineEdit>
#include<QMenu>
#include<QMenuBar>
#include<QMessageBox>
#include<QPointF>
+#include<QSettings>
+#include<QSignalMapper>
#include<QSizeF>
#include<QSplitter>
#include<QStandardItemModel>
#include<QStatusBar>
#include<QTableView>
+#include<QTemporaryFile>
#include<QUnZip>
#include<QZip>
+#define HRECT 1
+#define HFONT 2
+#define HFILE 4
+#define HALIGN 8
+#define HSMOOTH 0x10
+#define HCONTENT 0x20
+
+class MTEExampleDelegate:public QItemDelegate
+{
+ public:
+ MTEExampleDelegate(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 MTENullDelegate:public QItemDelegate
+{
+ public:
+ MTENullDelegate(QObject *parent = 0):QItemDelegate(parent) {}
+ QWidget *createEditor(QWidget *, const QStyleOptionViewItem &,
+ const QModelIndex &) const {return 0;}
+ void setEditorData(QWidget *, const QModelIndex &) const{}
+ void setModelData(QWidget *, QAbstractItemModel *,
+ const QModelIndex &) const {}
+ void updateEditorGeometry(QWidget *,const QStyleOptionViewItem &,
+ const QModelIndex &) const {}
+};
+
class DPTR_CLASS_NAME(MTicketEditor)
{
public:
QString mUnit;
QSizeF mSize;
enum Type{
- Unknown,
- LoadFont,
- Picture,
- Text,
- Barcode
+ Unknown=0,
+ LoadFont=0x100|HFILE,
+ Picture=0x200|HFILE|HRECT|HSMOOTH,
+ Text=0x300|HFONT|HRECT|HALIGN|HCONTENT,
+ Barcode=0x400|HRECT,
};
struct Line_s{
Type type;
QString font;
double fontsize;
Qt::Alignment align;
+ QString content;
};
QList<Line_s>mLines;
//widgets
QDoubleSpinBox*labelwidth,*labelheight;
QComboBox*unitbox;
- QTableView*itemtable,*filetable;
- QStandardItemModel*itemmodel,*filemodel;
- QWidget*labelpicture;
+ QTableView*itemtable,*filetable,*expltable;
+ QStandardItemModel*itemmodel,*filemodel,*explmodel;
+ QWidget*ticketpicture,*voucherpicture;
};
DEFINE_DPTR(MTicketEditor);
m->addSeparator();
m->addAction(tr("&Close"),this,SLOT(close()));
m=mb->addMenu(tr("&Edit"));
- m->addAction(tr("Add Item"));
- m->addAction(tr("Delete Item"));
+ QMenu *aim=m->addMenu(tr("Add Item"));
+ m->addAction(tr("Delete Item"),this,SLOT(delItem()));
m->addSeparator();
- m->addAction(tr("Add File"));
- m->addAction(tr("Delete File"));
+ m->addAction(tr("Add File"),this,SLOT(addFile()));
+ m->addAction(tr("Delete File"),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)));
//central
QSplitter*central=new QSplitter(Qt::Vertical);
central->addWidget(split=new QSplitter);
split->addWidget(d->filetable=new QTableView);
d->filetable->setModel(d->filemodel=new QStandardItemModel(this));
- split->addWidget(d->labelpicture=new QWidget);
d->filetable->horizontalHeader()->show();
d->filetable->verticalHeader()->hide();
+ d->filetable->setItemDelegate(new MTENullDelegate(this));
+ QTabWidget*tab;
+ split->addWidget(tab=new QTabWidget);
+ tab->addTab(d->ticketpicture=new QWidget,tr("As Ticket"));
+ tab->addTab(d->voucherpicture=new QWidget,tr("As Voucher"));
+ tab->addTab(d->expltable=new QTableView,tr("Example Data"));
+ d->expltable->setModel(d->explmodel=new QStandardItemModel(this));
+ d->expltable->setItemDelegate(new MTEExampleDelegate(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 MTicketEditor::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 MTicketEditor::loadFile(QString fn)
{
//try to open the file
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(" ");
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("MTicketEditor","top");
+ case Qt::AlignBottom:
+ return QCoreApplication::translate("MTicketEditor","bottom");
+ case Qt::AlignHCenter:
+ case Qt::AlignVCenter:
+ return QCoreApplication::translate("MTicketEditor","center");
+ case Qt::AlignLeft:
+ return QCoreApplication::translate("MTicketEditor","left");
+ case Qt::AlignRight:
+ return QCoreApplication::translate("MTicketEditor","right");
+ default:
+ return QCoreApplication::translate("MTicketEditor","align (%1)").arg((int)a);
+ }
+}
+
void MTicketEditor::parseTemplate(QByteArray bytes)
{
QDomDocument doc;
QString tn=el.tagName();
Private::Line_s line;
if(tn=="LoadFont")line.type=Private::LoadFont;else
- if(tn=="Picture")line.type=Private::LoadFont;else
- if(tn=="Text")line.type=Private::LoadFont;else
- if(tn=="Barcode")line.type=Private::LoadFont;
+ 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");
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);
}
}
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();
- if(d->itemmodel->columnCount()==0)
- d->itemmodel->insertColumns(0,5);
+ d->itemmodel->insertRows(0,d->mLines.size());
d->itemmodel->setHorizontalHeaderLabels(QStringList()
<<tr("Type")
- <<tr("Size")
<<tr("Offset")
+ <<tr("Size")
<<tr("File/Font")
<<tr("Font Size")
- <<tr("smooth")
+ <<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();
}
void MTicketEditor::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()
+ );
+ }
+ //render ticket
+ MOTicket t;
+ t.setticketid(exdata.value("BARCODE"));
+ t.setprice(str2cent(exdata.value("PRICE")));
+ QTemporaryFile tfile(QDir::tempPath()+"/templateXXXXXX.xtt");
+ tfile.open();
+ saveTemplate(tfile);
+ MTicketRenderer rend(tfile.fileName());
+ rend.render(t,*(d->ticketpicture));
+ //render voucher
+}
+
+void MTicketEditor::saveTemplate(QFile& fd)
+{
+ QZip zip;
+ zip.open(&fd);
+ {QBuffer buf;buf.open(QIODevice::ReadWrite);
+ saveXmlPart(buf);buf.seek(0);
+ zip.storeFile("template.xml",buf);}
+ zip.close();
+ fd.flush();
+}
+
+void MTicketEditor::saveXmlPart(QIODevice& fd)
+{
+
+}
+
+
+void MTicketEditor::addFile()
+{
+
+}
+
+void MTicketEditor::delFile()
+{
+
+}
+
+void MTicketEditor::addItem(int )
+{
+
+}
+
+void MTicketEditor::delItem()
+{
}