can show event details now
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 7 Oct 2007 16:21:08 +0000 (16:21 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 7 Oct 2007 16:21:08 +0000 (16:21 +0000)
git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@44 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

12 files changed:
doc/prog_protocol.html
src/event.cpp
src/event.h
src/eventedit.cpp
src/eventedit.h
src/smoke_de.ts
src/smoke_de_SAX.ts
src/webrequest.cpp
src/webrequest.h
www/inc/event.php
www/inc/session.php
www/machine.php

index aebeeff..38775da 100644 (file)
@@ -100,7 +100,7 @@ The client sends its authentication data as XML:
 
 The authentication data is calculated using the hash-function mandated by the server. The HostAuth item is calculated using the HostChallenge and the hosts key. The UserAuth item is calculated using the UserChallenge and the users password. Both *Auth values are hexadecimal-encoded.<p>
 
-The result one single numeric item in the body that states the new session timeout in seconds (0 if the request failed). The status is "Ok" or "Unauthenticated" - in the latter case the session ID is deleted and the client needs to start with a <tt>startsession</tt> request again if it wants to retry.<p>
+The status is "Ok" or "Unauthenticated" - in the latter case the session ID is deleted and the client needs to start with a <tt>startsession</tt> request again if it wants to retry. If the request succeeds, the result body contains two numeric items (separated by a newline) that state the new session timeout  and the current time as a Unix timestamp (seconds sice epoch - 1Jan1970, 00:00 UTC).<p>
 
 A result of "Unauthenticated" can have multiple reasons: the timeout of the temporary session expired before the request was received, the authentication of the user failed, the user is not allowed to connect from this or an anonymous host, or the authentication of the host failed and the user is not allowed to connect from an anonymous host.
 
@@ -120,3 +120,55 @@ Special rights are:<br>
 <table frame="1" border="1">
 <tr><td>_admin</td><td>The user is an administrator and can automatically execute everything.</td></tr>
 </table>
+
+
+<h2>Event Related Requests</h2>
+
+<h3>Getting a List of Events</h3>
+
+The <tt>geteventlist</tt> transaction requests all events from the server. The response is a simple XML structure that contains only very basic data for each event:<p>
+
+<pre>
+&lt;EventList>
+  &lt;Event id="0" start="1190543432">blechsalat&lt;/Event>
+  &lt;Event id="1" start="1191419769">stringsalat&lt;/Event>
+&lt;/EventList>
+</pre>
+
+Each event is encapsulated in an <tt>Event</tt> tag. The events have no specific order. The <tt>id</tt> attribute contains the internal ID of the event that can be used to reference it in other requests. The <tt>start</tt> attribute contains the start time of the event as Unix timestamp. The text of the <tt>Event</tt> tag contains the title of the event.<p>
+
+<h3>Getting Detailed Event Data</h3>
+
+The <tt>geteventdata</tt> transaction returns detailed data about the event. The request body contains a space separated list of event IDs. The response looks like:<p>
+
+<pre>
+&lt;EventData>
+  &lt;Event id="0" start="1190543432" end="1190543532" capacity="25" defaultprice="1177" cancelled="false">
+    &lt;Title>blechsalat&lt;/Title>
+    &lt;Artist>Broken Blech&lt;/Artist>
+    &lt;Description>a lot of text containing encoded &amp;lt;b&amp;gt;HTML&amp;lt;/b&amp;gt; tags&lt;/Description>
+    &lt;Room>Invisible Library&lt;/Room>
+    &lt;CancelReason>a damned good one&lt;/CancelReason>
+  &lt;/Event>
+  &lt;Event id="1" start="1191419769" ...>
+  ...
+  &lt;/Event>
+&lt;/EventData>
+</pre>
+
+Attributes and tags:<br>
+<table frame="1" border="1">
+<tr><td>id</td><td>the ID of the event</td></tr>
+<tr><td>start</td><td>the start time as Unix timestamp</td></tr>
+<tr><td>end</td><td>the end time as Unix timestamp</td></tr>
+<tr><td>capacity</td><td>how many tickets may be sold for this event</td></tr>
+<tr><td>defaultprice</td><td>the default price for tickets as integer in cent (or penny or ...)</td></tr>
+<tr><td>cancelled</td><td>optional: "true" or "false" -- shows whether the event is cancelled, default is "false"</td></tr>
+<tr><td>Title</td><td>the title of the event</td></tr>
+<tr><td>Artist</td><td>the artist appearing</td></tr>
+<tr><td>Description</td><td>a description for the web page, may contain HTML</td></tr>
+<tr><td>Room</td><td>the room it is happening in (the room must exist in the list of available rooms)</td></tr>
+<tr><td>CancelReason</td><td>optional: if the event is cancelled, the reason for it (human readable)</td></tr>
+</table>
+
+If one of the requested events does not exist, it simply does not generate an <tt>Event</tt> block. It is permissible for the server to send an empty <tt>EventData</tt> tag if no data is available for the request.<p>
index a62b60a..be52a47 100644 (file)
 #include "event.h"
 #include "webrequest.h"
 
+#include <QCoreApplication>
+#include <QDomDocument>
+#include <QDomElement>
+
 MEvent::MEvent(MWebRequest*r,int id)
 {
        req=r;
        eventid=id;
+       m_starttime=QDateTime::currentDateTime().toTime_t();
+       m_endtime=m_starttime+3600;
+       m_capacity=10;
+       m_defaultprice=100;
+       m_valid=true;
        if(id>=0){
-               req->request("geteventdata",QString::number(id).toAscii());
+               //get data from server
+               if(!req->request("geteventdata",QString::number(id).toAscii())){
+                       m_valid=false;
+                       return;
+               }
+               //check server response state
+               if(req->responseStatus()!=MWebRequest::Ok){
+                       m_valid=false;
+                       return;
+               }
+               //parse data
+               QDomDocument doc;
+               if(!doc.setContent(req->responseBody())){
+                       m_valid=false;
+                       return;
+               }
+               QDomElement root=doc.documentElement();
+               //search for this event
+               QDomNodeList nl=root.elementsByTagName("Event");
+               for(int i=0;i<nl.size();i++){
+                       //filter
+                       QDomElement el=nl.at(i).toElement();
+                       if(el.isNull())continue;
+                       bool b;
+                       int eid=el.attribute("id","x").toInt(&b);
+                       if(eid!=eventid || !b)continue;
+                       //get attribute data
+                       m_starttime=el.attribute("start","0").toInt();
+                       m_endtime=el.attribute("end","0").toInt();
+                       m_capacity=el.attribute("capacity","0").toInt();
+                       m_defaultprice=el.attribute("defaultprice","0").toInt();
+                       bool iscancel=el.attribute("cancelled","false")=="true";
+                       //get title
+                       QDomNodeList nl2=el.elementsByTagName("Title");
+                       if(nl2.size()>0){
+                               QDomElement el2=nl2.at(0).toElement();
+                               if(!el2.isNull())
+                                       m_title=el2.text();
+                       }
+                       //get artist
+                       nl2=el.elementsByTagName("Artist");
+                       if(nl2.size()>0){
+                               QDomElement el2=nl2.at(0).toElement();
+                               if(!el2.isNull())
+                                       m_artist=el2.text();
+                       }
+                       //get description
+                       nl2=el.elementsByTagName("Description");
+                       if(nl2.size()>0){
+                               QDomElement el2=nl2.at(0).toElement();
+                               if(!el2.isNull())
+                                       m_description=el2.text();
+                       }
+                       //get room
+                       nl2=el.elementsByTagName("Room");
+                       if(nl2.size()>0){
+                               QDomElement el2=nl2.at(0).toElement();
+                               if(!el2.isNull())
+                                       m_roomid=el2.text().trimmed();
+                       }
+                       //get cancel reason
+                       nl2=el.elementsByTagName("CancelReason");
+                       if(nl2.size()>0){
+                               QDomElement el2=nl2.at(0).toElement();
+                               if(!el2.isNull())
+                                       m_cancelreason=el2.text().trimmed();
+                       }
+                       if(iscancel){
+                               if(m_cancelreason=="")m_cancelreason=" ";
+                       }else{
+                               m_cancelreason="";
+                       }
+               }
        }
 }
 
@@ -29,6 +110,16 @@ void MEvent::save()
 {
 }
 
-QString MEvent::title()
+QRegExp MEvent::priceRegExp()const
+{
+       return QRegExp(QCoreApplication::translate("MEvent","[0-9]+\\.[0-9]{2}","price validator regexp"));
+}
+
+QString MEvent::priceString()const
 {
+       QString ret=QString::number(m_defaultprice/100);
+       ret+=QCoreApplication::translate("MEvent",".","price decimal dot");
+       ret+=QString::number((m_defaultprice/10)%10);
+       ret+=QString::number(m_defaultprice%10);
+       return ret;
 }
\ No newline at end of file
index 396a179..928f18f 100644 (file)
@@ -25,7 +25,21 @@ class MEvent
                
                void save();
                
-               QString title();
+               QString title()const{return m_title;}
+               QString artist()const{return m_artist;}
+               QString description()const{return m_description;}
+               int startTime()const{return m_starttime;}
+               int endTime()const{return m_endtime;}
+               QString room()const{return m_roomid;}
+               int capacity()const{return m_capacity;}
+               int price()const{return m_defaultprice;}
+               bool isCancelled()const{return !m_cancelreason.isEmpty();}
+               QString cancelReason()const{return m_cancelreason.trimmed();}
+               
+               QString priceString()const;
+               QRegExp priceRegExp()const;
+               
+               bool isValid()const{return m_valid;}
        private:
                MWebRequest*req;
                int eventid;
@@ -40,6 +54,8 @@ class MEvent
                int m_defaultprice;
                //if not null/empty: event has been cancelled
                QString m_cancelreason;
+               //holds whether the loaded data is valid
+               bool m_valid;
 };
 
 #endif
index 45f3dd6..1ffc1cf 100644 (file)
 
 #include "eventedit.h"
 
+#include <QGridLayout>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QDateTimeEdit>
+#include <QTextEdit>
+#include <QTimer>
+#include <QMessageBox>
+
 MEventEditor::MEventEditor(QWidget*w,MWebRequest*r,qint32 id)
        :QDialog(w),event(r,id)
 {
-       setWindowTitle("Event Editor");
+       if(!event.isValid()){
+               QMessageBox::warning(this,tr("Warning"),tr("Unable to load event from server."));
+               //make myself disappear immediately
+               QTimer::singleShot(1,this,SLOT(reject()));
+               //no point in setting up widgets
+               return;
+       }
+       setWindowTitle(tr("Event Editor"));
        req=r;
        
+       QGridLayout*gl;
+       QVBoxLayout*vl;
+       QHBoxLayout*hl;
+       QPushButton*p;
+       int lctr=0;
+       QLabel*lab;
+       
+       setLayout(vl=new QVBoxLayout);
+       vl->addLayout(gl=new QGridLayout);
+       
+       gl->addWidget(lab=new QLabel(tr("Title:")),lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(title=new QLineEdit,lctr,1);
+       title->setText(event.title());
+       
+       gl->addWidget(lab=new QLabel(tr("Artist:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(artist=new QLineEdit,lctr,1);
+       artist->setText(event.artist());
+       
+       gl->addWidget(lab=new QLabel(tr("Description:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(description=new QTextEdit,lctr,1);
+       description->setPlainText(event.description());
+       
+       gl->addWidget(lab=new QLabel(tr("Start Time:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(starttime=new QDateTimeEdit,lctr,1);
+       starttime->setDisplayFormat(tr("ddd MMMM d yyyy, h:mm ap","time format"));
+       starttime->setCalendarPopup(true);
+       starttime->setDateTime(QDateTime::fromTime_t(event.startTime()));
+       
+       gl->addWidget(lab=new QLabel(tr("End Time:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(endtime=new QDateTimeEdit,lctr,1);
+       endtime->setDisplayFormat(tr("ddd MMMM d yyyy, h:mm ap","time format"));
+       endtime->setCalendarPopup(true);
+       endtime->setDateTime(QDateTime::fromTime_t(event.endTime()));
        
+       gl->addWidget(lab=new QLabel(tr("Room/Place:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addLayout(hl=new QHBoxLayout,lctr,1);
+       hl->addWidget(room=new QLineEdit,10);
+       room->setReadOnly(true);
+       room->setText(event.room());
+       hl->addWidget(p=new QPushButton("..."),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(selectRoom()));
+       
+       gl->addWidget(lab=new QLabel(tr("Capacity:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(capacity=new QSpinBox,lctr,1);
+       capacity->setRange(0,1000000000);//it is unlikely that any show will attract more people!
+       capacity->setValue(event.capacity());
+       
+       gl->addWidget(lab=new QLabel(tr("Default Price:")),++lctr,0);
+       lab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+       gl->addWidget(price=new QLineEdit,lctr,1);
+       price->setValidator(new QRegExpValidator(event.priceRegExp(),this));
+       price->setText(event.priceString());
+       
+       gl->addWidget(cancelcheck=new QCheckBox(tr("Cancel Event:")),++lctr,0);
+       cancelcheck->setChecked(event.isCancelled());
+       gl->addWidget(cancelreason=new QLineEdit,lctr,1);
+       cancelreason->setEnabled(event.isCancelled());
+       cancelreason->setText(event.cancelReason());
+       connect(cancelcheck,SIGNAL(toggled(bool)),cancelreason,SLOT(setEnabled(bool)));
+       
+       vl->addStretch();
+       
+       vl->addLayout(hl=new QHBoxLayout,0);
+       hl->addStretch();
+       hl->addWidget(p=new QPushButton(tr("Save")));
+       connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+       connect(p,SIGNAL(clicked()),this,SLOT(writeBack()));
+       hl->addWidget(p=new QPushButton(tr("Cancel")));
+       connect(p,SIGNAL(clicked()),this,SLOT(reject()));
 }
+
+void MEventEditor::writeBack()
+{}
+
+void MEventEditor::selectRoom()
+{}
\ No newline at end of file
index 7951e58..acc85d3 100644 (file)
 #include "event.h"
 
 class MWebRequest;
+class QDateTimeEdit;
+class QLineEdit;
+class QTextEdit;
+class QCheckBox;
+class QSpinBox;
 
 class MEventEditor:public QDialog
 {
+       Q_OBJECT
        public:
                MEventEditor(QWidget*,MWebRequest*,qint32 id=-1);
+       private slots:
+               void writeBack();
+               void selectRoom();
        private:
                MWebRequest*req;
                MEvent event;
+               QDateTimeEdit*starttime,*endtime;
+               QLineEdit*title,*artist,*room,*price,*cancelreason;
+               QTextEdit*description;
+               QCheckBox*cancelcheck;
+               QSpinBox*capacity;
 };
 
 
index 24a4831..552be3d 100644 (file)
@@ -1,6 +1,75 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS><TS version="1.1" language="de">
 <context>
+    <name>MEventEditor</name>
+    <message>
+        <location filename="eventedit.cpp" line="28"/>
+        <source>Event Editor</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="38"/>
+        <source>Title:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="41"/>
+        <source>Artist:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="44"/>
+        <source>Description:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="47"/>
+        <source>Start Time:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="54"/>
+        <source>ddd MMMM d yyyy, h:mm ap</source>
+        <comment>time format</comment>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="51"/>
+        <source>End Time:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="55"/>
+        <source>Room/Place:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="60"/>
+        <source>Capacity:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="63"/>
+        <source>Default Price:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="66"/>
+        <source>Cancel Event:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="72"/>
+        <source>Save</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="73"/>
+        <source>Cancel</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MKeyGen</name>
     <message>
         <location filename="keygen.cpp" line="86"/>
@@ -216,27 +285,27 @@ At least %1 Bits of random are required.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="50"/>
+        <location filename="overview.cpp" line="51"/>
         <source>&amp;Customer</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="61"/>
+        <location filename="overview.cpp" line="62"/>
         <source>C&amp;onfigure</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="65"/>
+        <location filename="overview.cpp" line="66"/>
         <source>Events</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="155"/>
+        <location filename="overview.cpp" line="165"/>
         <source>Warning</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="155"/>
+        <location filename="overview.cpp" line="165"/>
         <source>I was unable to renew the login at the server, the error was: %1</source>
         <translation type="unfinished"></translation>
     </message>
@@ -246,131 +315,136 @@ At least %1 Bits of random are required.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="46"/>
+        <location filename="overview.cpp" line="47"/>
         <source>&amp;Show details...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="47"/>
+        <location filename="overview.cpp" line="48"/>
         <source>&amp;New Event...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="48"/>
+        <location filename="overview.cpp" line="49"/>
         <source>&amp;Cancel Event...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="51"/>
+        <location filename="overview.cpp" line="52"/>
         <source>&amp;Show all customers</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="53"/>
+        <location filename="overview.cpp" line="54"/>
         <source>C&amp;art</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="54"/>
+        <location filename="overview.cpp" line="55"/>
         <source>Add &amp;Ticket</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="55"/>
+        <location filename="overview.cpp" line="56"/>
         <source>Add &amp;Voucher</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="56"/>
+        <location filename="overview.cpp" line="57"/>
         <source>&amp;Remove Item</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="57"/>
+        <location filename="overview.cpp" line="58"/>
         <source>&amp;Abort Shopping</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="59"/>
+        <location filename="overview.cpp" line="60"/>
         <source>&amp;Show all orders</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="73"/>
+        <location filename="overview.cpp" line="76"/>
         <source>New Event...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="76"/>
+        <location filename="overview.cpp" line="79"/>
         <source>Details...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="78"/>
+        <location filename="overview.cpp" line="83"/>
         <source>Order Ticket...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="81"/>
+        <location filename="overview.cpp" line="86"/>
         <source>Shopping Cart</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="90"/>
+        <location filename="overview.cpp" line="95"/>
         <source>Add Ticket</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="91"/>
+        <location filename="overview.cpp" line="96"/>
         <source>Add Voucher</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="92"/>
+        <location filename="overview.cpp" line="97"/>
         <source>Remove Item</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="97"/>
+        <location filename="overview.cpp" line="102"/>
         <source>Customer:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="102"/>
+        <location filename="overview.cpp" line="107"/>
         <source>Delivery Address:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="105"/>
+        <location filename="overview.cpp" line="110"/>
         <source>Comments:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="112"/>
+        <location filename="overview.cpp" line="117"/>
         <source>Save Order</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="113"/>
+        <location filename="overview.cpp" line="118"/>
         <source>Clear</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="123"/>
+        <location filename="overview.cpp" line="137"/>
         <source>Start Time</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="123"/>
+        <location filename="overview.cpp" line="137"/>
         <source>Title</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="126"/>
+        <location filename="overview.cpp" line="140"/>
         <source>ddd MMMM d yyyy, h:mm ap</source>
         <comment>time format</comment>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="overview.cpp" line="46"/>
+        <source>&amp;Update Event List</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MWebRequest</name>
index 1c71a21..4c0d765 100644 (file)
@@ -2,6 +2,75 @@
 <!DOCTYPE TS><TS version="1.1" language="de">
 <defaultcodec></defaultcodec>
 <context>
+    <name>MEventEditor</name>
+    <message>
+        <location filename="eventedit.cpp" line="28"/>
+        <source>Event Editor</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="38"/>
+        <source>Title:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="41"/>
+        <source>Artist:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="44"/>
+        <source>Description:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="47"/>
+        <source>Start Time:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="54"/>
+        <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="eventedit.cpp" line="51"/>
+        <source>End Time:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="55"/>
+        <source>Room/Place:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="60"/>
+        <source>Capacity:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="63"/>
+        <source>Default Price:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="66"/>
+        <source>Cancel Event:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="72"/>
+        <source>Save</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="eventedit.cpp" line="73"/>
+        <source>Cancel</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MKeyGen</name>
     <message>
         <location filename="keygen.cpp" line="86"/>
@@ -217,27 +286,27 @@ At least %1 Bits of random are required.</source>
         <translation>&amp;Veranschdaldung</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="50"/>
+        <location filename="overview.cpp" line="51"/>
         <source>&amp;Customer</source>
         <translation>&amp;Gunde</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="61"/>
+        <location filename="overview.cpp" line="62"/>
         <source>C&amp;onfigure</source>
         <translation>G&amp;onfiguriern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="65"/>
+        <location filename="overview.cpp" line="66"/>
         <source>Events</source>
         <translation>Veranschdaldungen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="155"/>
+        <location filename="overview.cpp" line="165"/>
         <source>Warning</source>
         <translation>Dumm gelaufen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="155"/>
+        <location filename="overview.cpp" line="165"/>
         <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>
@@ -247,131 +316,136 @@ At least %1 Bits of random are required.</source>
         <translation>&amp;Ohne Neds und Dobbelden Boden</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="46"/>
+        <location filename="overview.cpp" line="47"/>
         <source>&amp;Show details...</source>
         <translation>&amp;Dedails anzeigen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="47"/>
+        <location filename="overview.cpp" line="48"/>
         <source>&amp;New Event...</source>
         <translation>&amp;Neue Veranschdaldung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="48"/>
+        <location filename="overview.cpp" line="49"/>
         <source>&amp;Cancel Event...</source>
         <translation>Veranschdaldung &amp;absach&apos;n...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="51"/>
+        <location filename="overview.cpp" line="52"/>
         <source>&amp;Show all customers</source>
         <translation>&amp;Alle Gunden anzeigen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="53"/>
+        <location filename="overview.cpp" line="54"/>
         <source>C&amp;art</source>
         <translation>Eing&amp;aufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="54"/>
+        <location filename="overview.cpp" line="55"/>
         <source>Add &amp;Ticket</source>
         <translation>Ein&amp;driddsgarde hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="55"/>
+        <location filename="overview.cpp" line="56"/>
         <source>Add &amp;Voucher</source>
         <translation>&amp;Gudschein hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="56"/>
+        <location filename="overview.cpp" line="57"/>
         <source>&amp;Remove Item</source>
         <translation>Doch &amp;ni&apos; nehm&apos;</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="57"/>
+        <location filename="overview.cpp" line="58"/>
         <source>&amp;Abort Shopping</source>
         <translation>&amp;Eingauf Abbrechen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="59"/>
+        <location filename="overview.cpp" line="60"/>
         <source>&amp;Show all orders</source>
         <translation>&amp;Alle Beschdellungen anzeichen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="73"/>
+        <location filename="overview.cpp" line="76"/>
         <source>New Event...</source>
         <translation>Neue Veranschdaldung...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="76"/>
+        <location filename="overview.cpp" line="79"/>
         <source>Details...</source>
         <translation>Dedails anzeichen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="78"/>
+        <location filename="overview.cpp" line="83"/>
         <source>Order Ticket...</source>
         <translation>Eindriddsgarde beschdellen...</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="81"/>
+        <location filename="overview.cpp" line="86"/>
         <source>Shopping Cart</source>
         <translation>Eingaufswagen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="90"/>
+        <location filename="overview.cpp" line="95"/>
         <source>Add Ticket</source>
         <translation>Eindriddsgarde hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="91"/>
+        <location filename="overview.cpp" line="96"/>
         <source>Add Voucher</source>
         <translation>Gudschein hinzufüchen</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="92"/>
+        <location filename="overview.cpp" line="97"/>
         <source>Remove Item</source>
         <translation>Doch ni&apos; nehm&apos;</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="97"/>
+        <location filename="overview.cpp" line="102"/>
         <source>Customer:</source>
         <translation>Gunde:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="102"/>
+        <location filename="overview.cpp" line="107"/>
         <source>Delivery Address:</source>
         <translation>Adresse wo&apos;s Zeuch hin soll:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="105"/>
+        <location filename="overview.cpp" line="110"/>
         <source>Comments:</source>
         <translation>Wischdiches Gelaber und Gerede:</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="112"/>
+        <location filename="overview.cpp" line="117"/>
         <source>Save Order</source>
         <translation>Beschdellung abschbeichern</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="113"/>
+        <location filename="overview.cpp" line="118"/>
         <source>Clear</source>
         <translation>Wechwerfen und von vorne!</translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="123"/>
+        <location filename="overview.cpp" line="137"/>
         <source>Start Time</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="123"/>
+        <location filename="overview.cpp" line="137"/>
         <source>Title</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="overview.cpp" line="126"/>
+        <location filename="overview.cpp" line="140"/>
         <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="46"/>
+        <source>&amp;Update Event List</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MWebRequest</name>
index f9fb699..2f506a9 100644 (file)
@@ -26,7 +26,12 @@ MWebRequest::MWebRequest()
        webtimeout=30000;
        finid=0;finerr=fin=false;
        proxyport=-1;
+       sessiontimeout=0;
        connect(&req,SIGNAL(requestFinished(int,bool)),this,SLOT(httpFin(int,bool)));
+       QTimer*tm=new QTimer(this);
+       tm->setSingleShot(false);
+       tm->start(10000);
+       connect(tm,SIGNAL(timeout()),this,SLOT(reloginCheck()));
 }
 MWebRequest::~MWebRequest(){}
 
@@ -69,12 +74,14 @@ bool MWebRequest::request(QString hreq,QByteArray data)
                //it did not finish yet, caught a timeout.
                req.abort();
                errstr="Web Request timed out.";
+               rspstatus="HTTP";
                return false;
        }
        qDebug("Received Request finish for ID=%i Status=%s",finid,finerr?"Error":"Ok");
        //finished with low-level error?
        if(finerr){
                errstr="HTTP Error: "+req.errorString();
+               rspstatus="HTTP";
                qDebug("%s",errstr.toAscii().data());
                return false;
        }
@@ -82,11 +89,12 @@ bool MWebRequest::request(QString hreq,QByteArray data)
        //check for high level error
        if(rsph.statusCode()!=200){
                errstr="HTTP Error, return code "+QString::number(rsph.statusCode())+" "+rsph.reasonPhrase();
+               rspstatus="HTTP";
                return false;
        }
        //get data
        rspdata=req.readAll();
-       rspstatus=rsph.value("x-magicsmoke-status").remove('"').trimmed();
+       rspstatus=rsph.value("x-magicsmoke-status").remove('"').trimmed().toLower();
        //
        qDebug("HTTP Response Headers:\n%s",rsph.toString().toAscii().data());
        qDebug("HTTP Response Body:\n%s\n<-->",rspdata.data());
@@ -144,6 +152,7 @@ bool MWebRequest::login(QString usr,QString pwd,QString hn)
 
 bool MWebRequest::doLogin()
 {
+       sessiontimeout=0;
        //get authentication algo
        if(!request("serverinfo"))return false;
        if(rspstatus.toLower()!="ok"){
@@ -225,13 +234,34 @@ bool MWebRequest::doLogin()
                errstr=tr("Unable to authenticate.");
                return false;
        }
-       //TODO: store session timeout and do something useful with it
+       //get timestamps from server
+       QStringList tlst=QString::fromAscii(rspdata).trimmed().split("\n",QString::SkipEmptyParts);
+       qint64 tout=-1,tcur=-1;
+       bool b;
+       if(tlst.size()>=1){
+               tout=tlst[0].trimmed().toInt(&b);
+               if(!b)tout=-1;
+       }
+       if(tlst.size()>=2){
+               tcur=tlst[1].trimmed().toInt(&b);
+               if(!b)tcur=-1;
+       }
+       //correct timeout
+       if(tcur>=0){
+               int toff=QDateTime::currentDateTime().toTime_t()-tcur;
+               tout+=toff;
+       }
+       //store new timeout (don't store if this is less than 5min in the future,
+       // to prevent endless loops)
+       if((tout-300)>QDateTime::currentDateTime().toTime_t())
+               sessiontimeout=tout-30;//safety range of 20s + 10s timer delay
        //all ok
        return true;
 }
 
 void MWebRequest::logout()
 {
+       sessiontimeout=0;
        request("closesession");
 }
 
@@ -296,3 +326,34 @@ QList<MWebRequest::Eventlet> MWebRequest::getAllEvents()
        }
        return ret;
 }
+
+QByteArray MWebRequest::responseBody()
+{
+       return rspdata;
+}
+
+MWebRequest::ResponseStatus MWebRequest::responseStatus()
+{
+       if(rspstatus=="HTTP")
+               return HttpError;
+       if(rspstatus=="ok")
+               return Ok;
+       if(rspstatus=="nonpost")
+               return NonPost;
+       if(rspstatus=="unauthorized")
+               return Unauthorized;
+       if(rspstatus=="notallowed")
+               return NotAllowed;
+       if(rspstatus=="invalidrequest")
+               return InvalidRequest;
+       if(rspstatus=="syntaxerror")
+               return SyntaxError;
+       return Error;
+}
+
+void MWebRequest::reloginCheck()
+{
+       if(sessiontimeout<=0)return;
+       if(sessiontimeout<=QDateTime::currentDateTime().toTime_t())
+               relogin();
+}
index 50a7a30..39021bd 100644 (file)
@@ -32,6 +32,30 @@ class MWebRequest:public QObject
                
                /**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*/
+               QByteArray responseBody();
+               
+               enum ResponseStatus{
+                       /**Everything was ok*/
+                       Ok=0,
+                       /**an unknown error occurred*/
+                       Error=1,
+                       /**the request was not a POST method (should never happen)*/
+                       NonPost=2,
+                       /**the session expired or was never established*/
+                       Unauthorized=3,
+                       /**the user does not have this right*/
+                       NotAllowed=4,
+                       /**the request name was invalid, the request does not exist*/
+                       InvalidRequest=5,
+                       /**the request data had syntactical errors*/
+                       SyntaxError=6,
+                       /**the HTTP transport failed or the server was unable to execute the script*/
+                       HttpError=100
+               };
+               
+               /**returns the (lower-case) response status of the last request*/
+               ResponseStatus responseStatus();
                
                /**returns the last error as string*/
                QString errorString();
@@ -66,6 +90,8 @@ class MWebRequest:public QObject
        private slots:
                /**internal: used by wait loop for web requests*/
                void httpFin(int,bool);
+               /**internal: check whether we need to redo the login*/
+               void reloginCheck();
                
        signals:
                /**internal: used by wait loop for web request*/
@@ -88,6 +114,8 @@ class MWebRequest:public QObject
                QString rspstatus;
                QByteArray rspdata;
                int finid,waitid;
+               //session timeout for relogin
+               qint64 sessiontimeout;
                
                /**used by login and relogin to do the actual work*/
                bool doLogin();
index 3348f02..e31a438 100644 (file)
@@ -43,4 +43,107 @@ function getAllEventsXml()
        echo $xml->saveXml();
 }
 
+class Event
+{
+       private $evid;
+       private $title;
+       private $artist;
+       private $description;
+       private $starttime;
+       private $endtime;
+       private $roomid;
+       private $capacity;
+       private $defaultprice;
+       private $cancelreason;
+
+       /**creates an event object, the id must be a valid eventid gotten from getAllEvents or -1 if you
+       want to create a new event*/
+       public function __construct($id)
+       {
+               global $db;
+               //check that event exists
+               $id=$id+0;
+               if($id<0)$id=-1;
+               else{
+                       $res=$db->select("event","*","eventid=$id");
+                       if(count($res)!=1)$id=-1;
+                       else{
+                               $this->title=$res[0]["title"];
+                               $this->artist=$res[0]["artist"];
+                               $this->description=$res[0]["description"];
+                               $this->starttime=$res[0]["starttime"];
+                               $this->endtime=$res[0]["endtime"];
+                               $this->roomid=$res[0]["roomid"];
+                               $this->capacity=$res[0]["capacity"];
+                               $this->defaultprice=$res[0]["defaultprice"];
+                               $this->cancelreason=$res[0]["cancelreason"];
+                       }
+               }
+               //remember it
+               $this->evid=$id;
+       }
+       
+       /**returns whether this event already exists in the database*/
+       public function exists()
+       {
+               return $this->evid >= 0;
+       }
+       
+       /**returns the ID of the event*/
+       public function getEventId(){return $this->evid;}
+       /**returns the start time of the event*/
+       public function getStartTime(){return $this->starttime;}
+       /**returns the end time of the event*/
+       public function getEndTime(){return $this->endtime;}
+       /**returns the ticket capacity of the event*/
+       public function getCapacity(){return $this->capacity;}
+       /**returns the default price in cent of the event*/
+       public function getDefaultPrice(){return $this->defaultprice;}
+       /**returns whether the event is cancelled*/
+       public function isCancelled()
+       {
+               if($this->cancelreason===false)return false;
+               else return $this->cancelreason!="";
+       }
+       /**returns the title of the event*/
+       public function getTitle(){return $this->title;}
+       /**returns the artist of the event*/
+       public function getArtist(){return $this->artist;}
+       /**returns the room/place of the event*/
+       public function getRoomId(){return $this->roomid;}
+       /**returns the description of the event*/
+       public function getDescription(){return $this->description;}
+       /**returns the reason why the event is cancelled if isCancelled() returns true*/
+       public function getCancelReason(){return $this->cancelreason;}
+};
+
+/**machine-function: get the requested events as XML data*/
+function getEventsXml($evts)
+{
+       header("X-MagicSmoke-Status: Ok");
+       $xml=new DOMDocument;
+       $root=$xml->createElement("EventData");
+       if(count($evts)>0)
+       foreach($evts as $k => $eid){
+               $ev=new Event($eid);
+               if(!$ev->exists())continue;
+               $nod=$xml->createElement("Event");
+               $nod->setAttribute("id",$eid);
+               $nod->setAttribute("start",$ev->getStartTime());
+               $nod->setAttribute("end",$ev->getEndTime());
+               $nod->setAttribute("capacity",$ev->getCapacity());
+               $nod->setAttribute("defaultprice",$ev->getDefaultPrice());
+               $nod->setAttribute("cancelled",$ev->isCancelled()?"true":"false");
+               $nod->appendChild($xml->createElement("Title",$ev->getTitle()));
+               $nod->appendChild($xml->createElement("Artist",$ev->getArtist()));
+               $nod->appendChild($xml->createElement("Room",$ev->getRoomId()));
+               $nod->appendChild($xml->createElement("Description",$ev->getDescription()));
+               if($ev->isCancelled())
+                       $nod->appendChild($xml->createElement("CancelReason",$ev->getCancelReason()));
+               $root->appendChild($nod);
+       }
+       $xml->appendChild($root);
+       echo $xml->saveXml();
+}
+
 ?>
\ No newline at end of file
index ecd1263..3b1bb05 100644 (file)
@@ -190,7 +190,7 @@ class Session
                //success
                header("X-MagicSmoke-Status: Ok");
                global $ClientSessionTimeout;
-               $tout=time()+$ClientSessionTimeout;
+               $tout=(time()+$ClientSessionTimeout)."\n".time();
                $db->update("session",array("user"=>$username,"timeout"=>$tout),"sessionid=".$db->escapeString($this->sessid));
                echo $tout;
        }
index 0934ce6..f56ce3e 100644 (file)
@@ -106,6 +106,19 @@ if($SMOKEREQUEST=="geteventlist"){
        exit();
 }
 
+//get a specific event
+if($SMOKEREQUEST=="geteventdata"){
+       //convert request data into array
+       $evts=array();
+       $lst=explode(" ",$REQUESTDATA);
+       foreach($lst as $k=>$v){
+               $evts[]=$v+0;
+       }
+       //get data and build XML
+       getEventsXml(array_values(array_unique($evts)));
+       exit();
+}
+
 //EOF
 header("X-MagicSmoke-Status: Error");
 die("Internal Error: unknown command, hiccup in code structure.");