refactor event overview, first draft of enabling HTML, draft of pattern
authorKonrad Rosenbaum <konrad@silmor.de>
Sun, 29 May 2016 12:10:32 +0000 (14:10 +0200)
committerKonrad Rosenbaum <konrad@silmor.de>
Sun, 29 May 2016 12:10:32 +0000 (14:10 +0200)
iface/msinterface.cpp
iface/msinterface.h
src/mwin/eventstab.cpp
src/mwin/eventstab.h
src/widgets/eventview.cpp [new file with mode: 0644]
src/widgets/eventview.h [new file with mode: 0644]
src/widgets/widgets.pri

index 8d97953..5a3fd1e 100644 (file)
@@ -287,3 +287,13 @@ bool MSInterface::checkFlags(const QStringList& fl) const
        //survived all tests
        return true;
 }
+
+QUrl MSInterface::parentUrl() const
+{
+       QUrl parent=url();
+       parent.setFragment(QString());
+       parent.setQuery(QString());
+       QString path=parent.path();
+       if(path==QString() || path.endsWith('/'))return parent;
+       parent.setPath(path.left(path.lastIndexOf('/')+1));
+}
index f271ab6..7ce3475 100644 (file)
@@ -98,6 +98,9 @@ class MSIFACE_EXPORT MSInterface:public MInterface
                
                ///return all flags of the current user
                QStringList allFlags()const{return userflags;}
+
+               ///return the parent directory of the base URL
+               QUrl parentUrl()const;
                
                ///return application main data directory
                static QString appDataDir();
index 4afafe8..a6240e6 100644 (file)
@@ -13,6 +13,7 @@
 #include "centbox.h"
 #include "eventedit.h"
 #include "eventsummary.h"
+#include "eventview.h"
 #include "main.h"
 #include "misc.h"
 #include "msinterface.h"
 #include <QTextBrowser>
 #include <QUrl>
 #include <QUrlQuery>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QEventLoop>
+
+
 
 MEventsTab::MEventsTab(QString pk)
 {
@@ -57,7 +64,7 @@ MEventsTab::MEventsTab(QString pk)
        setObjectName("eventstab");
        
        //Event tab
-       QVBoxLayout*vl;QHBoxLayout*hl;
+       QVBoxLayout*vl;
        setLayout(vl=new QVBoxLayout);
        QSplitter*split;
        vl->addWidget(split=new QSplitter);
@@ -70,38 +77,10 @@ MEventsTab::MEventsTab(QString pk)
        eventtable->setSortingEnabled(true);
        eventmodel->setSortRole(SortRole);
        connect(eventtable->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this,SLOT(updateDetails()));
-       split->addWidget(eventdetail=new QTextBrowser);
-       eventdetail->setReadOnly(true);
-       connect(eventdetail,SIGNAL(anchorClicked(QUrl)),this,SLOT(eventOrderTicketUrl(QUrl)));
-       eventdetail->setOpenExternalLinks(false);
-       eventdetail->setOpenLinks(false);
-/*     hl->addSpacing(5);
-       hl->addLayout(vl=new QVBoxLayout,0);
-       QPushButton*p;
-       vl->addWidget(p=new QPushButton(tr("New Event")),0);
-       p->setEnabled(req->hasRight(req->RCreateEvent));
-       QMenu*m;
-       p->setMenu(m=new QMenu);
-       m->addAction(tr("New Event..."),this,SLOT(newEvent()));
-       m->addAction(tr("Clone Current Event..."),this,SLOT(cloneEvent()));
+       split->addWidget(eventdetail=new MEventView);
+       connect(eventdetail,SIGNAL(eventOrderTicket(qint64,qint64)),this,SIGNAL(eventOrderTicket(qint64,qint64)));
+       connect(eventdetail,SIGNAL(eventOrderTicket()),this,SIGNAL(eventOrderTicket()));
 
-       vl->addWidget(p=new QPushButton(tr("Details...")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
-       p->setEnabled(req->hasRight(req->RGetEvent));
-       vl->addSpacing(15);
-       vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
-       connect(p,SIGNAL(clicked()),this,SIGNAL(eventOrderTicket()));
-       p->setEnabled(req->hasRight(req->RCreateOrder)||req->hasRight(req->RCreateReservation));
-       vl->addSpacing(15);
-       vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
-       connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
-       p->setEnabled(req->hasRight(req->RGetEventSummary));
-       vl->addSpacing(15);
-       vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
-       p->setEnabled(req->hasRight(req->RCancelEvent));
-       connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
-       vl->addStretch(10);
-*/     
        //fill tables
        if(req->hasRight(req->RGetAllEvents)){
                updateEvents();
@@ -204,8 +183,7 @@ MEventsTab::~MEventsTab()
 void MEventsTab::updateDetails()
 {
        //clear
-       eventdetail->clearHistory();
-       eventdetail->clear();
+       eventdetail->clearEvent();
        //get selection
        QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
        if(ilst.size()<1)return;
@@ -213,93 +191,7 @@ void MEventsTab::updateDetails()
        //get event
        MOEvent event=eventmodel->data(idx,ObjectRole).value<MOEvent>();
        if(!event.isValid())return;
-       //generate HTML
-       QString detail="<h1>"+htmlize(event.title())+"</h1>\n";
-       detail+=tr("Artist: %1").arg(htmlize(event.artist().value().name()))+"<p>\n";
-       detail+=tr("Starttime: %1").arg(htmlize(event.startTimeString()))+"<br>\n";
-       detail+=tr("Endtime: %1").arg(htmlize(event.startTimeString()))+"<p>\n";
-       detail+=tr("Room: %1").arg(htmlize(event.room()))+"<br>\n";
-       detail+=tr("Seats: %1 max. (%2 sold out; %3 reserved; %4 free)").arg(event.capacity()).arg(event.amountSold()).arg(event.amountReserved()).arg(event.amountFree())+"<p>\n";
-
-       const QString bgsold=tr("<div style=\"background-color:#ff8080\">Sold Out!</div>","Colored display for sold out tickets");
-       const QString bgavail=tr("<table border=1 style=\"border-style:groove; background-color:#00ff00\"><tr><td><div style=\"background-color:#80ff80\"><a href=\"%1\">Order Tickets...</a></div></td></tr></table>","Colored display for ordering tickets");
-       const QString bghide=tr("<div style=\"background-color:#c0c0c0\">Unable to sell.</div>","Colored display for tickets unavailable to this user");
-
-       const bool showevent=req->checkFlags(event.flags());
-       if(showevent)
-               detail+=event.amountFree()>0?bgavail.arg(QString("order:?ev=%1").arg(event.id())):bgsold;
-       else
-               detail+=bghide;
-       detail+="<h2>"+tr("Prices")+"</h2>\n";
-       detail+="<table frame=1 border=1>"
-       "<thead><tr><th>"+tr("Category")+"</th><th>"+tr("Price")+"</th><th>"+tr("Available")+"</th><th>"+tr("Max. Seats")+"</th><th>"+tr("Order")+"</th></tr></thead>\n";
-       QList<MOEventPrice>prices=event.price();
-       qSort(prices.begin(),prices.end(),[](const MOEventPrice&p1,const MOEventPrice&p2){return p1.prio()<p2.prio();});
-       for(MOEventPrice ctg:prices){
-               detail+="<tr><td>"+ctg.pricecategory().value().name();
-               detail+="</td><td>"+cent2str(ctg.price().value());
-               const int avail=ctg.maxavailable()-ctg.amountticketsblock();
-               detail+="</td><td>"+QString::number(avail);
-               detail+="</td><td>"+QString::number(ctg.maxavailable());
-               if(showevent && req->checkFlags(ctg.flags()))
-                       detail+="</td><td>"+
-                               (avail>0?
-                                       bgavail.arg(QString("order:?ev=%1&pr=%2").arg(event.id()).arg(ctg.pricecategoryid()))
-                                       :bgsold);
-               else
-                       detail+="</td><td>"+bghide;
-               detail+="</td></tr>";
-       }
-       detail+="</table><p>\n";
-       
-       detail+="<h2>"+tr("Description")+"</h2>\n"+event.description()+"<p>\n";
-       detail+="<h2>"+tr("Comment")+"</h2>\n"+htmlize(event.comment());
-       //set value
-       eventdetail->setHtml(detail);
-}
-
-void MEventsTab::eventOrderTicketUrl(const QUrl &url)
-{
-       //check whether it is order URL
-       if(url.scheme()=="order"){
-               QUrlQuery query(url);
-               if(query.hasQueryItem("ev")){
-                       bool b=false;
-                       qint64 evid=query.queryItemValue("ev").toLongLong(&b);
-                       if(!b || evid<0){
-                               qDebug()<<"ordering tickets for current event (invalid EvID)...";
-                               emit eventOrderTicket();
-                               return;
-                       }
-                       qint64 prid=-1;
-                       if(query.hasQueryItem("pr")){
-                               prid=query.queryItemValue("pr").toLongLong(&b);
-                               if(!b)prid=-1;
-                       }
-                       qDebug()<<"ordering tickets for event"<<evid<<"price ID"<<prid;
-                       emit eventOrderTicket(evid,prid);
-               }else{
-                       qDebug()<<"ordering tickets for current event (no EvID)...";
-                       emit eventOrderTicket();
-               }
-               return;
-       }
-       QUrl target=url;
-       //Other URLs happen only in the comment or description sections
-       if(url.isRelative()){
-               //a relative link can only occur in comment or description, so it is relative to the
-               //server URL (the index.php used for displaying this on the web page is parallel to machine.php,
-               //so we can safely use it as base for resolving the relative URL)
-               target=req->url().resolved(url);
-               qDebug()<<"Relative URL"<<url<<"aligned to"<<req->url();
-               qDebug()<<" ...opening"<<target;
-       }
-       if(QDesktopServices::openUrl(target))
-               qDebug()<<"Opened URL"<<target;
-       else{
-               qDebug()<<"WARNING: unknown URL type in"<<url;
-               QMessageBox::warning(this,tr("Warning"),tr("Unable to open URL %1").arg(url.toString()));
-       }
+       eventdetail->setEvent(event);
 }
 
 void MEventsTab::newEvent()
index 3759adc..1a10383 100644 (file)
@@ -29,7 +29,7 @@ class QSpinBox;
 class QStandardItemModel;
 class QTabWidget;
 class QTableView;
-class QTextBrowser;
+class MEventView;
 
 class MSInterface;
 
@@ -82,9 +82,6 @@ class MEventsTab:public QWidget
                /// \param multi true if multiple IDs can be selected, false if only one can be selec ted
                void selectEventIds(QList<int>&eids,bool multi=true)const;
 
-               ///order ticket from URL click
-               void eventOrderTicketUrl(const QUrl&);
-
        signals:
                /**order ticket from event tab*/
                void eventOrderTicket();
@@ -97,7 +94,7 @@ class MEventsTab:public QWidget
                //widgets
                QTableView*eventtable;
                QStandardItemModel*eventmodel;
-               QTextBrowser*eventdetail;
+               MEventView*eventdetail;
                //event list
                QAction*showoldevents;
                //refresh timers
diff --git a/src/widgets/eventview.cpp b/src/widgets/eventview.cpp
new file mode 100644 (file)
index 0000000..e77bb5a
--- /dev/null
@@ -0,0 +1,185 @@
+//
+// C++ Implementation: event list tab
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007-2013
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#include "eventview.h"
+#include "misc.h"
+#include "msinterface.h"
+
+#include <MOEvent>
+#include <MOEventPrice>
+
+#include <QEventLoop>
+#include <QUrl>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QTimer>
+#include <QUrlQuery>
+#include <QMessageBox>
+#include <QDesktopServices>
+
+
+MEventView::MEventView ( QWidget* parent ) : QTextBrowser ( parent )
+{
+       setReadOnly(true);
+       connect(this,SIGNAL(anchorClicked(QUrl)),this,SLOT(handleClick(QUrl)));
+       setOpenExternalLinks(false);
+       setOpenLinks(false);
+       qDebug()<<"Setting path"<<req->parentUrl()<<"for URL"<<req->url();
+       setSearchPaths(QStringList()<<req->parentUrl().toString());
+       resetPattern();
+}
+
+
+QVariant MEventView::loadResource ( int type, const QUrl& name )
+{
+       Q_UNUSED(type);
+       qDebug()<<"Loading Resource"<<name;
+       if(name.isRelative()||name.scheme()=="http"||name.scheme()=="https"){
+               QUrl url(name);
+               if(name.isRelative())url=req->url().resolved(name);
+               QNetworkAccessManager nam;
+               connect(&nam,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),req,SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
+               QNetworkReply*rpl= nam.get(QNetworkRequest(url));
+               qDebug()<<"Trying to GET"<<url;
+               QEventLoop loop;
+               connect(rpl,SIGNAL(finished()),&loop,SLOT(quit()));
+               QTimer::singleShot(15000,&loop,SLOT(quit()));
+               loop.exec();
+               QByteArray data=rpl->readAll();
+               qDebug()<<"...got"<<data.size()<<"bytes";
+               return data;
+       }else
+               return QTextBrowser::loadResource ( type, name );
+}
+
+void MEventView::clearEvent()
+{
+       clearHistory();
+       clear();
+}
+
+void MEventView::setEvent ( MOEvent event )
+{
+       clearEvent();
+
+       //generate HTML
+       QString detail="<h1>"+htmlize(event.title())+"</h1>\n";
+       detail+=tr("Artist: %1").arg(htmlize(event.artist().value().name()))+"<p>\n";
+       detail+=tr("Starttime: %1").arg(htmlize(event.startTimeString()))+"<br>\n";
+       detail+=tr("Endtime: %1").arg(htmlize(event.endTimeString()))+"<p>\n";
+       detail+=tr("Room: %1").arg(htmlize(event.room()))+"<br>\n";
+       detail+=tr("Seats: %1 max. (%2 sold out; %3 reserved; %4 free)").arg(event.capacity()).arg(event.amountSold()).arg(event.amountReserved()).arg(event.amountFree())+"<p>\n";
+
+       const QString bgsold=tr("<div style=\"background-color:#ff8080\">Sold Out!</div>","Colored display for sold out tickets");
+       const QString bgavail=tr("<table border=1 style=\"border-style:groove; background-color:#00ff00\"><tr><td><div style=\"background-color:#80ff80\"><a href=\"%1\">Order Tickets...</a></div></td></tr></table>","Colored display for ordering tickets");
+       const QString bghide=tr("<div style=\"background-color:#c0c0c0\">Unable to sell.</div>","Colored display for tickets unavailable to this user");
+
+       const bool showevent=req->checkFlags(event.flags());
+       if(showevent)
+               detail+=event.amountFree()>0?bgavail.arg(QString("order:?ev=%1").arg(event.id())):bgsold;
+       else
+               detail+=bghide;
+       detail+="<h2>"+tr("Prices")+"</h2>\n";
+       detail+="<table frame=1 border=1>"
+       "<thead><tr><th>"+tr("Category")+"</th><th>"+tr("Price")+"</th><th>"+tr("Available")+"</th><th>"+tr("Max. Seats")+"</th><th>"+tr("Order")+"</th></tr></thead>\n";
+       QList<MOEventPrice>prices=event.price();
+       qSort(prices.begin(),prices.end(),[](const MOEventPrice&p1,const MOEventPrice&p2){return p1.prio()<p2.prio();});
+       for(MOEventPrice ctg:prices){
+               detail+="<tr><td>"+ctg.pricecategory().value().name();
+               detail+="</td><td>"+cent2str(ctg.price().value());
+               const int avail=ctg.maxavailable()-ctg.amountticketsblock();
+               detail+="</td><td>"+QString::number(avail);
+               detail+="</td><td>"+QString::number(ctg.maxavailable());
+               if(showevent && req->checkFlags(ctg.flags()))
+                       detail+="</td><td>"+
+                               (avail>0?
+                                       bgavail.arg(QString("order:?ev=%1&pr=%2").arg(event.id()).arg(ctg.pricecategoryid()))
+                                       :bgsold);
+               else
+                       detail+="</td><td>"+bghide;
+               detail+="</td></tr>";
+       }
+       detail+="</table><p>\n";
+
+       detail+="<h2>"+tr("Description")+"</h2>\n"+event.description()+"<p>\n";
+       detail+="<h2>"+tr("Comment")+"</h2>\n";
+       QString comment=event.comment();
+       if(!comment.trimmed().startsWith("<html>"))comment=htmlize(comment);
+       detail+=comment;
+       //set value
+       setHtml(detail);
+}
+
+void MEventView::handleClick(const QUrl &url)
+{
+       //check whether it is order URL
+       if(url.scheme()=="order"){
+               QUrlQuery query(url);
+               if(query.hasQueryItem("ev")){
+                       bool b=false;
+                       qint64 evid=query.queryItemValue("ev").toLongLong(&b);
+                       if(!b || evid<0){
+                               qDebug()<<"ordering tickets for current event (invalid EvID)...";
+                               emit eventOrderTicket();
+                               return;
+                       }
+                       qint64 prid=-1;
+                       if(query.hasQueryItem("pr")){
+                               prid=query.queryItemValue("pr").toLongLong(&b);
+                               if(!b)prid=-1;
+                       }
+                       qDebug()<<"ordering tickets for event"<<evid<<"price ID"<<prid;
+                       emit eventOrderTicket(evid,prid);
+               }else{
+                       qDebug()<<"ordering tickets for current event (no EvID)...";
+                       emit eventOrderTicket();
+               }
+               return;
+       }
+       QUrl target=url;
+       //Other URLs happen only in the comment or description sections
+       if(url.isRelative()){
+               //a relative link can only occur in comment or description, so it is relative to the
+               //server URL (the index.php used for displaying this on the web page is parallel to machine.php,
+               //so we can safely use it as base for resolving the relative URL)
+               target=req->url().resolved(url);
+               qDebug()<<"Relative URL"<<url<<"aligned to"<<req->url();
+               qDebug()<<" ...opening"<<target;
+       }
+       if(QDesktopServices::openUrl(target))
+               qDebug()<<"Opened URL"<<target;
+       else{
+               qDebug()<<"WARNING: unknown URL type in"<<url;
+               QMessageBox::warning(this,tr("Warning"),tr("Unable to open URL %1").arg(url.toString()));
+       }
+}
+
+void MEventView::setPattern ( QString p )
+{
+       mPattern=p;
+}
+
+void MEventView::resetPattern()
+{
+       mPattern=tr(
+        "<h1>{event.name|html}</h1>\n"
+        "Artist: {event.artist|html}<p>\n"
+        "Starttime: {event.startTimeString}<br>\n"
+        "Endtime: {event.endTimeString}<p>\n"
+        "Room: {event.room|html}<br>\n"
+        "Seats: {event.capacity} max. ({event.amountSold} sold out; {event.amountReserved} reserved; {event.amountFree} free)<p>\n"
+        "{% if(event.haveAccess) %}\n"
+
+        "{% endif %}"
+       );
+}
diff --git a/src/widgets/eventview.h b/src/widgets/eventview.h
new file mode 100644 (file)
index 0000000..6fa58e5
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// C++ Interface: event view`
+//
+// Description: widget for displaying event details
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2016
+//
+// Copyright: See README/COPYING.GPL files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_EVENTVIEW_H
+#define MAGICSMOKE_EVENTVIEW_H
+
+#include <QTextBrowser>
+
+#include <MOEvent>
+
+///Event Viewer
+class MEventView:public QTextBrowser
+{
+       Q_OBJECT
+public:
+       explicit MEventView ( QWidget* parent = 0 );
+       QVariant loadResource(int type, const QUrl & name)override;
+
+public slots:
+       void setEvent(MOEvent);
+       void clearEvent();
+       void setPattern(QString);
+       void resetPattern();
+private slots:
+       void handleClick(const QUrl&);
+signals:
+       /**order ticket from event tab*/
+       void eventOrderTicket();
+       /**order ticket from event tab*/
+       void eventOrderTicket(qint64,qint64);
+private:
+       QString mPattern;
+};
+
+
+#endif
index ac92607..40f1ed2 100644 (file)
@@ -2,12 +2,14 @@ HEADERS += \
        widgets/centbox.h \
        widgets/listview.h \
        widgets/treeview.h \
-       widgets/barcodeline.h
+       widgets/barcodeline.h \
+       widgets/eventview.h
 
 SOURCES += \
        widgets/centbox.cpp \
        widgets/listview.cpp \
        widgets/treeview.cpp \
-       widgets/barcodeline.cpp
+       widgets/barcodeline.cpp \
+       widgets/eventview.cpp
 
 INCLUDEPATH += ./widgets