#include <QBoxLayout>
#include <QCheckBox>
#include <QComboBox>
+#include <QDebug>
+#include <QDesktopServices>
#include <QFrame>
#include <QHeaderView>
#include <QInputDialog>
+#include <QItemSelectionModel>
#include <QLabel>
#include <QMenu>
#include <QMenuBar>
#include <QPushButton>
#include <QSettings>
#include <QSpinBox>
+#include <QSplitter>
#include <QStandardItemModel>
#include <QTableView>
-#include <QTextEdit>
+#include <QTextBrowser>
+#include <QUrl>
+#include <QUrlQuery>
MEventsTab::MEventsTab(QString pk)
{
//Event tab
QVBoxLayout*vl;QHBoxLayout*hl;
- setLayout(hl=new QHBoxLayout);
- hl->addWidget(eventtable=new QTableView,10);
+ setLayout(vl=new QVBoxLayout);
+ QSplitter*split;
+ vl->addWidget(split=new QSplitter);
+ split->addWidget(eventtable=new QTableView);
eventtable->setModel(eventmodel=new QStandardItemModel(this));
eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
- eventtable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ eventtable->setSelectionBehavior(QAbstractItemView::SelectRows);
eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
eventtable->verticalHeader()->hide();
eventtable->setSortingEnabled(true);
eventmodel->setSortRole(SortRole);
- hl->addSpacing(5);
+ 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);
m->addAction(tr("New Event..."),this,SLOT(newEvent()));
m->addAction(tr("Clone Current Event..."),this,SLOT(cloneEvent()));
- vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
p->setEnabled(req->hasRight(req->RGetEvent));
vl->addSpacing(15);
p->setEnabled(req->hasRight(req->RCancelEvent));
connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
vl->addStretch(10);
-
+*/
//fill tables
if(req->hasRight(req->RGetAllEvents)){
updateEvents();
QMenu*m=new QMenu(tr("&View"));
ret<<m;
m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
- ->setEnabled(req->hasRight(req->RGetAllEvents));
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("Event &Summary..."),this,SLOT(eventSummary()))
+ ->setEnabled(req->hasRight(MInterface::RGetEventSummary));
m->addSeparator();
showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
showoldevents->setChecked(QSettings().value("profiles/"+profilekey+"/showOldEvents",false).toBool());
m=new QMenu(tr("&Edit"));
+ ret<<m;
m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
->setEnabled(req->hasRight(req->RGetEvent));
m->addAction(tr("&New Event..."),this,SLOT(newEvent()))
->setEnabled(req->hasRight(req->RCreateEvent));
+ m->addAction(tr("&Clone Current Event..."),this,SLOT(cloneEvent()))
+ ->setEnabled(req->hasRight(req->RCreateEvent));
+ m->addAction(tr("C&ancel Event..."),this,SLOT(eventCancel()))
+ ->setEnabled(req->hasRight(req->MInterface::RCancelEvent));
m->addSeparator();
m->addAction(tr("&Edit Price Categories..."),this,SLOT(editPriceCat()));
now.addDays(-maxage);
}
//fill model
+ eventdetail->clear();
+ eventdetail->clearHistory();
eventmodel->clear();
eventmodel->insertColumns(0,6);
eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
//show
eventmodel->insertRow(j);
eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),IdRole);
+ eventmodel->setData(eventmodel->index(j,0),QVariant::fromValue(evl[i]),ObjectRole);
eventmodel->setData(eventmodel->index(j,0),evl[i].startTimeString());
eventmodel->setData(eventmodel->index(j,0),evl[i].start().value(),SortRole);
eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
{
}
+void MEventsTab::updateDetails()
+{
+ //clear
+ eventdetail->clearHistory();
+ eventdetail->clear();
+ //get selection
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ //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()));
+ }
+}
+
void MEventsTab::newEvent()
{
MEventEditor ed(this);