* overview for orders
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 24 Mar 2008 19:27:03 +0000 (19:27 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 24 Mar 2008 19:27:03 +0000 (19:27 +0000)
* ticket class
* ticket rendering
* finalized template handling
* fixed code-39 generation
* added draft of a bill template

git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@140 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

26 files changed:
doc/prog_protocol.html
doc/prog_tickettemplate.html
examples/bill.odt [new file with mode: 0644]
examples/ticket.xtt
src/code39.cpp
src/code39.h
src/event.cpp
src/event.h
src/eventsummary.cpp
src/mainwindow.cpp
src/order.cpp
src/order.h
src/orderwin.cpp [new file with mode: 0644]
src/orderwin.h [new file with mode: 0644]
src/overview.cpp
src/overview.h
src/smoke.pro
src/smoke_de.ts
src/smoke_de_SAX.ts
src/ticketrender.cpp [new file with mode: 0644]
src/ticketrender.h [new file with mode: 0644]
src/webrequest.cpp
src/webrequest.h
www/inc/classes/order.php
www/inc/machine/template.php
www/machine.php

index 2109eb4..6469b99 100644 (file)
@@ -573,6 +573,6 @@ The Hash is caculated at the server side and can be used to find out whether the
 
 The <tt>gettemplate</tt> transaction returns a specific template. The request contains only the file name, the response contains the template file as content. In case of an error the content is left empty and the status code is set appropriately.
 
-</h3>Setting a Template</h3>
+<h3>Setting a Template</h3>
 
 The <tt>settemplate</tt> transaction creates a new template file. The request contains the file name terminated with a newline ("\n") and then the binary content of the template - it is important that there are no additional characters between the newline and the template content. The response contains the new hash of the template or error details.
\ No newline at end of file
index dfdbcf0..e691887 100644 (file)
@@ -17,9 +17,8 @@ The <tt>template.xml</tt> file describes the painting operations that form the t
 &lt;TicketTemplate unit="mm|in|px" size="11 22">
   &lt;LoadFont file="nameInsideArchive.ttf"/>
   &lt;Picture file="nameInsideArchive.png" size="11 22" offset="33 44" smooth="1"/>
-  &lt;Text font="fontFamilyName" embeddedFont="fontFamilyName" fontsize="sizeInPt"
-      offset="11 22" align="left|right|center" valign="top|bottom|center"
-      >some string with @VARIABLES@ to print&lt;/Text>
+  &lt;Text font="fontFamilyName" fontsize="sizeInPt" offset="11 22" size="33 44" align="left|right|center"
+     valign="top|bottom|center" >some string with @VARIABLES@ to print&lt;/Text>
   &lt;Barcode offset="11 22" size="33 44"/>
   ...
 &lt;/TicketTemplate>
@@ -38,13 +37,12 @@ The elements are:
 The attributes are
 <table frame="1" border="1">
 <tr><td><b>Attribute</b></td><td><b>Description</b></td></tr>
-<tr><td>unit</td><td>describes in what unit sizes and offsets are described in the template, possible values are "mm" (Millimeter), "in" (Inches), "px" (Pixels), the default is "mm". Except for "px" all of them are allowed to use fractions.</td></tr>
+<tr><td>unit</td><td>describes in what unit sizes and offsets are described in the template, possible values are "mm" (Millimeter), "in" (Inches); the default is "mm". All of them are allowed to use fractions.</td></tr>
 <tr><td>size</td><td>describes the size the element is scaled to (or in the case of the complete ticket: its total size), it is two positive numbers separated by a space: "width height"</td></tr>
-<tr><td>offset</td><td>describes the position of the element as "X Y" coordinates. Positive numbers describe the distance from the upper left corner, negative numbers the distance from the lower right corner.</td></tr>
+<tr><td>offset</td><td>describes the position of the element as "X Y" coordinates. They describe the distance from the upper left corner.</td></tr>
 <tr><td>file</td><td>a relative file name within the template ZIP file</td></tr>
 <tr><td>smooth</td><td>for Pictures: describes whether the scaling should be done using edged (0) or smooth (1) scaling</td></tr>
 <tr><td>font</td><td>contains the name of a font family that is used for rendering the text (eg. "Helvetica"), the font is searched in the complete font database of the host</td></tr>
-<tr><td>embeddedFont</td><td>contains the name of a font family that is used for rendering the text, it is searched in the dynmically loaded fonts that are embedded in the template ZIP file; if font and embeddedFont are present, embeddedFont takes precedence</td></tr>
 <tr><td>fontsize</td><td>the height of the text to render in pt (default is 10)</td></tr>
 <tr><td>align</td><td>horizontal alignment of the text: "left" starts the text at its offset, "right" places the text left of its offset, "center" puts the horizontal center of the text on the offset</td></tr>
 <tr><td>valign</td><td>vertical alignment of the text: "top" puts the text below its offset, "bottom" places the text above of its offset, "center" puts the vertical center of the text on the offset</td></tr>
diff --git a/examples/bill.odt b/examples/bill.odt
new file mode 100644 (file)
index 0000000..2d79f00
Binary files /dev/null and b/examples/bill.odt differ
index 8744b4a..be0929d 100644 (file)
Binary files a/examples/ticket.xtt and b/examples/ticket.xtt differ
index a4eb35c..e292b5b 100644 (file)
@@ -54,7 +54,7 @@ static QMap<char,QString> initmap()
        map.insert('K',"0001010101110001");
        map.insert('L',"0100010101110001");
        map.insert('M',"0001000101011101");
-       map.insert('0',"0101000101110001");
+       map.insert('N',"0101000101110001");
        map.insert('O',"0001010001011101");
        map.insert('P',"0100010001011101");
        map.insert('Q',"0101010001110001");
@@ -81,12 +81,15 @@ static char code39mod(QString str)
        return c39mod[sum%43].toAscii();
 }
 
-QPixmap code39(QString str)
+QImage code39(QString str)
 {
        //check string, return empty pixmap if invalid
        str=str.toUpper();
        for(int i=0;i<str.size();i++){
-               if(!c39mod.contains(str[i]))return QPixmap();
+               if(!c39mod.contains(str[i])){
+                       qDebug("Warning: invalid barcode requested: %s.",str.toAscii().data());
+                       return QImage();
+               }
        }
        //create 01-list
        QString rstr=c39map['*'];
@@ -94,14 +97,15 @@ QPixmap code39(QString str)
                rstr+=c39map[str[i].toAscii()];
        rstr+=c39map[code39mod(str)];
        rstr+=c39map['*'];
+       qDebug("Code-39, encoding: %s -> %c",str.toAscii().data(),code39mod(str));
+       //define xpm
+       char *xpm[4];
+       QByteArray xpmsz=QString().sprintf("%i 1 2 1",rstr.size()).toAscii();
+       xpm[0]=xpmsz.data();
+       xpm[1]="0\tg #000000";
+       xpm[2]="1\tg #FFFFFF";
+       QByteArray xpmc=rstr.toAscii();
+       xpm[3]=xpmc.data();
        //create pixmap
-       QPixmap pix(str.size()*16,1);
-       QPainter dev(&pix);
-       dev.setPen(Qt::black);
-       //paint
-       pix.fill(Qt::white);
-       for(int i=0;i<rstr.size();i++)
-               if(rstr[i]=='0')
-                       dev.drawPoint(i,0);
-       return pix;
+       return QImage(xpm);
 }
index fcf0888..549a738 100644 (file)
 //
 //
 
-#include <QPixmap>
+#include <QImage>
 #include <QString>
 
 /**Takes a string and converts it into a code-39 bar code.
 Code-39 allows letters (case-insensitive), digits, spaces and the special chars "-.$/+%".
 The bar code pixmap will be 1 pixel high and 16 pixels wide for each character (plus start/stop character and checksum character) - it needs to be scaled up to fit the intended size.*/
-QPixmap code39(QString);
+QImage code39(QString);
index 6c71acd..05abff0 100644 (file)
@@ -24,6 +24,14 @@ MEvent::MEvent(MWebRequest*r,int id)
        refresh();
 }
 
+MEvent::MEvent()
+{
+       req=0;
+       eventid=-1;
+       m_starttime=m_endtime=m_capacity=m_defaultprice=0;
+       m_valid=m_complete=false;
+}
+
 MEvent::MEvent(MWebRequest*r,QDomElement&el)
 {
        req=r;
@@ -41,6 +49,29 @@ MEvent::MEvent(MWebRequest*r,QDomElement&el)
        else initFromElement(el);
 }
 
+MEvent::MEvent(const MEvent&e)
+{
+       operator=(e);
+}
+
+MEvent& MEvent::operator=(const MEvent&e)
+{
+       req=e.req;
+       eventid=e.eventid;
+       m_title=e.m_title;
+       m_artist=e.m_artist;
+       m_description=e.m_description;
+       m_starttime=e.m_starttime;
+       m_endtime=e.m_endtime;
+       m_roomid=e.m_roomid;
+       m_capacity=e.m_capacity;
+       m_defaultprice=e.m_defaultprice;
+       m_cancelreason=e.m_cancelreason;
+       m_valid=e.m_valid;
+       m_complete=e.m_complete;
+       return *this;
+}
+
 void MEvent::refresh()
 {
        m_starttime=QDateTime::currentDateTime().toTime_t();
@@ -218,4 +249,14 @@ void MEvent::setPrice(QString str)
        if(ps.size()>=1)prc=ps[0].toInt()*100;
        if(ps.size()>=2)prc+=ps[1].toInt();
        m_defaultprice=prc;
-}
\ No newline at end of file
+}
+
+QString MEvent::startTimeString()const
+{
+        return QDateTime::fromTime_t(m_starttime).toString(QCoreApplication::translate("MEvent","yyyy-MM-dd hh:mm ap","date/time format"));
+}
+
+QString MEvent::endTimeString()const
+{
+        return QDateTime::fromTime_t(m_endtime).toString(QCoreApplication::translate("MEvent","yyyy-MM-dd hh:mm ap","date/time format"));
+}
index 19ef9d6..2d3dea6 100644 (file)
@@ -22,13 +22,20 @@ class QDomElement;
 class MEvent
 {
        public:
+               /**creates an invalid event*/
+               MEvent();
                /**creates an event by ID, the constructor asks the server/database for details*/
                MEvent(MWebRequest*,int);
                /**creates an event via a DOM-element, used by WebRequest::getAllEvents*/
                MEvent(MWebRequest*,QDomElement&);
+               /**copies an event*/
+               MEvent(const MEvent&);
                /**destructs an event*/
                ~MEvent();
                
+               /**copies the event*/
+               MEvent& operator=(const MEvent&);
+               
                /**updates data from the database, can be used to upgrade an incomplete event to a complete one*/
                void refresh();
                
@@ -48,6 +55,10 @@ class MEvent
                int startTime()const{return m_starttime;}
                /**returns the end time of the event as Unix timestamp*/
                int endTime()const{return m_endtime;}
+               /**returns the start time of the event as localized string*/
+               QString startTimeString()const;
+               /**returns the end time of the event as localized string*/
+               QString endTimeString()const;
                /**returns the room of the event, the room must be one out of the list of valid rooms*/
                QString room()const{return m_roomid;}
                /**returns the amount of tickets than can be sold for this event, initially this should be a copy of the rooms capacity*/
index 0a9acdb..0869e71 100644 (file)
@@ -23,6 +23,7 @@
 #include <QBoxLayout>
 #include <QGridLayout>
 #include <QFileDialog>
+#include <QMessageBox>
 
 MEventSummary::MEventSummary(QWidget*par,MWebRequest*rq,int eid)
        :QDialog(par)
@@ -139,7 +140,12 @@ void MEventSummary::getSummaryData()
 
 void MEventSummary::print()
 {
-       MOdtSignalRenderer rend("../examples/eventsummary.odtt");
+       QString tf=req->getTemplate("eventsummary.odtt");
+       if(tf==""){
+               QMessageBox::warning(this,tr("Warning"),tr("Unable to get template file (eventsummary.odtt). Giving up."));
+               return;
+       }
+       MOdtSignalRenderer rend(tf);
        connect(&rend,SIGNAL(getVariable(QString,QString&)),this,SLOT(getVariable(QString,QString&)));
        connect(&rend,SIGNAL(getLoopIterations(QString,int&)),this,SLOT(getLoopIterations(QString,int&)));
        connect(&rend,SIGNAL(getLoopVariable(QString,int,QString,QString&)),this,SLOT(getLoopVariable(QString,int,QString,QString&)));
index 6495198..778dd8b 100644 (file)
@@ -199,7 +199,7 @@ void MMainWindow::startLogin()
        //make it impossible for the user to interfere
        setEnabled(false);
        //create request object
-       MWebRequest *mw=new MWebRequest;
+       MWebRequest *mw=new MWebRequest(profiles->itemData(profiles->currentIndex()).toString());
        mw->setUrl(serverurl->text());
        if(useproxy->isChecked())
                mw->setProxy(proxyname->text(),proxyport->value(),proxyuser->text(),proxypass->text());
index 68ec1d2..6779cf9 100644 (file)
@@ -20,8 +20,9 @@ MOrder::MOrder()
 {
        req=0;
        m_orderid=m_customer=-1;
-       m_price=m_paid=0;
+       m_price=m_paid=m_otime=m_stime=0;
        m_status=Invalid;
+       m_complete=false;
 }
 
 MOrder::MOrder(MWebRequest*r,qint32 id)
@@ -30,7 +31,7 @@ MOrder::MOrder(MWebRequest*r,qint32 id)
        getFromDB(id);
 }
 
-MOrder::MOrder(MWebRequest*r,QDomElement&e)
+MOrder::MOrder(MWebRequest*r,const QDomElement&e)
 {
        req=r;
        parseXml(e);
@@ -38,12 +39,25 @@ MOrder::MOrder(MWebRequest*r,QDomElement&e)
 
 MOrder::MOrder(const MOrder&o)
 {
+       operator=(o);
+}
+
+MOrder& MOrder::operator=(const MOrder&o)
+{
        req=o.req;
        m_orderid=o.m_orderid;
        m_customer=o.m_customer;
        m_price=o.m_price;
        m_paid=o.m_paid;
        m_status=o.m_status;
+       m_otime=o.m_otime;
+       m_stime=o.m_stime;
+       m_complete=o.m_complete;
+       m_tickets=o.m_tickets;
+       m_seller=o.m_seller;
+       m_deladdress=o.m_deladdress;
+       m_comment=o.m_comment;
+       return *this;
 }
 
 int MOrder::orderID()const
@@ -53,7 +67,7 @@ int MOrder::orderID()const
 
 bool MOrder::isValid()const
 {
-       return m_orderid>=0 && m_status!=Invalid;
+       return m_status!=Invalid;
 }
 
 int MOrder::customerID()const
@@ -78,6 +92,10 @@ QString MOrder::orderStatusString()const
                case Sent:return QCoreApplication::translate("MOrder","sent","state");
                case Cancelled:return QCoreApplication::translate("MOrder","cancelled","state");
                case Closed:return QCoreApplication::translate("MOrder","closed","state");
+               case CheckOk:return QCoreApplication::translate("MOrder","check: ok","state");
+               case CheckSaleOnly:return QCoreApplication::translate("MOrder","check: sale only","state");
+               case CheckOrderOnly:return QCoreApplication::translate("MOrder","check: order only","state");
+               case CheckFail:return QCoreApplication::translate("MOrder","check: failed","state");
                default:return QCoreApplication::translate("MOrder","invalid","state");
        }
 }
@@ -143,17 +161,35 @@ int MOrder::amountToRefund()const
 
 bool MOrder::isSent()const
 {
-       //only in placed mode there is a need for action, hence in all other modes we assum sent
+       //only in placed mode there is a need for action, hence in all other modes we assume sent
        return m_status!=Placed;
 }
 
 void MOrder::getFromDB(qint32 i)
 {
-       //TODO
+       if(!req)return;
+       if(i<0)return;
+       //request
+       if(!req->request("getorder",QByteArray::number(i)))return;
+       if(req->responseStatus()!=MWebRequest::Ok)return;
+       //parse
+       QDomDocument doc;
+       if(!doc.setContent(req->responseBody())){
+               qDebug("Unable to parse response to getorder request.");
+               return;
+       }
+       parseXml(doc.documentElement());
 }
 
 void MOrder::parseXml(const QDomElement&e)
 {
+       //reset
+       m_complete=false;
+       m_otime=m_stime=0;
+       m_seller="";
+       m_deladdress="";
+       m_comment="";
+       m_tickets.clear();
        //Basics
        bool b;
        m_orderid=e.attribute("id","-1").toInt(&b);
@@ -171,6 +207,244 @@ void MOrder::parseXml(const QDomElement&e)
        if(st=="placed")m_status=Placed;else
        if(st=="sent")m_status=Sent;else
        if(st=="cancelled")m_status=Cancelled;else
-       if(st=="closed")m_status=Closed;
+       if(st=="closed")m_status=Closed;else
+       if(st=="ok")m_status=CheckOk;else
+       if(st=="saleonly")m_status=CheckSaleOnly;else
+       if(st=="orderonly")m_status=CheckOrderOnly;else
+       if(st=="fail")m_status=CheckFail;
        else m_status=Invalid;
+       //complete stuff
+       if(!e.hasAttribute("seller"))return;
+       m_complete=true;
+       m_otime=e.attribute("ordertime","0").toInt();
+       m_stime=e.attribute("senttime","0").toInt();
+       m_seller=e.attribute("seller");
+       QDomNodeList nl=e.elementsByTagName("DeliveryAddress");
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               m_deladdress=el.text();
+       }
+       nl=e.elementsByTagName("Comment");
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               m_comment=el.text();
+       }
+       nl=e.elementsByTagName("Ticket");
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               MTicket tick(req,el);
+               if(tick.isValid()){
+                       tick.setOrderID(m_orderid);
+                       m_tickets.append(tick);
+               }
+       }
+       //TODO: scan vouchers
+}
+
+void MOrder::makeComplete()
+{
+       //already complete?
+       if(m_complete)return;
+       //sanity check: it does not make sense to check invalid or checked orders
+       if(m_status&Mask != MaskIsStored)return;
+       if(m_orderid<0)return;
+       if(!req)return;
+       //go to database
+       getFromDB(m_orderid);
+}
+
+/**************
+ * below this line we need to make sure the order is completed before we return results
+ */
+
+QDateTime MOrder::orderDateTime()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_otime);
+}
+
+QString MOrder::orderDateTimeStr()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_otime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd hh:mm ap","date/time format"));
+}
+
+QDate MOrder::orderDate()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_otime).date();
+}
+
+QString MOrder::orderDateStr()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_otime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd","date format"));
+}
+
+QDateTime MOrder::sentDateTime()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_stime);
+}
+
+QString MOrder::sentDateTimeStr()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_stime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd hh:mm ap","date/time format"));
+}
+
+QDate MOrder::sentDate()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_stime).date();
+}
+
+QString MOrder::sentDateStr()
+{
+       makeComplete();
+       return QDateTime::fromTime_t(m_stime).toString(QCoreApplication::translate("MOrder","yyyy-MM-dd","date format"));
+}
+
+QString MOrder::seller()
+{
+       makeComplete();
+       return m_seller;
+}
+
+QString MOrder::deliveryAddress()
+{
+       makeComplete();
+       return m_deladdress;
+}
+
+QString MOrder::comment()
+{
+       makeComplete();
+       return m_comment;
+}
+
+QList<MTicket> MOrder::tickets()
+{
+       makeComplete();
+       return m_tickets;
+}
+
+/******************************************************************************
+ * Ticket
+ ******************************************************************************/
+
+MTicket::MTicket()
+{
+       req=0;
+       m_eventid=m_orderid=-1;
+       m_price=0;
+       m_status=Invalid;
+}
+
+MTicket::MTicket(MWebRequest*r,const QDomElement&e)
+{
+       req=r;
+       m_eventid=e.attribute("event","-1").toInt();
+       m_orderid=e.attribute("order","-1").toInt();
+       m_id=e.attribute("id");
+       m_price=e.attribute("price","0").toInt();
+       QString st=e.attribute("status");
+       if(st=="bought")m_status=Bought;else
+       if(st=="refund")m_status=Refund;else
+       if(st=="used")m_status=Used;else
+       if(st=="reserved")m_status=Reserved;else
+       if(st=="ok")m_status=CheckOk;else
+       if(st=="saleonly")m_status=CheckSaleOnly;else
+       if(st=="orderonly")m_status=CheckOrderOnly;else
+       if(st=="toolate")m_status=CheckFailTooLate;else
+       if(st=="exhausted")m_status=CheckFailExhausted;else
+       if(st=="cancelled")m_status=CheckFailCancelled;else
+       if(st=="invalid")m_status=CheckFailEventInvalid;
+       else m_status=Invalid;
+}
+
+MTicket::MTicket(const MTicket&t)
+{
+       operator=(t);
+}
+
+MTicket& MTicket::operator=(const MTicket&t)
+{
+       req=t.req;
+       m_eventid=t.m_eventid;
+       m_orderid=t.m_orderid;
+       m_price=t.m_price;
+       m_status=t.m_status;
+       m_id=t.m_id;
+       return *this;
+}
+
+bool MTicket::isValid()const
+{
+       return m_status!=Invalid;
+}
+
+QString MTicket::ticketID()const
+{
+       return m_id;
+}
+
+qint32 MTicket::orderID()const
+{
+       return m_orderid;
+}
+
+int MTicket::price()const
+{
+       return m_price;
+}
+
+QString MTicket::priceString()const
+{
+       return QString::number(m_price/100)+QCoreApplication::translate("MTicket",".","decimal dot")+QString().sprintf("%02d",m_price%100);
+}
+
+qint32 MTicket::eventID()const
+{
+       return m_eventid;
+}
+
+MEvent MTicket::event()const
+{
+       if(m_status==Invalid)return MEvent();
+       if(m_eventid<0)return MEvent();
+       if(!m_event.isValid())
+               m_event=MEvent(req,m_eventid);
+       return m_event;
+}
+
+MTicket::TicketStatus MTicket::status()const
+{
+       return m_status;
+}
+
+QString MTicket::statusString()const
+{
+       switch(m_status){
+               case Bought:return QCoreApplication::translate("MTicket","bought","ticket state");
+               case Refund:return QCoreApplication::translate("MTicket","to refund","ticket state");
+               case Used:return QCoreApplication::translate("MTicket","used","ticket state");
+               case Reserved:return QCoreApplication::translate("MTicket","reserved","ticket state");
+               case CheckOk:return QCoreApplication::translate("MTicket","ok","ticket state");
+               case CheckSaleOnly:return QCoreApplication::translate("MTicket","sale only","ticket state");
+               case CheckOrderOnly:return QCoreApplication::translate("MTicket","order only","ticket state");
+               case CheckFailTooLate:return QCoreApplication::translate("MTicket","too late: event over","ticket state");
+               case CheckFailExhausted:return QCoreApplication::translate("MTicket","no more tickets","ticket state");
+               case CheckFailCancelled:return QCoreApplication::translate("MTicket","event cancelled","ticket state");
+               case CheckFailEventInvalid:return QCoreApplication::translate("MTicket","no such event","ticket state");
+               default:return QCoreApplication::translate("MTicket","invalid","ticket state");
+       }
+}
+
+void MTicket::setOrderID(qint32 o)
+{
+       m_orderid=o;
 }
index f1a883c..9a1e3ba 100644 (file)
 #define MAGICSMOKE_ORDER_H
 
 #include <QString>
+#include <QDateTime>
+#include <QDate>
 
 #include "customer.h"
 
+#include "event.h"
+
 class MWebRequest;
 class QDomElement;
 
+/**this class represents a single ticket*/
+class MTicket
+{
+       public:
+               /**creates an invalid ticket*/
+               MTicket();
+               /**creates a ticket from XML*/
+               MTicket(MWebRequest*,const QDomElement&);
+               /**copies a ticket*/
+               MTicket(const MTicket&);
+               
+               /**copies the ticket*/
+               MTicket& operator=(const MTicket&);
+               
+               /**returns whether the ticket is valid*/
+               bool isValid()const;
+               
+               /**returns the ID of the ticket*/
+               QString ticketID()const;
+               
+               /**returns the ID of the order this ticket belongs to (-1 if it is invalid or does not belong to an order)*/
+               qint32 orderID()const;
+               
+               /**returns the price of the ticket (in cent)*/
+               int price()const;
+               
+               /**returns the price of the ticket as localized string*/
+               QString priceString()const;
+               
+               /**returns the ID of the event the ticket belongs to*/
+               qint32 eventID()const;
+               
+               /**returns the event for this ticket (queries DB once)*/
+               MEvent event()const;
+               
+               /**represents the status of a ticket*/
+               enum TicketStatus{
+                       /**the ticket object is invalid*/
+                       Invalid=0,
+                       /**Mask to find out whether the ticket is stored or has a check status*/
+                       Mask=0xf0,
+                       /**Flag: the ticket is stored in the DB (status&Mask==MaskIsStored)*/
+                       MaskIsStored=0x10,
+                       /**the ticket has been bought, but not yet used*/
+                       Bought=0x10,
+                       /**the ticket has been refunded or needs refund (eg. after the event was cancelled)*/
+                       Refund=0x11,
+                       /**the ticket has been used*/
+                       Used=0x12,
+                       /**the ticket has been reserved by a seller*/
+                       Reserved=0x13,
+                       /**Flag: the ticket has been checked only (status&Mask==MaskIsChecked)*/
+                       MaskIsChecked=0x20,
+                       /**check status: the ticket can be ordered*/
+                       CheckOk=0x20,
+                       /**check status: the ticket can only be sold, not ordered for later delivery*/
+                       CheckSaleOnly=0x21,
+                       /**check status: this ticket can be ordered for later delivery, but not sold*/
+                       CheckOrderOnly=0x22,
+                       /**check status: the ticket order fails, because order times are over*/
+                       CheckFailTooLate=0x23,
+                       /**check status: the ticket order fails, because there are not enough tickets left*/
+                       CheckFailExhausted=0x24,
+                       /**check status: the ticket order fails, because the event was cancelled*/
+                       CheckFailCancelled=0x25,
+                       /**check status: the ticket order fails, because the event does not exist*/
+                       CheckFailEventInvalid=0x26
+               };
+               
+               /**returns the status of the ticket*/
+               TicketStatus status()const;
+               
+               /**returns the ticket status as string*/
+               QString statusString()const;
+               
+       protected:
+               friend class MOrder;
+               /**sets the order-ID of the ticket, used by MOrder*/
+               void setOrderID(qint32);
+               
+       private:
+               MWebRequest*req;
+               qint32 m_eventid,m_orderid,m_price;
+               TicketStatus m_status;
+               QString m_id;
+               mutable MEvent m_event;
+};
+
 class MOrder
 {
        public:
@@ -28,11 +120,14 @@ class MOrder
                /**create order by id*/
                MOrder(MWebRequest*,qint32);
                /**create order from XML element*/
-               MOrder(MWebRequest*,QDomElement&);
+               MOrder(MWebRequest*,const QDomElement&);
                /**copy order*/
                MOrder(const MOrder&);
                
-               /**returns the order ID (-1 for invalid orders)*/
+               /**copies the order*/
+               MOrder& operator=(const MOrder&);
+               
+               /**returns the order ID (-1 for invalid orders or after a simple check)*/
                int orderID()const;
                
                /**returns whether the order is valid*/
@@ -47,15 +142,29 @@ class MOrder
                /**status*/
                enum OrderStatus{
                        /**the order is invalid (not a DB state)*/
-                       Invalid,
+                       Invalid=0,
+                       /**mask code to find general status of the order*/
+                       Mask=0xf0,
+                       /**status codes that have this bit (status&Mask==MaskIsStored) set are stored in the DB*/
+                       MaskIsStored=0x10,
                        /**the order has been placed, nothing is delivered or paid*/
-                       Placed,
+                       Placed=0x10,
                        /**the tickets/vouchers have been shipped*/
-                       Sent,
+                       Sent=0x11,
                        /**the order was cancelled*/
-                       Cancelled,
+                       Cancelled=0x12,
                        /**the order is closed (currently unused state)*/
-                       Closed
+                       Closed=0x13,
+                       /**status codes that have this bit (status&Mask==MaskIsChecked) set are checked only*/
+                       MaskIsChecked=0x20,
+                       /**check status: this order would pass*/
+                       CheckOk=0x20,
+                       /**check status: this order can be sold, but not ordered for later delivery*/
+                       CheckSaleOnly=0x21,
+                       /**check status: this order can be ordered for later delivery, but not sold*/
+                       CheckOrderOnly=0x22,
+                       /**check status: the order fails*/
+                       CheckFail=0x23
                };
                
                /**returns the status of the order*/
@@ -91,10 +200,49 @@ class MOrder
                /**returns whether the tickets of this order have already been shipped*/
                bool isSent()const;
                
+               /**returns the order date+time*/
+               QDateTime orderDateTime();
+               
+               /**returns the order date+time as string*/
+               QString orderDateTimeStr();
+               
+               /**returns the order date only*/
+               QDate orderDate();
+               
+               /**returns the order date only as string*/
+               QString orderDateStr();
+               
+               /**returns the shipping date+time*/
+               QDateTime sentDateTime();
+               
+               /**returns the shipping date+time as string*/
+               QString sentDateTimeStr();
+               
+               /**returns the shipping date only*/
+               QDate sentDate();
+               
+               /**returns the shipping date only as string*/
+               QString sentDateStr();
+               
+               /**returns the seller of this order*/
+               QString seller();
+               
+               /**returns the delivery address (empty string if none is set)*/
+               QString deliveryAddress();
+               
+               /**returns the comment of the order (empty string if none set)*/
+               QString comment();
+               
+               /**returns the list of tickets of this order*/
+               QList<MTicket> tickets();
+               
        private:
                MWebRequest*req;
-               int m_orderid,m_customer,m_price,m_paid;
+               int m_orderid,m_customer,m_price,m_paid,m_otime,m_stime;
                OrderStatus m_status;
+               QString m_seller,m_deladdress,m_comment;
+               bool m_complete;
+               QList<MTicket> m_tickets;
                
                /**internal: requests the order from the database*/
                void getFromDB(qint32);
@@ -104,6 +252,9 @@ class MOrder
                
                /**helper: converts a cent value into a localized string*/
                static QString cent2string(int);
+               
+               /**internal: makes sure the order is completely retrieved*/
+               void makeComplete();
 };
 
 #endif
diff --git a/src/orderwin.cpp b/src/orderwin.cpp
new file mode 100644 (file)
index 0000000..7e4b6ec
--- /dev/null
@@ -0,0 +1,218 @@
+//
+// C++ Implementation: orderwin
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2008
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "orderwin.h"
+#include "event.h"
+#include "webrequest.h"
+#include "ticketrender.h"
+
+#include <QBoxLayout>
+#include <QGridLayout>
+#include <QLabel>
+#include <QTableView>
+#include <QStandardItemModel>
+#include <QPushButton>
+#include <QMenuBar>
+#include <QMenu>
+#include <QComboBox>
+#include <QPixmap>
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QPainter>
+#include <QMessageBox>
+
+MOrderWindow::MOrderWindow(QWidget*par,MWebRequest*r,const MOrder&o)
+       :QMainWindow(par),req(r),m_order(o)
+{
+       setWindowTitle(tr("Order Details"));
+       m_changed=false;
+       
+       QMenuBar*mb=menuBar();
+       QMenu *m=mb->addMenu(tr("&Order"));
+       m->addAction(tr("&Order..."));
+       m->addAction(tr("&Sell..."));
+       m->addSeparator();
+       m->addAction(tr("C&ancel Order..."));
+       m->addSeparator();
+       m->addAction(tr("&Close"),this,SLOT(close()));
+       m=mb->addMenu(tr("&Payment"));
+       m->addAction(tr("Receive &Payment..."));
+       m->addAction(tr("&Refund..."));
+       m=mb->addMenu(tr("P&rinting"));
+       m->addAction(tr("Print &Bill..."));
+       m->addAction(tr("Save Bill &as file..."));
+       m->addSeparator();
+       m->addAction(tr("Print &Tickets..."));
+       m->addAction(tr("Print &Current Ticket..."),this,SLOT(printCurrentTicket()));
+       m->addAction(tr("&View Tickets..."),this,SLOT(ticketView()));
+       
+       QWidget*w;
+       setCentralWidget(w=new QWidget);
+       QVBoxLayout *vl;
+       w->setLayout(vl=new QVBoxLayout);
+       
+       QGridLayout*gl;
+       vl->addLayout(gl=new QGridLayout,0);
+       int rw=0;
+       gl->addWidget(new QLabel(tr("Order ID:")),rw,0);
+       gl->addWidget(m_orderid=new QLabel(QString::number(m_order.orderID())),rw,1);
+       gl->addWidget(new QLabel(tr("Order Date:")),++rw,0);
+       gl->addWidget(m_orderdate=new QLabel(m_order.orderDateTimeStr()),rw,1);
+       gl->addWidget(new QLabel(tr("Shipping Date:")),++rw,0);
+       gl->addWidget(m_sentdate=new QLabel(m_order.sentDateTimeStr()),rw,1);
+       gl->addWidget(new QLabel(tr("Customer:")),++rw,0);
+       gl->addWidget(new QLabel(m_order.customer().getNameAddress()),rw,1);
+       gl->addWidget(new QLabel(tr("Sold by:")),++rw,0);
+       gl->addWidget(new QLabel(m_order.seller()),rw,1);
+       gl->addWidget(new QLabel(tr("Total Price:")),++rw,0);
+       gl->addWidget(new QLabel(m_order.totalPriceString()),rw,1);
+       gl->addWidget(new QLabel(tr("Already Paid:")),++rw,0);
+       gl->addWidget(new QLabel(m_order.amountPaidString()),rw,1);
+       gl->addWidget(new QLabel(tr("Order State:")),++rw,0);
+       gl->addWidget(m_state=new QLabel(m_order.orderStatusString()),rw,1);
+       gl->setColumnStretch(0,0);
+       gl->setColumnStretch(1,10);
+       
+       vl->addSpacing(10);
+       vl->addWidget(m_tickettable=new QTableView,10);
+       m_tickettable->setModel(m_ticketmodel=new QStandardItemModel(this));
+       m_tickettable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+       updateTable();
+       
+       req->dataDir();
+}
+
+void MOrderWindow::updateTable()
+{
+       QList<MTicket> tickets=m_order.tickets();
+       QList<MEvent> events;
+       if(tickets.size()>0)
+               events=req->getAllEvents();
+       m_ticketmodel->setHorizontalHeaderLabels(QStringList()<<tr("Ticket ID")<<tr("Event")<<tr("Start Time")<<tr("Status")<<tr("Price"));
+       m_ticketmodel->insertRows(0,tickets.size());
+       for(int i=0;i<tickets.size();i++){
+               m_ticketmodel->setData(m_ticketmodel->index(i,0),tickets[i].ticketID());
+               m_ticketmodel->setData(m_ticketmodel->index(i,3),tickets[i].statusString());
+               m_ticketmodel->setData(m_ticketmodel->index(i,4),tickets[i].priceString());
+               //find event
+               MEvent ev;int eid=tickets[i].eventID();
+               for(int j=0;j<events.size();j++)
+                       if(events[j].eventId()==eid)
+                               ev=events[j];
+               //render remainder
+               m_ticketmodel->setData(m_ticketmodel->index(i,1),ev.title());
+               m_ticketmodel->setData(m_ticketmodel->index(i,2),ev.startTimeString());
+       }
+       m_tickettable->resizeColumnsToContents();
+}
+
+void MOrderWindow::setChanged()
+{
+       m_changed=true;
+}
+
+bool MOrderWindow::isChanged()const
+{
+       return m_changed;
+}
+
+void MOrderWindow::ticketView()
+{
+       QList<MTicket>tickets=m_order.tickets();
+       if(tickets.size()<1)return;
+       MTicketView tv(this,tickets);
+       tv.exec();
+}
+
+void MOrderWindow::printCurrentTicket()
+{
+       //get current ticketid
+       QModelIndexList lst=m_tickettable->selectionModel()->selectedIndexes();
+       if(lst.size()<1)return;
+       QModelIndex idx=m_ticketmodel->index(lst[0].row(),0);
+       QString id=m_ticketmodel->data(idx).toString();
+       if(id=="")return;
+       //find ticket
+       QList<MTicket>tickets=m_order.tickets();
+       MTicket tick;
+       for(int i=0;i<tickets.size();i++)
+               if(tickets[i].ticketID()==id)
+                       tick=tickets[i];
+       if(!tick.isValid())return;
+       //print
+       printTickets(QList<MTicket>()<<tick);
+}
+
+void MOrderWindow::printTickets()
+{
+       printTickets(m_order.tickets());
+}
+
+void MOrderWindow::printTickets(QList<MTicket> tickets)
+{
+       //sanity check
+       if(tickets.size()<1)return;
+       //get template
+       QString tf=req->getTemplate("ticket.xtt");
+       if(tf==""){
+               QMessageBox::warning(this,tr("Warning"),tr("Unable to get template file (ticket.xtt). Giving up."));
+               return;
+       }
+       //get printer settings
+       QPrinter printer;
+       QPrintDialog pd(&printer,this);
+       if(pd.exec()!=QDialog::Accepted)return;
+       //TODO: insert label arrangement
+       //TODO: fix to use correct template
+       MTicketRenderer render(tf);
+       QPainter painter(&printer);
+       render.render(tickets[0],printer,&painter);
+       
+}
+
+
+/*************************************************************************************/
+
+MTicketView::MTicketView(QWidget*w,QList<MTicket>t)
+       :QDialog(w),tickets(t)
+{
+       setWindowTitle(tr("Preview Tickets"));
+       
+       QVBoxLayout*vl;
+       setLayout(vl=new QVBoxLayout);
+       QComboBox *cb;
+       vl->addWidget(cb=new QComboBox,0);
+       cb->setEditable(false);
+       for(int i=0;i<tickets.size();i++)
+               cb->addItem(tickets[i].ticketID());
+       vl->addWidget(disp=new QLabel,10);
+       //TODO: get the real template!
+       render=new MTicketRenderer("../examples/ticket.xtt");
+       changeTicket(0);
+       connect(cb,SIGNAL(currentIndexChanged(int)),this,SLOT(changeTicket(int)));
+}
+
+MTicketView::~MTicketView()
+{
+       delete render;
+}
+
+void MTicketView::changeTicket(int idx)
+{
+       
+       QSizeF sz=render->ticketSize(*disp);
+       QPixmap tick(sz.toSize());
+       tick.fill();
+       if(!render->render(tickets[idx],tick))
+               qDebug("unable to render");
+       disp->setPixmap(tick);
+}
diff --git a/src/orderwin.h b/src/orderwin.h
new file mode 100644 (file)
index 0000000..3eb8e16
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// C++ Interface: orderwin
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2008
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_ORDERWIN_H
+#define MAGICSMOKE_ORDERWIN_H
+
+#include <QMainWindow>
+#include "order.h"
+
+class QLabel;
+class QTableView;
+class QStandardItemModel;
+class MWebRequest;
+
+/**displays an order and allows the user to execute several commands on it*/
+class MOrderWindow:public QMainWindow
+{
+       Q_OBJECT
+       public:
+               /**creates the order window*/
+               MOrderWindow(QWidget*,MWebRequest*,const MOrder&);
+               
+               /**returns whether the order has been changed by this window*/
+               bool isChanged()const;
+               
+       private slots:
+               /**internal: mark order as changed*/
+               void setChanged();
+               
+               /**internal: updates the ticket table*/
+               void updateTable();
+               
+               /**internal: show the tickets as graphics*/
+               void ticketView();
+               /**internal: print the currently selected ticket*/
+               void printCurrentTicket();
+               /**internal: print all tickets*/
+               void printTickets();
+               /**internal helper: print list of tickets*/
+               void printTickets(QList<MTicket>);
+       
+       private:
+               MWebRequest*req;
+               MOrder m_order;
+               bool m_changed;
+               QLabel *m_orderid,*m_orderdate,*m_sentdate,*m_state;
+               QTableView *m_tickettable;
+               QStandardItemModel *m_ticketmodel;
+};
+
+class MTicketRenderer;
+
+/**helper class: displays tickets*/
+class MTicketView:public QDialog
+{
+       Q_OBJECT
+       public:
+               MTicketView(QWidget*,QList<MTicket>);
+               ~MTicketView();
+               
+       private slots:
+               void changeTicket(int);
+       private:
+               QList<MTicket> tickets;
+               QLabel*disp;
+               MTicketRenderer*render;
+};
+
+#endif
index 76bdf8d..d9b12c9 100644 (file)
@@ -15,6 +15,7 @@
 #include "eventedit.h"
 #include "checkdlg.h"
 #include "eventsummary.h"
+#include "orderwin.h"
 
 #include <QSettings>
 #include <QMessageBox>
@@ -38,6 +39,8 @@
 #include <QDomDocument>
 #include <QDomElement>
 #include <QComboBox>
+#include <QInputDialog>
+#include <QMessageBox>
 
 #define ORDERNONE      0
 #define ORDERALL       0xff
@@ -59,6 +62,8 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
        m->addAction(tr("&Offline mode"))->setEnabled(false);
        m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword())) ->setEnabled(req->hasRole("setmypasswd"));
        m->addSeparator();
+       m->addAction(tr("&Upload Template..."),this,SLOT(uploadTemplate()));
+       m->addSeparator();
        m->addAction(tr("&Close Session"),this,SLOT(close()));
        
        m=mb->addMenu(tr("&Event"));
@@ -176,13 +181,12 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
        ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
        ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
        hl->addLayout(vl=new QVBoxLayout,0);
-       vl->addWidget(new QPushButton(tr("Details...")),0);
-       vl->addSpacing(10);
-       vl->addWidget(new QPushButton(tr("Payment")),0);
-       vl->addWidget(new QPushButton(tr("Refund")),0);
-       vl->addSpacing(10);
-       vl->addWidget(new QPushButton(tr("Print Tickets")),0);
-       vl->addWidget(new QPushButton(tr("Print Bill")),0);
+       vl->addWidget(p=new QPushButton(tr("Update")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(updateOrders()));
+       vl->addSpacing(15);
+       vl->addWidget(p=new QPushButton(tr("Details...")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(orderDetails()));
+       p->setEnabled(req->hasRole("getorder"));
        vl->addStretch(10);
        
        //Entrance Control Tab
@@ -883,6 +887,43 @@ void MOverview::updateOrders()
        }
 }
 
+void MOverview::orderDetails()
+{
+       //get selected order
+       int id;
+       QModelIndexList ilst=ordertable->selectionModel()->selectedIndexes();
+       if(ilst.size()<1)return;
+       QModelIndex idx=ordermodel->index(ilst[0].row(),0);
+       id=ordermodel->data(idx,Qt::UserRole).toInt();
+       if(id<0)return;
+       //open order window
+       MOrderWindow *om=new MOrderWindow(this,req,MOrder(req,id));
+       om->setAttribute(Qt::WA_DeleteOnClose);
+       om->show();
+}
+
+void MOverview::uploadTemplate()
+{
+       //get file
+       QString fn=QFileDialog::getOpenFileName(this,tr("Please select a template file."));
+       if(fn=="")return;
+       //get template name
+       QString tn=QFileInfo(fn).fileName();
+       QRegExp fr("[a-z0-9_\\.]+");
+       do{
+               bool ok;
+               tn=QInputDialog::getText(this,tr("Enter Template Name"),tr("Please enter a name for the template file, it should contain only letters, digits, underscores and dots:"),QLineEdit::Normal,tn,&ok).toLower();
+               if(!ok)return;
+               if(fr.exactMatch(tn))break;
+               QMessageBox::warning(this,tr("Warning"),tr("The template name must only contain letters, digits, underscores and dots."));
+       }while(true);
+       //send it
+       if(req->setTemplate(tn,fn))
+               QMessageBox::information(this,tr("Success"),tr("Successfully uploaded the template."));
+       else
+               QMessageBox::warning(this,tr("Warning"),tr("Unable to upload the template."));
+}
+
 /**********************************************/
 
 MPasswordChange::MPasswordChange(QWidget*par,QString user)
index 70529ad..d82abe3 100644 (file)
@@ -57,6 +57,8 @@ class MOverview:public QMainWindow
                
                /**get all orders, update list*/
                void updateOrders();
+               /**open order detail window*/
+               void orderDetails();
                
                /**update list of users*/
                void updateUsers();
@@ -114,6 +116,9 @@ class MOverview:public QMainWindow
                /**react on entry in Entrance tab*/
                void entranceValidate();
                
+               /**upload Templates*/
+               void uploadTemplate();
+               
        private:
                //my session object
                QPointer<MWebRequest>req;
index c3e7303..14e9cae 100644 (file)
@@ -38,7 +38,9 @@ SOURCES = \
        customer.cpp \
        checkdlg.cpp \
        eventsummary.cpp \
-       odtrender.cpp
+       odtrender.cpp \
+       ticketrender.cpp \
+       orderwin.cpp
 
 #some PHP files are listed below to scan them for translatable items:
 HEADERS = \
@@ -57,6 +59,8 @@ HEADERS = \
        checkdlg.h \
        eventsummary.h \
        odtrender.h \
+       ticketrender.h \
+       orderwin.h \
        ../www/machine.php \
        ../www/inc/machine/session.php \
        ../www/inc/machine/host.php \
index f6ba829..baa2a27 100644 (file)
         <translation>Sie haben nicht das Recht diese Transaktin durchzuführen.</translation>
     </message>
     <message>
-        <location filename="../www/machine.php" line="280"/>
+        <location filename="../www/machine.php" line="292"/>
         <source>Internal Error: unknown command, hiccup in code structure.</source>
         <translation>Interner Fehler: unbekanntes Kommando, Fehler in Code-Struktur. Bitte melden Sie diesen Fehler und wie es dazu kam dem Programmierer.</translation>
     </message>
         <source>eventsummary</source>
         <translation>Veranstaltungübersicht</translation>
     </message>
+    <message>
+        <location filename="../www/machine.php" line="26"/>
+        <source>getorderlist</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../www/machine.php" line="26"/>
+        <source>getorder</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MCheckDialog</name>
 <context>
     <name>MCustomerDialog</name>
     <message>
-        <location filename="customer.cpp" line="297"/>
+        <location filename="customer.cpp" line="305"/>
         <source>Customer %1</source>
         <translation>Kunde %1</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="299"/>
+        <location filename="customer.cpp" line="307"/>
         <source>New Customer</source>
         <translation>Neuer Kunde</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="305"/>
+        <location filename="customer.cpp" line="313"/>
         <source>Name:</source>
         <translation>Name:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="307"/>
+        <location filename="customer.cpp" line="315"/>
         <source>Address:</source>
         <translation>Rechnungsadresse:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="310"/>
+        <location filename="customer.cpp" line="318"/>
         <source>Contact Information:</source>
         <translation>Kontaktinformationen:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="314"/>
+        <location filename="customer.cpp" line="322"/>
         <source>Web-Login/eMail:</source>
         <translation>Web-Login/eMail:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="317"/>
+        <location filename="customer.cpp" line="325"/>
         <source>Comment:</source>
         <translation>Kommentar:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="325"/>
+        <location filename="customer.cpp" line="333"/>
         <source>Save</source>
         <translation>Speichern</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="328"/>
+        <location filename="customer.cpp" line="336"/>
         <source>Cancel</source>
         <translation>Abbrechen</translation>
     </message>
 <context>
     <name>MCustomerListDialog</name>
     <message>
-        <location filename="customer.cpp" line="186"/>
+        <location filename="customer.cpp" line="194"/>
         <source>Select a Customer</source>
         <translation>Kunde auswählen</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="188"/>
+        <location filename="customer.cpp" line="196"/>
         <source>Customers</source>
         <translation>Kunden</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="200"/>
+        <location filename="customer.cpp" line="208"/>
         <source>Details...</source>
         <translation>Details...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="202"/>
+        <location filename="customer.cpp" line="210"/>
         <source>Create new...</source>
         <translation>Neu...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="204"/>
+        <location filename="customer.cpp" line="212"/>
         <source>Delete...</source>
         <translation>Löschen...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="212"/>
+        <location filename="customer.cpp" line="220"/>
         <source>Select</source>
         <translation>Auswählen</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="214"/>
+        <location filename="customer.cpp" line="222"/>
         <source>Cancel</source>
         <translation>Abbrechen</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="217"/>
+        <location filename="customer.cpp" line="225"/>
         <source>Close</source>
         <translation>Schließen</translation>
     </message>
 <context>
     <name>MEvent</name>
     <message>
-        <location filename="event.cpp" line="148"/>
+        <location filename="event.cpp" line="179"/>
         <source>Event is not complete, cannot save.</source>
         <translation>Veranstaltung ist nicht komplett. Kann nicht speichern.</translation>
     </message>
     <message>
-        <location filename="event.cpp" line="193"/>
+        <location filename="event.cpp" line="224"/>
         <source>[0-9]+\.[0-9]{2}</source>
         <comment>price validator regexp</comment>
         <translation>[0-9]+,[0-9]{2}</translation>
     </message>
     <message>
-        <location filename="event.cpp" line="216"/>
+        <location filename="event.cpp" line="247"/>
         <source>.</source>
         <comment>price decimal dot</comment>
         <translation>,</translation>
     </message>
+    <message>
+        <location filename="event.cpp" line="261"/>
+        <source>yyyy-MM-dd hh:mm ap</source>
+        <comment>date/time format</comment>
+        <translation>ddd, d.M.yyyy hh:mm</translation>
+    </message>
 </context>
 <context>
     <name>MEventEditor</name>
 <context>
     <name>MEventSummary</name>
     <message>
-        <location filename="eventsummary.cpp" line="36"/>
+        <location filename="eventsummary.cpp" line="37"/>
         <source>Summary for Event %1</source>
         <translation>Ãœbersicht zu Veranstaltung %1</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="42"/>
+        <location filename="eventsummary.cpp" line="43"/>
         <source>Title:</source>
         <translation>Titel:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="44"/>
+        <location filename="eventsummary.cpp" line="45"/>
         <source>Artist:</source>
         <translation>Künstler:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="46"/>
+        <location filename="eventsummary.cpp" line="47"/>
         <source>Start:</source>
         <translation>Beginn:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="156"/>
+        <location filename="eventsummary.cpp" line="179"/>
         <source>yyyy-MM-dd hh:mm ap</source>
         <comment>Date+Time format for displaying event start time</comment>
         <translation>ddd, d.M.yyyy hh:mm</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="49"/>
+        <location filename="eventsummary.cpp" line="50"/>
         <source>Capacity:</source>
         <translation>Sitzplätze:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="51"/>
+        <location filename="eventsummary.cpp" line="52"/>
         <source>Tickets currently reserved:</source>
         <translation>Momentan reservierte Karten:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="53"/>
+        <location filename="eventsummary.cpp" line="54"/>
         <source>Tickets currently cancelled:</source>
         <translation>Momentan abgesagte Karten:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="55"/>
+        <location filename="eventsummary.cpp" line="56"/>
         <source>Tickets currently usable:</source>
         <translation>Momentan nutzbare Karten:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="57"/>
+        <location filename="eventsummary.cpp" line="58"/>
         <source>Total Income:</source>
         <translation>Umsatz:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="200"/>
+        <location filename="eventsummary.cpp" line="223"/>
         <source>.</source>
         <comment>decimal dot</comment>
         <translation>,</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Price</source>
         <translation>Preis</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Bought</source>
         <translation>Gekauft</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Used</source>
         <translation>Benutzt</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Unused</source>
         <translation>Unbenutzt</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="84"/>
+        <location filename="eventsummary.cpp" line="85"/>
         <source>Print</source>
         <translation>Drucken</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="86"/>
+        <location filename="eventsummary.cpp" line="87"/>
         <source>Save as...</source>
         <translation>Speichern unter...</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="88"/>
+        <location filename="eventsummary.cpp" line="90"/>
         <source>Close</source>
         <translation>Schließen</translation>
     </message>
@@ -838,583 +854,920 @@ At least %1 Bits of random are required.</source>
     </message>
 </context>
 <context>
+    <name>MOrder</name>
+    <message>
+        <location filename="order.cpp" line="91"/>
+        <source>placed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="92"/>
+        <source>sent</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="93"/>
+        <source>cancelled</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="94"/>
+        <source>closed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="95"/>
+        <source>check: ok</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="96"/>
+        <source>check: sale only</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="97"/>
+        <source>check: order only</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="98"/>
+        <source>check: failed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="99"/>
+        <source>invalid</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="126"/>
+        <source>.</source>
+        <comment>decimal dot</comment>
+        <translation>,</translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="296"/>
+        <source>yyyy-MM-dd hh:mm ap</source>
+        <comment>date/time format</comment>
+        <translation>ddd, d.M.yyyy hh:mm</translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="308"/>
+        <source>yyyy-MM-dd</source>
+        <comment>date format</comment>
+        <translation>d.M.yyyy</translation>
+    </message>
+</context>
+<context>
+    <name>MOrderWindow</name>
+    <message>
+        <location filename="orderwin.cpp" line="35"/>
+        <source>Order Details</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="39"/>
+        <source>&amp;Order</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="40"/>
+        <source>&amp;Order...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="41"/>
+        <source>&amp;Sell...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="43"/>
+        <source>C&amp;ancel Order...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="45"/>
+        <source>&amp;Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="46"/>
+        <source>&amp;Payment</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="47"/>
+        <source>Receive &amp;Payment...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="48"/>
+        <source>&amp;Refund...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="49"/>
+        <source>P&amp;rinting</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="50"/>
+        <source>Print &amp;Bill...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="51"/>
+        <source>Save Bill &amp;as file...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="53"/>
+        <source>Print &amp;Tickets...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="54"/>
+        <source>Print &amp;Current Ticket...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="55"/>
+        <source>&amp;View Tickets...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="65"/>
+        <source>Order ID:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="67"/>
+        <source>Order Date:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="69"/>
+        <source>Shipping Date:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="71"/>
+        <source>Customer:</source>
+        <translation type="unfinished">Kunde</translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="73"/>
+        <source>Sold by:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="75"/>
+        <source>Total Price:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="77"/>
+        <source>Already Paid:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="79"/>
+        <source>Order State:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Ticket ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Event</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Start Time</source>
+        <translation type="unfinished">Anfangszeit</translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Status</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Price</source>
+        <translation type="unfinished">Preis</translation>
+    </message>
+</context>
+<context>
     <name>MOverview</name>
     <message>
-        <location filename="overview.cpp" line="50"/>
+        <location filename="overview.cpp" line="58"/>
         <source>&amp;Session</source>
         <translation>&amp;Session</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="51"/>
+        <location filename="overview.cpp" line="59"/>
         <source>&amp;Re-Login</source>
         <translation>&amp;Login wiederholen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="55"/>
+        <location filename="overview.cpp" line="63"/>
         <source>&amp;Close Session</source>
         <translation>Session &amp;schließen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="57"/>
+        <location filename="overview.cpp" line="65"/>
         <source>&amp;Event</source>
         <translation>&amp;Veranstaltung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="62"/>
+        <location filename="overview.cpp" line="70"/>
         <source>&amp;Customer</source>
         <translation>&amp;Kunde</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="73"/>
+        <location filename="overview.cpp" line="81"/>
         <source>C&amp;onfigure</source>
         <translation>&amp;Konfigurieren</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="80"/>
+        <location filename="overview.cpp" line="88"/>
         <source>Events</source>
         <translation>Veranstaltungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="626"/>
+        <location filename="overview.cpp" line="644"/>
         <source>Warning</source>
         <translation>Warnung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="308"/>
+        <location filename="overview.cpp" line="326"/>
         <source>I was unable to renew the login at the server, the error was: %1</source>
         <translation>Der erneute Login ist fehlgeschlagen: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="52"/>
+        <location filename="overview.cpp" line="60"/>
         <source>&amp;Offline mode</source>
         <translation>&amp;Offlinemodus</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="60"/>
+        <location filename="overview.cpp" line="68"/>
         <source>&amp;New Event...</source>
         <translation>&amp;Neue Veranstaltung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="63"/>
+        <location filename="overview.cpp" line="71"/>
         <source>&amp;Show all customers</source>
         <translation>&amp;Alle Kunden anzeigen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="65"/>
+        <location filename="overview.cpp" line="73"/>
         <source>C&amp;art</source>
         <translation>&amp;Einkaufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="66"/>
+        <location filename="overview.cpp" line="74"/>
         <source>Add &amp;Ticket</source>
         <translation>Eintrittskarte &amp;hinzufügen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="67"/>
+        <location filename="overview.cpp" line="75"/>
         <source>Add &amp;Voucher</source>
         <translation>&amp;Gutschein hinzufügen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="68"/>
+        <location filename="overview.cpp" line="76"/>
         <source>&amp;Remove Item</source>
         <translation>&amp;Entfernen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="69"/>
+        <location filename="overview.cpp" line="77"/>
         <source>&amp;Abort Shopping</source>
         <translation>&amp;Einkauf abbrechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="71"/>
+        <location filename="overview.cpp" line="79"/>
         <source>&amp;Show all orders</source>
         <translation>&amp;Alle Bestellungen anzeigen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="90"/>
+        <location filename="overview.cpp" line="98"/>
         <source>New Event...</source>
         <translation>Neue Veranstaltung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="167"/>
+        <location filename="overview.cpp" line="183"/>
         <source>Details...</source>
         <translation>Details...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="97"/>
+        <location filename="overview.cpp" line="105"/>
         <source>Order Ticket...</source>
         <translation>Bestellen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="107"/>
+        <location filename="overview.cpp" line="115"/>
         <source>Shopping Cart</source>
         <translation>Einkaufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="119"/>
+        <location filename="overview.cpp" line="127"/>
         <source>Add Ticket</source>
         <translation>Eintrittskarte hinzufügen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="121"/>
+        <location filename="overview.cpp" line="129"/>
         <source>Add Voucher</source>
         <translation>Gutschein hinzufügen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="124"/>
+        <location filename="overview.cpp" line="132"/>
         <source>Remove Item</source>
         <translation>Entfernen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="130"/>
+        <location filename="overview.cpp" line="138"/>
         <source>Customer:</source>
         <translation>Kunde</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="136"/>
+        <location filename="overview.cpp" line="144"/>
         <source>Delivery Address:</source>
         <translation>Lieferadresse:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="139"/>
+        <location filename="overview.cpp" line="147"/>
         <source>Comments:</source>
         <translation>Kommentare:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="152"/>
+        <location filename="overview.cpp" line="160"/>
         <source>Clear</source>
         <translation>Von vorn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Start Time</source>
         <translation>Anfangszeit</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Title</source>
         <translation>Titel</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="283"/>
+        <location filename="overview.cpp" line="301"/>
         <source>ddd MMMM d yyyy, h:mm ap</source>
         <comment>time format</comment>
         <translation>ddd, d.M.yyyy hh:mm</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="58"/>
+        <location filename="overview.cpp" line="66"/>
         <source>&amp;Update Event List</source>
         <translation>&amp;Veranstaltungsliste auffrischen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="59"/>
+        <location filename="overview.cpp" line="67"/>
         <source>&amp;Show/Edit details...</source>
         <translation>&amp;Details anzeigen/editieren...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="185"/>
+        <location filename="overview.cpp" line="197"/>
         <source>Users</source>
         <translation>Nutzer</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="193"/>
+        <location filename="overview.cpp" line="205"/>
         <source>New User...</source>
         <translation>Neuer Nutzer...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="196"/>
+        <location filename="overview.cpp" line="208"/>
         <source>Delete User...</source>
         <translation>Nutzer löschen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="200"/>
+        <location filename="overview.cpp" line="212"/>
         <source>Description...</source>
         <translation>Beschreibung.,.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="203"/>
+        <location filename="overview.cpp" line="215"/>
         <source>Hosts...</source>
         <translation>Hosts...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="206"/>
+        <location filename="overview.cpp" line="218"/>
         <source>Roles...</source>
         <translation>Rollen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="215"/>
+        <location filename="overview.cpp" line="227"/>
         <source>Hosts</source>
         <translation>Hosts</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="350"/>
+        <location filename="overview.cpp" line="368"/>
         <source>Login Name</source>
         <translation>Loginname</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="350"/>
+        <location filename="overview.cpp" line="368"/>
         <source>Description</source>
         <translation>Beschreibung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="365"/>
+        <location filename="overview.cpp" line="383"/>
         <source>New User</source>
         <translation>Neuer Nutzer</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="365"/>
+        <location filename="overview.cpp" line="383"/>
         <source>Please enter new user name (only letters, digits, and underscore allowed):</source>
         <translation>Neuen Nutzernamen eingeben (Buchstaben, Ziffern, Unterstrich):</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="778"/>
+        <location filename="overview.cpp" line="796"/>
         <source>Error</source>
         <translation>Fehler</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="370"/>
+        <location filename="overview.cpp" line="388"/>
         <source>The user name must contain only letters, digits, and underscores and must be at least one character long!</source>
         <translation>Der Nutzername darf nur aus Buchstaben, Ziffern und Unterstrich bestehen. Er muss mindestens ein Zeichen enthalten.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="405"/>
+        <location filename="overview.cpp" line="423"/>
         <source>Edit Description</source>
         <translation>Beschreibung Ã¤ndern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="405"/>
+        <location filename="overview.cpp" line="423"/>
         <source>Descriptionof user %1:</source>
         <translation>Beschreibung von Nutzer %1:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="53"/>
+        <location filename="overview.cpp" line="61"/>
         <source>Change my &amp;Password</source>
         <translation>Mein &amp;Passwort Ã¤ndern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="209"/>
+        <location filename="overview.cpp" line="221"/>
         <source>Set Password...</source>
         <translation>Passwort setzen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="223"/>
+        <location filename="overview.cpp" line="235"/>
         <source>New Host...</source>
         <translation>Neuer Host...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="226"/>
+        <location filename="overview.cpp" line="238"/>
         <source>Add This Host...</source>
         <translation>Diesen Host hinzufügen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="229"/>
+        <location filename="overview.cpp" line="241"/>
         <source>Delete Host...</source>
         <translation>Host löschen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="233"/>
+        <location filename="overview.cpp" line="245"/>
         <source>Generate New Key...</source>
         <translation>Neuen Schlüssel anlegen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="236"/>
+        <location filename="overview.cpp" line="248"/>
         <source>Import...</source>
         <translation>Importieren...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="239"/>
+        <location filename="overview.cpp" line="251"/>
         <source>Export...</source>
         <translation>Exportieren...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="374"/>
+        <location filename="overview.cpp" line="392"/>
         <source>Password</source>
         <translation>Passwort</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="374"/>
+        <location filename="overview.cpp" line="392"/>
         <source>Please enter an initial password for the user:</source>
         <translation>Bitte geben Sie ein intiales Passwort ein:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="389"/>
+        <location filename="overview.cpp" line="407"/>
         <source>Delete User?</source>
         <translation>Nutzer löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="389"/>
+        <location filename="overview.cpp" line="407"/>
         <source>Really delete user &apos;%1&apos;?</source>
         <translation>Nutzer &apos;%1&apos; wirklich löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="448"/>
+        <location filename="overview.cpp" line="466"/>
         <source>Error setting password: %1</source>
         <translation>Passwort kann nicht gesetzt werden: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="463"/>
+        <location filename="overview.cpp" line="481"/>
         <source>The password must be non-empty and both lines must match</source>
         <translation>Das Passwort darf nicht leer sein und beide Zeilen müssen Ã¼bereinstimmen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="479"/>
+        <location filename="overview.cpp" line="497"/>
         <source>Host Name</source>
         <translation>Hostname</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="479"/>
+        <location filename="overview.cpp" line="497"/>
         <source>Host Key</source>
         <translation>Hostkey</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="497"/>
+        <location filename="overview.cpp" line="515"/>
         <source>Create New Host</source>
         <translation>Neuen Host anlegen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="497"/>
+        <location filename="overview.cpp" line="515"/>
         <source>Please enter a host name:</source>
         <translation>Bitte geben Sie einen neuen Hostnamen ein:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="505"/>
+        <location filename="overview.cpp" line="523"/>
         <source>The key of this new host could only be generated with %1 bits entropy. Store anyway?</source>
         <translation>Der Key dieses Hosts konnte nur mit %1 Bits Entropie angelegt werde. Trotzdem speichern?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="528"/>
+        <location filename="overview.cpp" line="546"/>
         <source>Delete this Host?</source>
         <translation>Diesen Host löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="528"/>
+        <location filename="overview.cpp" line="546"/>
         <source>Really delete host &apos;%1&apos;?</source>
         <translation>Den Host &apos;%1&apos; wirklich löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="542"/>
+        <location filename="overview.cpp" line="560"/>
         <source>Change Host Key?</source>
         <translation>Hostkey Ã¤ndern?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="542"/>
+        <location filename="overview.cpp" line="560"/>
         <source>Really change the key of host &apos;%1&apos;?</source>
         <translation>Den Key von Host &apos;%1&apos; wirklich Ã¤ndern?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="547"/>
+        <location filename="overview.cpp" line="565"/>
         <source>The new key of this host could only be generated with %1 bits entropy. Store anyway?</source>
         <translation>Der Key dieses Hosts konnte nur mit %1 Bits Entropie angelegt werde. Trotzdem speichern?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="558"/>
+        <location filename="overview.cpp" line="576"/>
         <source>Import Key from File</source>
         <translation>Key aus Datei importieren</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="567"/>
+        <location filename="overview.cpp" line="585"/>
         <source>Unable to open file %1 for reading: %2</source>
         <translation>Datei %1 kann nicht zum Lesen geöffnet werden: %2</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="579"/>
+        <location filename="overview.cpp" line="597"/>
         <source>This is not a host key file.</source>
         <translation>Dies ist keine Hostkeydatei.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="584"/>
+        <location filename="overview.cpp" line="602"/>
         <source>This host key file does not contain a valid host name.</source>
         <translation>Die Hostkeydatei enthält keinen gültigen Hostnamen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="589"/>
+        <location filename="overview.cpp" line="607"/>
         <source>This host key file does not contain a valid key.</source>
         <translation>Diese Datei enthält keinen gültigen Hostkey.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="594"/>
+        <location filename="overview.cpp" line="612"/>
         <source>The key check sum did not match. Please get a clean copy of the host key file.</source>
         <translation>Die Checksumme dieser Datei ist fehlgeschlagen. Bitte besorgen Sie eine neue Kopie der Datei.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="612"/>
+        <location filename="overview.cpp" line="630"/>
         <source>This host cannot be exported.</source>
         <translation>Dieser Host kann nicht exportiert werden.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="617"/>
+        <location filename="overview.cpp" line="635"/>
         <source>Export Key to File</source>
         <translation>Hostkey als Datei speichern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="626"/>
+        <location filename="overview.cpp" line="644"/>
         <source>Unable to open file %1 for writing: %2</source>
         <translation>Datei %1 kann nicht zum Schreiben geöffnet werden: %2</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="146"/>
+        <location filename="overview.cpp" line="154"/>
         <source>Order Items</source>
         <translation>Bestellung anlegen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="149"/>
+        <location filename="overview.cpp" line="157"/>
         <source>Sell Items</source>
         <translation>Verkaufen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="156"/>
+        <location filename="overview.cpp" line="164"/>
         <source>Order List</source>
         <translation>Bestellungsliste</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="160"/>
+        <location filename="overview.cpp" line="168"/>
         <source>-select mode-</source>
         <translation>-Modus auswählen-</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="161"/>
+        <location filename="overview.cpp" line="169"/>
         <source>All Orders</source>
         <translation>Alle Bestellungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="162"/>
+        <location filename="overview.cpp" line="170"/>
         <source>Open Orders</source>
         <translation>Offene Bestellungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="163"/>
+        <location filename="overview.cpp" line="171"/>
         <source>Outstanding Payments</source>
         <translation>Noch nicht bezahlt</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="164"/>
+        <location filename="overview.cpp" line="172"/>
         <source>Outstanding Refunds</source>
         <translation>Offene Rückerstattungen</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="169"/>
         <source>Payment</source>
-        <translation>Bezahlen</translation>
+        <translation type="obsolete">Bezahlen</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="170"/>
         <source>Refund</source>
-        <translation>Rückerstattung</translation>
+        <translation type="obsolete">Rückerstattung</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="172"/>
         <source>Print Tickets</source>
-        <translation>Eintrittskarten drucken</translation>
+        <translation type="obsolete">Eintrittskarten drucken</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="173"/>
         <source>Print Bill</source>
-        <translation>Rechnung drucken</translation>
+        <translation type="obsolete">Rechnung drucken</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Amount</source>
         <translation>Anzahl</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="683"/>
+        <location filename="overview.cpp" line="701"/>
         <source>Select Event to order Ticket</source>
         <translation>Bitte wählen Sie eine Verstaltung aus, um zu bestellen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="697"/>
+        <location filename="overview.cpp" line="715"/>
         <source>Select</source>
         <translation>Auswählen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="699"/>
+        <location filename="overview.cpp" line="717"/>
         <source>Cancel</source>
         <translation>Abbrechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="734"/>
+        <location filename="overview.cpp" line="752"/>
         <source>There is nothing in the order. Ignoring it.</source>
         <translation>Bestellung ist leer. Vorgang abgebrochen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="738"/>
+        <location filename="overview.cpp" line="756"/>
         <source>Please chose a customer first!</source>
         <translation>Bitte wählen Sie zunächst einen Kunden aus!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="774"/>
+        <location filename="overview.cpp" line="792"/>
         <source>The request failed.</source>
         <translation>Anfrage ist fehlgeschlagen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="778"/>
+        <location filename="overview.cpp" line="796"/>
         <source>A problem occurred during the order: %1</source>
         <translation>Die Bestellung ist fehlgeschlagen: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="177"/>
+        <location filename="overview.cpp" line="189"/>
         <source>Entrance</source>
         <translation>Einlasskontrolle</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="814"/>
+        <location filename="overview.cpp" line="832"/>
         <source>Ticket Ok</source>
         <translation>Eintrittskarte gültig</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="818"/>
+        <location filename="overview.cpp" line="836"/>
         <source>Ticket Already Used</source>
         <translation>Die Eintrittkarte wurde bereits benutzt!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="822"/>
+        <location filename="overview.cpp" line="840"/>
         <source>Ticket Not Paid</source>
         <translation>Die Eintrittskarte ist noch nicht bezahlt!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="101"/>
+        <location filename="overview.cpp" line="109"/>
         <source>Ticket Summary...</source>
         <translation>Eintrittskartenübersicht...</translation>
     </message>
+    <message>
+        <location filename="overview.cpp" line="173"/>
+        <source>Undelivered Orders</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="180"/>
+        <source>Update</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Status</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Total</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Paid</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Customer</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MPasswordChange</name>
     <message>
-        <location filename="overview.cpp" line="840"/>
+        <location filename="overview.cpp" line="908"/>
         <source>Change my password</source>
         <translation>Mein Passwort Ã¤ndern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="842"/>
+        <location filename="overview.cpp" line="910"/>
         <source>Reset password of user %1</source>
         <translation>Passwort von Nutzer %1 setzen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="846"/>
+        <location filename="overview.cpp" line="914"/>
         <source>Old Password:</source>
         <translation>Altes Passwort:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="850"/>
+        <location filename="overview.cpp" line="918"/>
         <source>New Password:</source>
         <translation>Neues Passwort:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="853"/>
+        <location filename="overview.cpp" line="921"/>
         <source>Repeat Password:</source>
         <translation>Paswort wiederholen:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="861"/>
+        <location filename="overview.cpp" line="929"/>
         <source>Set Password</source>
         <translation>Passwort setzen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="863"/>
+        <location filename="overview.cpp" line="931"/>
         <source>Cancel</source>
         <translation>Abbrechen</translation>
     </message>
 </context>
 <context>
+    <name>MTicket</name>
+    <message>
+        <location filename="order.cpp" line="407"/>
+        <source>.</source>
+        <comment>decimal dot</comment>
+        <translation>,</translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="432"/>
+        <source>bought</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="433"/>
+        <source>to refund</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="434"/>
+        <source>used</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="435"/>
+        <source>reserved</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="436"/>
+        <source>ok</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="437"/>
+        <source>sale only</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="438"/>
+        <source>order only</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="439"/>
+        <source>too late: event over</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="440"/>
+        <source>no more tickets</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="441"/>
+        <source>event cancelled</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="442"/>
+        <source>no such event</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="443"/>
+        <source>invalid</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MTicketView</name>
+    <message>
+        <location filename="orderwin.cpp" line="166"/>
+        <source>Preview Tickets</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MUserHost</name>
     <message>
         <location filename="user.cpp" line="303"/>
@@ -1490,7 +1843,7 @@ At least %1 Bits of random are required.</source>
         <translation>Authentifikation fehlgeschlagen.</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="325"/>
+        <location filename="webrequest.cpp" line="326"/>
         <source>Error parsing EventList XML data (line %1 column %2): %3</source>
         <translation>Fehler beim Lesen der XML-Daten (Zeile %1, Spalte %2): %3</translation>
     </message>
@@ -1500,25 +1853,30 @@ At least %1 Bits of random are required.</source>
         <translation>Passwort kann nicht geändert werden: altes Passwort ist falsch.</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="348"/>
+        <location filename="webrequest.cpp" line="350"/>
         <source>Error parsing RoomList XML data (line %1 column %2): %3</source>
         <translation>Fehler beim Lesen der Daten (RoomList; Zeile %1, Spalte %2): %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="371"/>
+        <location filename="webrequest.cpp" line="374"/>
         <source>Error parsing UserList XML data (line %1 column %2): %3</source>
         <translation>Fehler beim Lesen der Daten (UserList; Zeile %1, Spalte %2): %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="394"/>
+        <location filename="webrequest.cpp" line="398"/>
         <source>Error parsing HostList XML data (line %1 column %2): %3</source>
         <translation>Fehler beim Lesen der Daten (HostList; Zeile %1, Spalte %2): %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="417"/>
+        <location filename="webrequest.cpp" line="422"/>
         <source>Error parsing CustomerList XML data (line %1 column %2): %3</source>
         <translation>Fehler beim Lesen der Daten (CustomerList; Zeile %1, Spalte %2): %3</translation>
     </message>
+    <message>
+        <location filename="webrequest.cpp" line="446"/>
+        <source>Error parsing OrderList XML data (line %1 column %2): %3</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>initkey</name>
index cfae056..f380f5a 100644 (file)
         <translation>Des darfsde nisch. Da mussde den Baba Adminischdrador frachn.</translation>
     </message>
     <message>
-        <location filename="../www/machine.php" line="280"/>
+        <location filename="../www/machine.php" line="292"/>
         <source>Internal Error: unknown command, hiccup in code structure.</source>
         <translation>Isch hab da een Broblem. Irschendwie gibsd das Gommando nur halb, aber och ni&apos; rischdisch. Frach ma&apos; den Brogrammierer.</translation>
     </message>
         <source>eventsummary</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../www/machine.php" line="26"/>
+        <source>getorderlist</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../www/machine.php" line="26"/>
+        <source>getorder</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MCheckDialog</name>
 <context>
     <name>MCustomerDialog</name>
     <message>
-        <location filename="customer.cpp" line="297"/>
+        <location filename="customer.cpp" line="305"/>
         <source>Customer %1</source>
         <translation>Gunde %1</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="299"/>
+        <location filename="customer.cpp" line="307"/>
         <source>New Customer</source>
         <translation>Neier Gunde</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="305"/>
+        <location filename="customer.cpp" line="313"/>
         <source>Name:</source>
         <translation>Dor Name:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="307"/>
+        <location filename="customer.cpp" line="315"/>
         <source>Address:</source>
         <translation>De Adresse:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="310"/>
+        <location filename="customer.cpp" line="318"/>
         <source>Contact Information:</source>
         <translation>Wie mor den erreischen gann:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="314"/>
+        <location filename="customer.cpp" line="322"/>
         <source>Web-Login/eMail:</source>
         <translation>Wie er sisch im Web anmelden gann:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="317"/>
+        <location filename="customer.cpp" line="325"/>
         <source>Comment:</source>
         <translation>Gommendar:</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="325"/>
+        <location filename="customer.cpp" line="333"/>
         <source>Save</source>
         <translation>Schbeichorn</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="328"/>
+        <location filename="customer.cpp" line="336"/>
         <source>Cancel</source>
         <translation>Doch ni&apos; machen</translation>
     </message>
 <context>
     <name>MCustomerListDialog</name>
     <message>
-        <location filename="customer.cpp" line="186"/>
+        <location filename="customer.cpp" line="194"/>
         <source>Select a Customer</source>
         <translation>Gunde auswählen</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="188"/>
+        <location filename="customer.cpp" line="196"/>
         <source>Customers</source>
         <translation>Gunden</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="200"/>
+        <location filename="customer.cpp" line="208"/>
         <source>Details...</source>
         <translation>Dedails anzeichen...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="202"/>
+        <location filename="customer.cpp" line="210"/>
         <source>Create new...</source>
         <translation>Neuen anlechen...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="204"/>
+        <location filename="customer.cpp" line="212"/>
         <source>Delete...</source>
         <translation>Wechschmeißen...</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="212"/>
+        <location filename="customer.cpp" line="220"/>
         <source>Select</source>
         <translation>Auswählen</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="214"/>
+        <location filename="customer.cpp" line="222"/>
         <source>Cancel</source>
         <translation>Mach ma ni&apos;</translation>
     </message>
     <message>
-        <location filename="customer.cpp" line="217"/>
+        <location filename="customer.cpp" line="225"/>
         <source>Close</source>
         <translation>Zumachn</translation>
     </message>
 <context>
     <name>MEvent</name>
     <message>
-        <location filename="event.cpp" line="148"/>
+        <location filename="event.cpp" line="179"/>
         <source>Event is not complete, cannot save.</source>
         <translation>De Veranschdaldung is ni gombledd, das gansch so ni abschiggn.</translation>
     </message>
     <message>
-        <location filename="event.cpp" line="193"/>
+        <location filename="event.cpp" line="224"/>
         <source>[0-9]+\.[0-9]{2}</source>
         <comment>price validator regexp</comment>
         <translation>[0-9]+,[0-9]{2}</translation>
     </message>
     <message>
-        <location filename="event.cpp" line="216"/>
+        <location filename="event.cpp" line="247"/>
         <source>.</source>
         <comment>price decimal dot</comment>
         <translation>,</translation>
     </message>
+    <message>
+        <location filename="event.cpp" line="261"/>
+        <source>yyyy-MM-dd hh:mm ap</source>
+        <comment>date/time format</comment>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MEventEditor</name>
 <context>
     <name>MEventSummary</name>
     <message>
-        <location filename="eventsummary.cpp" line="36"/>
+        <location filename="eventsummary.cpp" line="37"/>
         <source>Summary for Event %1</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="42"/>
+        <location filename="eventsummary.cpp" line="43"/>
         <source>Title:</source>
         <translation type="unfinished">Diddel:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="44"/>
+        <location filename="eventsummary.cpp" line="45"/>
         <source>Artist:</source>
         <translation type="unfinished">Günsdlor:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="46"/>
+        <location filename="eventsummary.cpp" line="47"/>
         <source>Start:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="156"/>
+        <location filename="eventsummary.cpp" line="179"/>
         <source>yyyy-MM-dd hh:mm ap</source>
         <comment>Date+Time format for displaying event start time</comment>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="49"/>
+        <location filename="eventsummary.cpp" line="50"/>
         <source>Capacity:</source>
         <translation type="unfinished">Magsimale Gäsde:</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="51"/>
+        <location filename="eventsummary.cpp" line="52"/>
         <source>Tickets currently reserved:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="53"/>
+        <location filename="eventsummary.cpp" line="54"/>
         <source>Tickets currently cancelled:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="55"/>
+        <location filename="eventsummary.cpp" line="56"/>
         <source>Tickets currently usable:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="57"/>
+        <location filename="eventsummary.cpp" line="58"/>
         <source>Total Income:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="200"/>
+        <location filename="eventsummary.cpp" line="223"/>
         <source>.</source>
         <comment>decimal dot</comment>
         <translation type="unfinished">,</translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Price</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Bought</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Used</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="68"/>
+        <location filename="eventsummary.cpp" line="69"/>
         <source>Unused</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="84"/>
+        <location filename="eventsummary.cpp" line="85"/>
         <source>Print</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="86"/>
+        <location filename="eventsummary.cpp" line="87"/>
         <source>Save as...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="eventsummary.cpp" line="88"/>
+        <location filename="eventsummary.cpp" line="90"/>
         <source>Close</source>
         <translation type="unfinished">Zumachn</translation>
     </message>
@@ -837,54 +853,272 @@ At least %1 Bits of random are required.</source>
     </message>
 </context>
 <context>
+    <name>MOrder</name>
+    <message>
+        <location filename="order.cpp" line="91"/>
+        <source>placed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="92"/>
+        <source>sent</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="93"/>
+        <source>cancelled</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="94"/>
+        <source>closed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="95"/>
+        <source>check: ok</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="96"/>
+        <source>check: sale only</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="97"/>
+        <source>check: order only</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="98"/>
+        <source>check: failed</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="99"/>
+        <source>invalid</source>
+        <comment>state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="126"/>
+        <source>.</source>
+        <comment>decimal dot</comment>
+        <translation type="unfinished">,</translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="296"/>
+        <source>yyyy-MM-dd hh:mm ap</source>
+        <comment>date/time format</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="308"/>
+        <source>yyyy-MM-dd</source>
+        <comment>date format</comment>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MOrderWindow</name>
+    <message>
+        <location filename="orderwin.cpp" line="35"/>
+        <source>Order Details</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="39"/>
+        <source>&amp;Order</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="40"/>
+        <source>&amp;Order...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="41"/>
+        <source>&amp;Sell...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="43"/>
+        <source>C&amp;ancel Order...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="45"/>
+        <source>&amp;Close</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="46"/>
+        <source>&amp;Payment</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="47"/>
+        <source>Receive &amp;Payment...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="48"/>
+        <source>&amp;Refund...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="49"/>
+        <source>P&amp;rinting</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="50"/>
+        <source>Print &amp;Bill...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="51"/>
+        <source>Save Bill &amp;as file...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="53"/>
+        <source>Print &amp;Tickets...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="54"/>
+        <source>Print &amp;Current Ticket...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="55"/>
+        <source>&amp;View Tickets...</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="65"/>
+        <source>Order ID:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="67"/>
+        <source>Order Date:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="69"/>
+        <source>Shipping Date:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="71"/>
+        <source>Customer:</source>
+        <translation type="unfinished">Gunde:</translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="73"/>
+        <source>Sold by:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="75"/>
+        <source>Total Price:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="77"/>
+        <source>Already Paid:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="79"/>
+        <source>Order State:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Ticket ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Event</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Start Time</source>
+        <translation type="unfinished">Anfangszeit</translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Status</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="orderwin.cpp" line="97"/>
+        <source>Price</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MOverview</name>
     <message>
-        <location filename="overview.cpp" line="50"/>
+        <location filename="overview.cpp" line="58"/>
         <source>&amp;Session</source>
         <translation>&amp;Sidsung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="51"/>
+        <location filename="overview.cpp" line="59"/>
         <source>&amp;Re-Login</source>
         <translation>&amp;Noch&apos;ma einloggn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="55"/>
+        <location filename="overview.cpp" line="63"/>
         <source>&amp;Close Session</source>
         <translation>Sidsung &amp;Zumachn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="57"/>
+        <location filename="overview.cpp" line="65"/>
         <source>&amp;Event</source>
         <translation>&amp;Veranschdaldung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="62"/>
+        <location filename="overview.cpp" line="70"/>
         <source>&amp;Customer</source>
         <translation>&amp;Gunde</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="73"/>
+        <location filename="overview.cpp" line="81"/>
         <source>C&amp;onfigure</source>
         <translation>G&amp;onfiguriern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="80"/>
+        <location filename="overview.cpp" line="88"/>
         <source>Events</source>
         <translation>Veranschdaldungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="626"/>
+        <location filename="overview.cpp" line="644"/>
         <source>Warning</source>
         <translation>Dumm gelaufen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="308"/>
+        <location filename="overview.cpp" line="326"/>
         <source>I was unable to renew the login at the server, the error was: %1</source>
         <translation>Isch gann de&apos; Verbindung off&apos;n gross&apos;n Reschner nisch erneuern. Der will nisch weil: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="52"/>
+        <location filename="overview.cpp" line="60"/>
         <source>&amp;Offline mode</source>
         <translation>&amp;Ohne Neds und Dobbelden Boden</translation>
     </message>
@@ -894,92 +1128,92 @@ At least %1 Bits of random are required.</source>
         <translation type="obsolete">&amp;Dedails anzeigen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="60"/>
+        <location filename="overview.cpp" line="68"/>
         <source>&amp;New Event...</source>
         <translation>Veranschdaldung &amp;absach&apos;n...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="63"/>
+        <location filename="overview.cpp" line="71"/>
         <source>&amp;Show all customers</source>
         <translation>&amp;Alle Gunden anzeigen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="65"/>
+        <location filename="overview.cpp" line="73"/>
         <source>C&amp;art</source>
         <translation>Eing&amp;aufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="66"/>
+        <location filename="overview.cpp" line="74"/>
         <source>Add &amp;Ticket</source>
         <translation>Ein&amp;driddsgarde hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="67"/>
+        <location filename="overview.cpp" line="75"/>
         <source>Add &amp;Voucher</source>
         <translation>&amp;Gudschein hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="68"/>
+        <location filename="overview.cpp" line="76"/>
         <source>&amp;Remove Item</source>
         <translation>Doch &amp;ni&apos; nehm&apos;</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="69"/>
+        <location filename="overview.cpp" line="77"/>
         <source>&amp;Abort Shopping</source>
         <translation>&amp;Eingauf Abbrechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="71"/>
+        <location filename="overview.cpp" line="79"/>
         <source>&amp;Show all orders</source>
         <translation>&amp;Alle Beschdellungen anzeichen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="90"/>
+        <location filename="overview.cpp" line="98"/>
         <source>New Event...</source>
         <translation>Neue Veranschdaldung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="167"/>
+        <location filename="overview.cpp" line="183"/>
         <source>Details...</source>
         <translation>Dedails anzeichen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="97"/>
+        <location filename="overview.cpp" line="105"/>
         <source>Order Ticket...</source>
         <translation>Eindriddsgarde beschdellen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="107"/>
+        <location filename="overview.cpp" line="115"/>
         <source>Shopping Cart</source>
         <translation>Eingaufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="119"/>
+        <location filename="overview.cpp" line="127"/>
         <source>Add Ticket</source>
         <translation>Eindriddsgarde hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="121"/>
+        <location filename="overview.cpp" line="129"/>
         <source>Add Voucher</source>
         <translation>Gudschein hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="124"/>
+        <location filename="overview.cpp" line="132"/>
         <source>Remove Item</source>
         <translation>Doch ni&apos; nehm&apos;</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="130"/>
+        <location filename="overview.cpp" line="138"/>
         <source>Customer:</source>
         <translation>Gunde:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="136"/>
+        <location filename="overview.cpp" line="144"/>
         <source>Delivery Address:</source>
         <translation>Adresse wo&apos;s Zeuch hin soll:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="139"/>
+        <location filename="overview.cpp" line="147"/>
         <source>Comments:</source>
         <translation>Wischdiches Gelaber und Gerede:</translation>
     </message>
@@ -989,441 +1223,560 @@ At least %1 Bits of random are required.</source>
         <translation type="obsolete">Beschdellung abschbeichern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="152"/>
+        <location filename="overview.cpp" line="160"/>
         <source>Clear</source>
         <translation>Wechwerfen und von vorne!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Start Time</source>
         <translation>Anfangszeit</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Title</source>
         <translation>Diddel</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="283"/>
+        <location filename="overview.cpp" line="301"/>
         <source>ddd MMMM d yyyy, h:mm ap</source>
         <comment>time format</comment>
         <translation>ddd, d.M.yyyy hh:mm</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="58"/>
+        <location filename="overview.cpp" line="66"/>
         <source>&amp;Update Event List</source>
         <translation>&amp;Voranschdaldungsliste nochma holen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="59"/>
+        <location filename="overview.cpp" line="67"/>
         <source>&amp;Show/Edit details...</source>
         <translation>&amp;Dedails anzeichen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="185"/>
+        <location filename="overview.cpp" line="197"/>
         <source>Users</source>
         <translation>Nudsor</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="193"/>
+        <location filename="overview.cpp" line="205"/>
         <source>New User...</source>
         <translation>Neier Nudsor...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="196"/>
+        <location filename="overview.cpp" line="208"/>
         <source>Delete User...</source>
         <translation>Nudsor löschen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="200"/>
+        <location filename="overview.cpp" line="212"/>
         <source>Description...</source>
         <translation>Beschreibung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="203"/>
+        <location filename="overview.cpp" line="215"/>
         <source>Hosts...</source>
         <translation>Reschnor...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="206"/>
+        <location filename="overview.cpp" line="218"/>
         <source>Roles...</source>
         <translation>Rollen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="215"/>
+        <location filename="overview.cpp" line="227"/>
         <source>Hosts</source>
         <translation>Reschnor</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="350"/>
+        <location filename="overview.cpp" line="368"/>
         <source>Login Name</source>
         <translation>Name zum Anmelden</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="350"/>
+        <location filename="overview.cpp" line="368"/>
         <source>Description</source>
         <translation>Beschreibung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="365"/>
+        <location filename="overview.cpp" line="383"/>
         <source>New User</source>
         <translation>Neier Nudsor</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="365"/>
+        <location filename="overview.cpp" line="383"/>
         <source>Please enter new user name (only letters, digits, and underscore allowed):</source>
         <translation>Bidde gib ma nen neien Nudsornam&apos; ein (nur Buchschdaben, Ziffern und &quot;_&quot;):</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="778"/>
+        <location filename="overview.cpp" line="796"/>
         <source>Error</source>
         <translation>Gans doller falschor Fehler</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="370"/>
+        <location filename="overview.cpp" line="388"/>
         <source>The user name must contain only letters, digits, and underscores and must be at least one character long!</source>
         <translation>Dor Nudsorname darf nur Buchschdaben, Ziffern und &quot;_&quot; endhalden. Umlaude sind böse. Und mindesdens een Buchschdaben lang mussor och sein.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="405"/>
+        <location filename="overview.cpp" line="423"/>
         <source>Edit Description</source>
         <translation>Beschreibung Ã¤ndorn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="405"/>
+        <location filename="overview.cpp" line="423"/>
         <source>Descriptionof user %1:</source>
         <translation>Beschreibung vom Nudsor %1:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="53"/>
+        <location filename="overview.cpp" line="61"/>
         <source>Change my &amp;Password</source>
         <translation>Mei eechnes &amp;Bassword Ã¤ndorn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="209"/>
+        <location filename="overview.cpp" line="221"/>
         <source>Set Password...</source>
         <translation>Bassword sedsen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="223"/>
+        <location filename="overview.cpp" line="235"/>
         <source>New Host...</source>
         <translation>Neier Reschnor...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="226"/>
+        <location filename="overview.cpp" line="238"/>
         <source>Add This Host...</source>
         <translation>Die Gisde hier hinzufüchen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="229"/>
+        <location filename="overview.cpp" line="241"/>
         <source>Delete Host...</source>
         <translation>Reschnor löschen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="233"/>
+        <location filename="overview.cpp" line="245"/>
         <source>Generate New Key...</source>
         <translation>Neien Schlüssel erzeuchen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="236"/>
+        <location filename="overview.cpp" line="248"/>
         <source>Import...</source>
         <translation>Imbordieren...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="239"/>
+        <location filename="overview.cpp" line="251"/>
         <source>Export...</source>
         <translation>Eggsbordieren...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="374"/>
+        <location filename="overview.cpp" line="392"/>
         <source>Password</source>
         <translation>Bassword</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="374"/>
+        <location filename="overview.cpp" line="392"/>
         <source>Please enter an initial password for the user:</source>
         <translation>Bidde gib ma een Bassword für den Nudsor ein:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="389"/>
+        <location filename="overview.cpp" line="407"/>
         <source>Delete User?</source>
         <translation>Nudsor löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="389"/>
+        <location filename="overview.cpp" line="407"/>
         <source>Really delete user &apos;%1&apos;?</source>
         <translation>Nudsor &apos;%1&apos; wirklich löschen? Bissde Dir da och gans sischor?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="448"/>
+        <location filename="overview.cpp" line="466"/>
         <source>Error setting password: %1</source>
         <translation>Gann Bassword ni sedsen: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="463"/>
+        <location filename="overview.cpp" line="481"/>
         <source>The password must be non-empty and both lines must match</source>
         <translation>Das Bassword darf nisch leer sein und beide Basswordzeilen müssen gleisch sein.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="479"/>
+        <location filename="overview.cpp" line="497"/>
         <source>Host Name</source>
         <translation>Reschnorname</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="479"/>
+        <location filename="overview.cpp" line="497"/>
         <source>Host Key</source>
         <translation>Reschnorschlüssel</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="497"/>
+        <location filename="overview.cpp" line="515"/>
         <source>Create New Host</source>
         <translation>Neien Reschnor anlechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="497"/>
+        <location filename="overview.cpp" line="515"/>
         <source>Please enter a host name:</source>
         <translation>Gib ma nen Nam&apos; für de Gisde ein:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="505"/>
+        <location filename="overview.cpp" line="523"/>
         <source>The key of this new host could only be generated with %1 bits entropy. Store anyway?</source>
         <translation>Dor Schlüssel von der Gisde hat nur %1 zufällige Bids. Das is a bissl wenisch. Drodsdem schbeichorn?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="528"/>
+        <location filename="overview.cpp" line="546"/>
         <source>Delete this Host?</source>
         <translation>De Gisdge löschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="528"/>
+        <location filename="overview.cpp" line="546"/>
         <source>Really delete host &apos;%1&apos;?</source>
         <translation>De Gisde &apos;%1&apos; wirklisch löschen? Bissde da och sischor?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="542"/>
+        <location filename="overview.cpp" line="560"/>
         <source>Change Host Key?</source>
         <translation>Den Schlüssel von dem Reschnor Ã¤ndorn?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="542"/>
+        <location filename="overview.cpp" line="560"/>
         <source>Really change the key of host &apos;%1&apos;?</source>
         <translation>Wirglich den Schlüssel von dem Reschnor &apos;%1&apos; Ã¤ndorn? Gans sischor?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="547"/>
+        <location filename="overview.cpp" line="565"/>
         <source>The new key of this host could only be generated with %1 bits entropy. Store anyway?</source>
         <translation>Dor Schlüssel von der Gisde hat nur %1 zufällige Bids. Das is a bissl wenisch. Drodsdem schbeichorn?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="558"/>
+        <location filename="overview.cpp" line="576"/>
         <source>Import Key from File</source>
         <translation>Schlüssel aus nor Dadai holen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="567"/>
+        <location filename="overview.cpp" line="585"/>
         <source>Unable to open file %1 for reading: %2</source>
         <translation>Gann de Dadai %1 nisch lesen. Des iss jedsd geene Ordografieschwäche, sondern: %2</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="579"/>
+        <location filename="overview.cpp" line="597"/>
         <source>This is not a host key file.</source>
         <translation>Das is abor doch gar ge Schlüssel! Willsde misch verarschen?</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="584"/>
+        <location filename="overview.cpp" line="602"/>
         <source>This host key file does not contain a valid host name.</source>
         <translation>De Schlüsseldadai had nen gans seldsamen Reschnornamen da drin. Desdorweschen gannsch die ni nehm.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="589"/>
+        <location filename="overview.cpp" line="607"/>
         <source>This host key file does not contain a valid key.</source>
         <translation>De Dadai is a bissl gabudd. Die mussde nochmal holen, ich gann die so ned lesen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="594"/>
+        <location filename="overview.cpp" line="612"/>
         <source>The key check sum did not match. Please get a clean copy of the host key file.</source>
         <translation>Isch hab da ma nachgereschned. De Scheggsumme vom Schlüssel is falsch. Das gannsch Dir so ni abnehm.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="612"/>
+        <location filename="overview.cpp" line="630"/>
         <source>This host cannot be exported.</source>
         <translation>Den Reschnor gannsch ni schbeichorn.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="617"/>
+        <location filename="overview.cpp" line="635"/>
         <source>Export Key to File</source>
         <translation>Schlüssel als Dadei ablechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="626"/>
+        <location filename="overview.cpp" line="644"/>
         <source>Unable to open file %1 for writing: %2</source>
         <translation>Gann de Dadai %1 nicht zum Schreiben offmachen weil: %2</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="146"/>
+        <location filename="overview.cpp" line="154"/>
         <source>Order Items</source>
         <translation>Ne Beschdellung anlegn.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="149"/>
+        <location filename="overview.cpp" line="157"/>
         <source>Sell Items</source>
         <translation>Vorkofen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="156"/>
+        <location filename="overview.cpp" line="164"/>
         <source>Order List</source>
         <translation>Beschdelllisde</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="160"/>
+        <location filename="overview.cpp" line="168"/>
         <source>-select mode-</source>
         <translation>-wähl ma was aus-</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="161"/>
+        <location filename="overview.cpp" line="169"/>
         <source>All Orders</source>
         <translation>Alle Beschdellungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="162"/>
+        <location filename="overview.cpp" line="170"/>
         <source>Open Orders</source>
         <translation>Offene Beschdellungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="163"/>
+        <location filename="overview.cpp" line="171"/>
         <source>Outstanding Payments</source>
         <translation>Wo noch ni bezahld is</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="164"/>
+        <location filename="overview.cpp" line="172"/>
         <source>Outstanding Refunds</source>
         <translation>Wo was zurügerschdadded werden muss</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="169"/>
         <source>Payment</source>
-        <translation>Bezahln</translation>
+        <translation type="obsolete">Bezahln</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="170"/>
         <source>Refund</source>
-        <translation>Zurügerschdadden</translation>
+        <translation type="obsolete">Zurügerschdadden</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="172"/>
         <source>Print Tickets</source>
-        <translation>Eindriddsgarde druggn</translation>
+        <translation type="obsolete">Eindriddsgarde druggn</translation>
     </message>
     <message>
         <location filename="overview.cpp" line="173"/>
         <source>Print Bill</source>
-        <translation>Reschnung druggn</translation>
+        <translation type="obsolete">Reschnung druggn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="663"/>
+        <location filename="overview.cpp" line="681"/>
         <source>Amount</source>
         <translation>Anzahl</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="683"/>
+        <location filename="overview.cpp" line="701"/>
         <source>Select Event to order Ticket</source>
         <translation>Wähl ma ne Voranschdaldung aus um ne Garde zu beschdelln</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="697"/>
+        <location filename="overview.cpp" line="715"/>
         <source>Select</source>
         <translation>Auswähln</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="699"/>
+        <location filename="overview.cpp" line="717"/>
         <source>Cancel</source>
         <translation>Ni machen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="734"/>
+        <location filename="overview.cpp" line="752"/>
         <source>There is nothing in the order. Ignoring it.</source>
         <translation>Da is doch gar nischd drin. Isch mach das jedsd ni!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="738"/>
+        <location filename="overview.cpp" line="756"/>
         <source>Please chose a customer first!</source>
         <translation>Du mussd schon nen Gunden auswähln, sonsd wees isch doch ni wer&apos;s griechen soll!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="774"/>
+        <location filename="overview.cpp" line="792"/>
         <source>The request failed.</source>
         <translation>De Anfrache is schiefgegangen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="778"/>
+        <location filename="overview.cpp" line="796"/>
         <source>A problem occurred during the order: %1</source>
         <translation>Isch hadde nen Broblem mit dor Beschdellung: %1</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="177"/>
+        <location filename="overview.cpp" line="189"/>
         <source>Entrance</source>
         <translation>Einlassgondrolle</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="814"/>
+        <location filename="overview.cpp" line="832"/>
         <source>Ticket Ok</source>
         <translation>Eindriddsgarde is in Ordnung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="818"/>
+        <location filename="overview.cpp" line="836"/>
         <source>Ticket Already Used</source>
         <translation>Die habsch schonmal gesehn, da will eener bedrüchen.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="822"/>
+        <location filename="overview.cpp" line="840"/>
         <source>Ticket Not Paid</source>
         <translation>Eindriddsgarde is nisch bedsahld. Schiggn ma&apos; an de Gasse.</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="101"/>
+        <location filename="overview.cpp" line="109"/>
         <source>Ticket Summary...</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="overview.cpp" line="173"/>
+        <source>Undelivered Orders</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="180"/>
+        <source>Update</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Status</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Total</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Paid</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="overview.cpp" line="862"/>
+        <source>Customer</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MPasswordChange</name>
     <message>
-        <location filename="overview.cpp" line="840"/>
+        <location filename="overview.cpp" line="908"/>
         <source>Change my password</source>
         <translation>Mei eechnes Bassword Ã¤ndorn</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="842"/>
+        <location filename="overview.cpp" line="910"/>
         <source>Reset password of user %1</source>
         <translation>Bassword vom Nudsor %1 zurügsedsen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="846"/>
+        <location filename="overview.cpp" line="914"/>
         <source>Old Password:</source>
         <translation>Aldes Bassword:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="850"/>
+        <location filename="overview.cpp" line="918"/>
         <source>New Password:</source>
         <translation>Neies Bassword:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="853"/>
+        <location filename="overview.cpp" line="921"/>
         <source>Repeat Password:</source>
         <translation>Nochma neies Bassword:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="861"/>
+        <location filename="overview.cpp" line="929"/>
         <source>Set Password</source>
         <translation>Bassword sedsen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="863"/>
+        <location filename="overview.cpp" line="931"/>
         <source>Cancel</source>
         <translation>Vorgisses, ni sedsen</translation>
     </message>
 </context>
 <context>
+    <name>MTicket</name>
+    <message>
+        <location filename="order.cpp" line="407"/>
+        <source>.</source>
+        <comment>decimal dot</comment>
+        <translation type="unfinished">,</translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="432"/>
+        <source>bought</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="433"/>
+        <source>to refund</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="434"/>
+        <source>used</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="435"/>
+        <source>reserved</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="436"/>
+        <source>ok</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="437"/>
+        <source>sale only</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="438"/>
+        <source>order only</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="439"/>
+        <source>too late: event over</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="440"/>
+        <source>no more tickets</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="441"/>
+        <source>event cancelled</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="442"/>
+        <source>no such event</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="order.cpp" line="443"/>
+        <source>invalid</source>
+        <comment>ticket state</comment>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MTicketView</name>
+    <message>
+        <location filename="orderwin.cpp" line="166"/>
+        <source>Preview Tickets</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MUserHost</name>
     <message>
         <location filename="user.cpp" line="303"/>
@@ -1499,7 +1852,7 @@ At least %1 Bits of random are required.</source>
         <translation>Isch gann misch ned anmälden.</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="325"/>
+        <location filename="webrequest.cpp" line="326"/>
         <source>Error parsing EventList XML data (line %1 column %2): %3</source>
         <translation>Isch gann des XML von dor EventList no vorschdehn (Zeile %1, Schbalde %2) weil: %3</translation>
     </message>
@@ -1509,25 +1862,30 @@ At least %1 Bits of random are required.</source>
         <translation>Gann Bassword ni&apos; Ã¤ndorn, das alde war falsch!</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="348"/>
+        <location filename="webrequest.cpp" line="350"/>
         <source>Error parsing RoomList XML data (line %1 column %2): %3</source>
         <translation>Isch gann des XML von dor RoomList no vorschdehn (Zeile %1, Schbalde %2) weil: %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="371"/>
+        <location filename="webrequest.cpp" line="374"/>
         <source>Error parsing UserList XML data (line %1 column %2): %3</source>
         <translation>Isch gann des XML von dor UserList no vorschdehn (Zeile %1, Schbalde %2) weil: %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="394"/>
+        <location filename="webrequest.cpp" line="398"/>
         <source>Error parsing HostList XML data (line %1 column %2): %3</source>
         <translation>Isch gann des XML von dor HostList no vorschdehn (Zeile %1, Schbalde %2) weil: %3</translation>
     </message>
     <message>
-        <location filename="webrequest.cpp" line="417"/>
+        <location filename="webrequest.cpp" line="422"/>
         <source>Error parsing CustomerList XML data (line %1 column %2): %3</source>
         <translation>Isch gann des XML von dor CustomerList no vorschdehn (Zeile %1, Schbalde %2) weil: %3</translation>
     </message>
+    <message>
+        <location filename="webrequest.cpp" line="446"/>
+        <source>Error parsing OrderList XML data (line %1 column %2): %3</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>initkey</name>
diff --git a/src/ticketrender.cpp b/src/ticketrender.cpp
new file mode 100644 (file)
index 0000000..c5fe6e9
--- /dev/null
@@ -0,0 +1,470 @@
+//
+// C++ Implementation: odtrender
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2008
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "ticketrender.h"
+
+#include <QDir>
+#include <QFile>
+#include <QPaintDevice>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QList>
+#include <QMap>
+#include <QStringList>
+#include <QFontDatabase>
+#include <QImage>
+#include <QPainter>
+
+#include "zip/qunzip.h"
+#include "zip/qzip.h"
+#include "code39.h"
+#include "order.h"
+
+
+class MTicketRendererPrivate
+{
+       protected:
+               friend class MTicketRenderer;
+               
+               MTicketRendererPrivate(QString file,MTicketRenderer*p);
+               ~MTicketRendererPrivate();
+               
+               //part of the constructor
+               void prepare(QUnZip&);
+               
+               //called by MTicketRenderer
+               bool render(const MTicket&,QPaintDevice&,QPainter*,QPointF);
+               
+               //called by MTicketRenderer
+               QSizeF ticketSize(const QPaintDevice&);
+               
+       private:
+               MTicketRenderer*parent;
+               //internal font-IDs
+               QList<int> fdb;
+               //image cache:
+               QMap<QString,QImage> idb;
+               //XML template cache (template.xml)
+               QDomDocument txml;
+               //contains the unit of measurement
+               QString unit;
+               //contains the size of the ticket in "unit"
+               QSizeF tsize;
+               //after constructor: contains whether this object is correctly initialized
+               bool canrender;
+               
+               //does the actual rendering work
+               void render(QDomElement&,const MTicket&,QPaintDevice&,QPainter*,QPointF);
+               
+               //renders a single line
+               QString renderLine(const MTicket&,QString);
+               
+               //gets variable content from the ticket
+               QString getVariable(const MTicket&,QString);
+               
+               //parses element to extract offset
+               QPointF getoffset(QDomElement&,bool);
+               
+               //parses element to extract size
+               QSizeF getsize(QDomElement&,bool);
+               
+               //converts a point to "natural" coordinates
+               QPointF tonatural(const QPaintDevice&,QPointF);
+               
+               //converts a size to "natural" coordinates
+               QSizeF tonatural(const QPaintDevice&,QSizeF);
+};
+
+MTicketRenderer::MTicketRenderer(QString file)
+{
+       d=new MTicketRendererPrivate(file,this);
+}
+
+MTicketRendererPrivate::MTicketRendererPrivate(QString file,MTicketRenderer*p)
+{
+       parent=p;
+       canrender=false;
+       //open ZIP
+       QUnZip temp;
+       QFile tfile(file);
+       if(tfile.open(QIODevice::ReadOnly))temp.open(&tfile);
+       else return;
+       prepare(temp);
+       temp.close();
+       tfile.close();
+       qDebug("Ticket Renderer initialized: %s",canrender?"ready!":"error, can't render.");
+}
+
+void MTicketRendererPrivate::prepare(QUnZip&temp)
+{
+       //make sure this is a valid ZIP file
+       if(!temp.locateFile("template.xml")){
+               qDebug("Ticket renderer: can't find template.xml");
+               canrender=false;
+               return;
+       }
+       //load XML
+       QBuffer buffer;
+       buffer.open(QBuffer::ReadWrite);
+       temp.getCurrentFile(buffer);
+       if(!txml.setContent(buffer.data())){
+               qDebug("Ticket renderer: can't parse template.xml - XML fault.");
+               canrender=false;
+               return;
+       }
+       //assume we can render now
+       canrender=true;
+       //parse document element
+       QDomElement doc=txml.documentElement();
+       unit=doc.attribute("unit","mm");
+       if(unit!="mm"&&unit!="in"){
+               qDebug("Ticket renderer: illegal unit in template.xml.");
+               canrender=false;
+               return;
+       }
+       tsize=getsize(doc,true);
+       if(!canrender)return;
+       //check for fonts
+       QDomNodeList nl=txml.elementsByTagName("LoadFont");
+       QStringList fndb;
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               QString fn=el.attribute("file");
+               if(fn==""){
+                       qDebug("Ticket renderer warning: Font element without file attribute. Line %i Column %i.",el.lineNumber(),el.columnNumber());
+                       continue;
+               }
+               if(fndb.contains(fn)){
+                       qDebug("Ticket renderer warning: Font file %s was loaded more than once. Line %i Column %i.",fn.toAscii().data(),el.lineNumber(),el.columnNumber());
+                       continue;
+               }
+               fndb.append(fn);
+               if(!temp.locateFile(fn)){
+                       qDebug("Ticket renderer warning: Font element references unknown file. Line %i Column %i.",el.lineNumber(),el.columnNumber());
+                       continue;
+               }
+               QBuffer buffer;
+               temp.getCurrentFile(buffer);
+               int fid=QFontDatabase::addApplicationFontFromData(buffer.data());
+               if(fid<0){
+                       qDebug("Ticket renderer warning: Font could not be loaded: %s",fn.toAscii().data());
+                       continue;
+               }
+               fdb.append(fid);
+       }
+       //check for pictures
+       nl=txml.elementsByTagName("Picture");
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               QString fn=el.attribute("file");
+               if(fn==""){
+                       qDebug("Ticket renderer error: Picture element without file attribute. Line %i Column %i.",el.lineNumber(),el.columnNumber());
+                       //failed pictures are fatal
+                       canrender=false;
+                       return;
+               }
+               if(idb.contains(fn))continue;
+               if(!temp.locateFile(fn)){
+                       qDebug("Ticket renderer error: Picture element references unknown file. Line %i Column %i.",el.lineNumber(),el.columnNumber());
+                       //failed pictures are fatal
+                       canrender=false;
+                       return;
+               }
+               QBuffer buffer;
+               temp.getCurrentFile(buffer);
+               QImage img;
+               if(!img.loadFromData(buffer.data())){
+                       qDebug("Ticket renderer error: Picture file %s could not be interpreted.",fn.toAscii().data());
+                       //failed pictures are fatal
+                       canrender=false;
+                       return;
+               }
+               idb.insert(fn,img);
+       }
+}
+
+MTicketRenderer::~MTicketRenderer()
+{
+       delete d;
+       d=0;
+}
+MTicketRendererPrivate::~MTicketRendererPrivate()
+{
+       //delete fonts
+       for(int i=0;i<fdb.size();i++)
+               QFontDatabase::removeApplicationFont(fdb[i]);
+}
+
+bool MTicketRenderer::render(const MTicket&ticket,QPaintDevice&pdev,QPainter*painter,QPointF offset)
+{
+       return d->render(ticket,pdev,painter,offset);
+}
+
+bool MTicketRendererPrivate::render(const MTicket&ticket,QPaintDevice&pdev,QPainter*painter,QPointF offset)
+{
+       //sanity check
+       if(!canrender){
+               qDebug("Ticket Renderer: render called, but can't render.");
+               return false;
+       }
+       //actually render
+       QDomElement el=txml.documentElement();
+       render(el,ticket,pdev,painter,offset);
+       //return result (canrender may be changed by renderer
+       return canrender;
+}
+
+QPointF MTicketRendererPrivate::getoffset(QDomElement&el,bool isfatal)
+{
+       QStringList off=el.attribute("offset").split(" ");
+       if(off.size()!=2){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QPointF();
+       }
+       QPointF ret;
+       bool b;
+       ret.setX(off[0].toDouble(&b));
+       if(!b){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QPointF();
+       }
+       ret.setY(off[1].toDouble(&b));
+       if(!b){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal offset in %s at line %i column %i.",el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QPointF();
+       }
+       return ret;
+}
+
+QSizeF MTicketRendererPrivate::getsize(QDomElement&el,bool isfatal)
+{
+       QStringList lst=el.attribute("size").split(" ");
+       if(lst.size()!=2){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal size (%i items) in %s at line %i column %i.",lst.size(),el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QSizeF();
+       }
+       QSizeF ret;
+       bool b;
+       ret.setWidth(lst[0].toDouble(&b));
+       if(!b){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal size (invalid width) in %s at line %i column %i.",el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QSizeF();
+       }
+       ret.setHeight(lst[1].toDouble(&b));
+       if(!b){
+               if(isfatal){
+                       qDebug("Ticket renderer error: Illegal size (invalid height) in %s at line %i column %i.",el.tagName().toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+               }
+               return QSizeF();
+       }
+       return ret;
+}
+
+QPointF MTicketRendererPrivate::tonatural(const QPaintDevice&dev,QPointF p)
+{
+       double fac;
+       if(unit=="mm")fac=25.4;
+       else fac=1.0;
+       p.setX(p.x()*dev.logicalDpiX()/fac);
+       p.setY(p.y()*dev.logicalDpiY()/fac);
+       return p;
+}
+
+QSizeF MTicketRendererPrivate::tonatural(const QPaintDevice&dev,QSizeF s)
+{
+       double fac;
+       if(unit=="mm")fac=25.4;
+       else fac=1.0;
+       s.setWidth(s.width()*dev.logicalDpiX()/fac);
+       s.setHeight(s.height()*dev.logicalDpiY()/fac);
+       return s;
+}
+
+void MTicketRendererPrivate::render(QDomElement&sup, const MTicket&tick, QPaintDevice&pdev, QPainter*painter, QPointF offset)
+{
+       //initialize painter
+       QPainter *paint;
+       if(painter)
+               paint=painter;
+       else
+               paint=new QPainter(&pdev);
+       QPointF noff=tonatural(pdev,offset);
+       QSizeF nsize=tonatural(pdev,tsize);
+       paint->setClipRect(QRectF(noff,nsize));
+       //parse file
+       QDomNodeList nl=sup.childNodes();
+       for(int i=0;i<nl.size();i++){
+               QDomElement el=nl.at(i).toElement();
+               if(el.isNull())continue;
+               QString enm=el.tagName();
+               if(enm=="LoadFont"){
+                       //ignore, already done in constructor
+               }else
+               if(enm=="Picture"){
+                       //get attributes
+                       QPointF off=getoffset(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       QSizeF sz=getsize(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       //TODO: make use of smooth
+//                     int smooth=el.attribute("smooth","1").toInt();
+                       QString fname=el.attribute("file");
+                       //paint
+                       paint->drawImage(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),idb[fname]);
+               }else
+               if(enm=="Text"){
+                       //get attributes
+                       QPointF off=getoffset(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       QSizeF sz=getsize(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       //get text
+                       QString text=renderLine(tick,el.text().trimmed());
+                       //get font; TODO: introduce weight and italic settings
+                       QString font=el.attribute("font","Helvetica");
+                       int size=el.attribute("fontsize","10").toInt();
+                       if(size<1)size=10;
+                       paint->setFont(QFont(font,size));
+                       //get alignment
+                       int flag=0;
+                       QString al=el.attribute("align","left");
+                       if(al=="left")flag=Qt::AlignLeft;else
+                       if(al=="right")flag=Qt::AlignRight;
+                       else flag=Qt::AlignHCenter;
+                       al=el.attribute("valign","top");
+                       if(al=="top")flag|=Qt::AlignTop;else
+                       if(al=="bottom")flag|=Qt::AlignBottom;
+                       else flag|=Qt::AlignVCenter;
+                       //render
+                       paint->drawText(QRectF(tonatural(pdev,off)+noff,tonatural(pdev,sz)),flag,text);
+               }else
+               if(enm=="Barcode"){
+                       //get attributes
+                       QPointF off=getoffset(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       QSizeF sz=getsize(el,true);
+                       if(!canrender){
+                               return;
+                       }
+                       QString cd=getVariable(tick,"TICKETID");
+                       //paint
+                       //TODO: find a way to switch off antialiasing
+                       QRectF rect(tonatural(pdev,off)+noff,tonatural(pdev,sz));
+                       paint->drawImage(rect,code39(cd));
+               }else{
+                       qDebug("Ticket renderer error: unknown element %s in ticket template at line %i column %i.",enm.toAscii().data(),el.lineNumber(),el.columnNumber());
+                       canrender=false;
+                       return;
+               }
+       }
+       if(!painter)
+               delete paint;
+}
+
+QString MTicketRendererPrivate::renderLine(const MTicket&tick,QString line)
+{
+       QString ret,vname;
+       bool isvar=false;
+       static QString vc="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       //scan characters
+       for(int i=0;i<line.size();i++){
+               //are we currently inside a variable name?
+               if(isvar){
+                       //end of var?
+                       if(line[i]=='@'){
+                               if(vname=="")ret+="@";
+                               else{
+                                       //this is a variable, get value
+                                       ret+=getVariable(tick,vname);
+                               }
+                               //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="";
+                       }
+               }else{//not inside variable name
+                       //is this the start of a var?
+                       if(line[i]=='@'){
+                               isvar=true;
+                               vname="";
+                       }else{
+                               ret+=line[i];
+                       }
+               }
+       }
+       //anything left over?
+       if(isvar){
+               //reset
+               ret+="@"+vname;
+       }
+       //return transformed line
+       return ret;
+}
+
+QString MTicketRendererPrivate::getVariable(const MTicket&tick,QString var)
+{
+       if(var=="TICKETID")return tick.ticketID();
+       if(var=="PRICE")return tick.priceString();
+       if(var=="DATETIME")return tick.event().startTimeString();
+       if(var=="ROOM")return tick.event().room();
+       if(var=="TITLE")return tick.event().title();
+       if(var=="ARTIST")return tick.event().artist();
+       return "";
+}
+
+QSizeF MTicketRenderer::ticketSize(const QPaintDevice&dev)
+{
+       return d->ticketSize(dev);
+}
+
+QSizeF MTicketRendererPrivate::ticketSize(const QPaintDevice&dev)
+{
+       return tonatural(dev,tsize);
+}
diff --git a/src/ticketrender.h b/src/ticketrender.h
new file mode 100644 (file)
index 0000000..b07ce48
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// C++ Interface: odtrender
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2008
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_TICKETRENDER_H
+#define MAGICSMOKE_TICKETRENDER_H
+
+#include <QString>
+#include <QPointF>
+#include <QSizeF>
+
+class MTicketRendererPrivate;
+class MTicket;
+class QPaintDevice;
+class QPainter;
+
+/**abstract base class for all ODT rendering classes*/
+class MTicketRenderer
+{
+       public:
+               /**instantiates a renderer loaded from template file*/
+               MTicketRenderer(QString file);
+               /**deletes the renderer*/
+               virtual ~MTicketRenderer();
+               
+               /**renders the ticket; returns whether the rendering was successful*/
+               virtual bool render(const MTicket&ticket,QPaintDevice&pdev,QPainter*painter=0,QPointF offset=QPointF());
+               
+               /**returns the size of the ticket in the coordinates of the specified paint device (used for preview)*/
+               virtual QSizeF ticketSize(const QPaintDevice&);
+               
+       protected:
+               friend class MTicketRendererPrivate;
+               
+       private:
+               MTicketRendererPrivate*d;
+};
+
+#endif
index c12d5b3..b22d539 100644 (file)
@@ -13,6 +13,7 @@
 #include "webrequest.h"
 #include "keygen.h"
 #include "hmac.h"
+#include "main.h"
 
 #include <QEventLoop>
 #include <QTimer>
 #include <QDomNodeList>
 #include <QDomElement>
 #include <QSettings>
+#include <QDir>
 
-MWebRequest::MWebRequest()
+MWebRequest::MWebRequest(QString pid)
 {
+       profileid=pid;
        webtimeout=30000;
        finid=0;finerr=fin=false;
        proxyport=-1;
@@ -35,6 +38,21 @@ MWebRequest::MWebRequest()
 }
 MWebRequest::~MWebRequest(){}
 
+QString MWebRequest::dataDir()const
+{
+       QString dd="profile."+profileid;
+       QDir dir(::dataDir);
+       if(!dir.exists(dd))
+               if(!dir.mkpath(dd))
+                       qDebug("Warning: oh dir! Can't create my data directory!");
+       return ::dataDir+"/"+dd;
+}
+
+QString MWebRequest::settingsGroup()const
+{
+       return "profsettings/"+profileid;
+}
+
 bool MWebRequest::request(QString hreq,QByteArray data)
 {
        //set up request
@@ -318,6 +336,7 @@ QList<MEvent> MWebRequest::getAllEvents()
 {
        errstr="";
        if(!request("geteventlist"))return QList<MEvent>();
+       if(responseStatus()!=Ok)return QList<MEvent>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -341,6 +360,7 @@ QList<MRoom> MWebRequest::getAllRooms()
 {
        errstr="";
        if(!request("getroomdata","<GetRooms detail=\"basic\"/>"))return QList<MRoom>();
+       if(responseStatus()!=Ok)return QList<MRoom>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -364,6 +384,7 @@ QList<MUser> MWebRequest::getAllUsers()
 {
        errstr="";
        if(!request("getusers",""))return QList<MUser>();
+       if(responseStatus()!=Ok)return QList<MUser>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -387,6 +408,7 @@ QList<MHost> MWebRequest::getAllHosts()
 {
        errstr="";
        if(!request("gethosts",""))return QList<MHost>();
+       if(responseStatus()!=Ok)return QList<MHost>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -410,6 +432,7 @@ QList<MCustomer> MWebRequest::getAllCustomers()
 {
        errstr="";
        if(!request("getcustomerlist",""))return QList<MCustomer>();
+       if(responseStatus()!=Ok)return QList<MCustomer>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -433,6 +456,7 @@ QList<MOrder> MWebRequest::getAllOrders()
 {
        errstr="";
        if(!request("getorderlist",""))return QList<MOrder>();
+       if(responseStatus()!=Ok)return QList<MOrder>();
        //parse return document
        QDomDocument doc;
        QString msg;int ln,cl;
@@ -487,3 +511,90 @@ QString MWebRequest::hostName()
 {
        return hostname;
 }
+
+QString MWebRequest::getTemplate(QString f)
+{
+       //syntax check
+       f=f.toLower();
+       QRegExp fregexp("[a-z0-9_\\.]+");
+       if(!fregexp.exactMatch(f))return "";
+       //do we need an update?
+       QString dname=dataDir()+"/templates/";
+       QSettings set;
+       set.beginGroup("templates/"+profileid);
+       QDateTime last=QDateTime::fromTime_t(set.value("lastupdate",0).toInt()+300);
+       if(last<QDateTime::currentDateTime()){do{
+               //get local info
+               set.beginGroup("checksum");
+               QStringList files=set.childKeys();
+               QMap<QString,QString> fmap;
+               for(int i=0;i<files.size();i++)
+                       fmap.insert(files[i],set.value(files[i]).toString());
+               set.endGroup();
+               //get remote info
+               if(!request("gettemplatelist",""))break;
+               if(responseStatus()!=Ok)break;
+               QDomDocument doc;
+               if(!doc.setContent(responseBody()))break;
+               //prune old stuff
+               set.remove("checksum");
+               //scan and create new list
+               QDomNodeList nl=doc.elementsByTagName("Template");
+               QMap<QString,QString>nfmap;
+               for(int i=0;i<nl.size();i++){
+                       QDomElement el=nl.at(i).toElement();
+                       if(el.isNull())continue;
+                       QString f=el.attribute("name","");
+                       QString h=el.attribute("hash","");
+                       if(f=="" || !fregexp.exactMatch(f))continue;
+                       nfmap.insert(f,h);
+                       set.setValue("checksum/"+f,h);
+               }
+               //compare old with new list, delete changed files
+               for(int i=0;i<files.size();i++){
+                       if(!nfmap.contains(files[i]))
+                               QFile(dname+"/"+f).remove();
+                       else
+                       if(nfmap[files[i]]!=fmap[files[i]])
+                               QFile(dname+"/"+f).remove();
+               }
+       }while(false);}
+       //check that it is a valid template file
+       if(!set.contains("checksum/"+f))return "";
+       //get the file if it does not exist
+       if(!QFile(dname+"/"+f).exists()){
+               //make sure directory exists
+               QDir(dataDir()).mkpath("templates");
+               //retrieve template file
+               if(!request("gettemplate",f.toAscii()))
+                       return "";
+               if(responseStatus()!=Ok)
+                       return "";
+               QFile fl(dname+"/"+f);
+               if(!fl.open(QIODevice::WriteOnly))
+                       return "";
+               fl.write(responseBody());
+               fl.close();
+       }
+       //return file name
+       return dname+"/"+f;
+}
+
+bool MWebRequest::setTemplate(QString n,QString f)
+{
+       //sanity check
+       QRegExp fregexp("[a-z0-9_\\.]+");
+       if(!fregexp.exactMatch(n))return false;
+       //get content
+       QFile fl(f);
+       if(!fl.open(QIODevice::ReadOnly))
+               return false;
+       QByteArray ba=fl.readAll();
+       fl.close();
+       //send to server
+       if(!request("settemplate",n.toAscii()+"\n"+ba))
+               return false;
+       if(responseStatus()!=Ok)
+               return false;
+       return true;
+}
index 62f4e1c..546542d 100644 (file)
@@ -34,9 +34,15 @@ class MWebRequest:public QObject
 {
        Q_OBJECT
        public:
-               MWebRequest();
+               MWebRequest(QString profileid);
                ~MWebRequest();
                
+               /**returns the data directory of this profile; it makes sure the directory exists*/
+               QString dataDir()const;
+               
+               /**returns the settings group of this profile; this group is free to be filled by other entities, it is not used by the webrequest itself or the mainwindow*/
+               QString settingsGroup()const;
+               
                /**generic request method, use the macro functions if possible; this function blocks until the request either succeeds, times out or fails; returns false if the request failed or timed out*/
                bool request(QString requestName,QByteArray data=QByteArray());
                /**returns the body returned by the server for the last request*/
@@ -91,6 +97,12 @@ class MWebRequest:public QObject
                /**return current host name of this session*/
                QString hostName();
                
+               /**return the (local) file name of a template, queries the DB if necessary - cache timeout is 5 minutes; returns an empty string if the template does not exist*/
+               QString getTemplate(QString);
+               
+               /**sends the template file to the server, returns whether it was successful*/
+               bool setTemplate(QString templatename,QString localfilename);
+               
        public slots:
                /**set how long to wait for a web request*/
                void setTimeout(int);
@@ -137,6 +149,8 @@ class MWebRequest:public QObject
                int finid,waitid;
                //session timeout for relogin
                qint64 sessiontimeout;
+               //profile name for lookups
+               QString profileid;
                
                /**used by login and relogin to do the actual work*/
                bool doLogin();
index e0ac3f4..d2a352a 100644 (file)
@@ -443,7 +443,20 @@ function getOrderListXml()
        }
        $xml->appendChild($doc);
        //output
+       header("X-MagicSmoke-Status: Ok");
        print($xml->saveXml());
 }
 
+function getOrderXml($oid)
+{
+       $order=new Order($oid);
+       if($order->isValid()){
+               header("X-MagicSmoke-Status: Ok");
+               $order->dumpXml();
+       }else{
+               header("X-MagicSmoke-Status: Error");
+               die(tr("No such orderID in database."));
+       }
+}
+
 ?>
\ No newline at end of file
index 0239af3..560a156 100644 (file)
@@ -38,7 +38,7 @@ function getTemplate($fname)
 
 function setTemplate($data)
 {
-       $pos=strpos($data,'\n');
+       $pos=strpos($data,"\n");
        if($pos===false){
                header("X-MagicSmoke-Status: Error");
                die(tr("Unable to find file name"));
index b941ed0..1614254 100644 (file)
@@ -23,7 +23,7 @@ $ALLOWEDREQUESTS=array(
        tr("geteventlist"),tr("geteventdata"),tr("seteventdata"),tr("eventsummary"), //event infos
        tr("getroomdata"),tr("setroomdata"),//room infos
        tr("getcustomerlist"),tr("getcustomer"),tr("setcustomer"), //customer info
-       tr("checkorder"),tr("createorder"),tr("createsale"),tr("getorderlist"), //sell/order stuff
+       tr("checkorder"),tr("createorder"),tr("createsale"),tr("getorderlist"),tr("getorder"), //sell/order stuff
        tr("gettemplatelist"),tr("gettemplate"),tr("settemplate") //templates
 );
 /**contains the low-level request name from the client*/
@@ -280,6 +280,11 @@ if($SMOKEREQUEST=="getorderlist"){
        getOrderListXml();
        exit();
 }
+//get a single order
+if($SMOKEREQUEST=="getorder"){
+       getOrderXml(trim($REQUESTDATA)+0);
+       exit();
+}
 
 
 //EOF