--- /dev/null
+//
+// C++ Implementation: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "centbox.h"
+#include "checkdlg.h"
+#include "eventedit.h"
+#include "eventsummary.h"
+#include "main.h"
+#include "misc.h"
+#include "moneylog.h"
+#include "msinterface.h"
+#include "orderwin.h"
+#include "overview.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCryptographicHash>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFile>
+#include <QFileDialog>
+#include <QFrame>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSettings>
+#include <QSpinBox>
+#include <QStandardItemModel>
+#include <QStatusBar>
+#include <QTabWidget>
+#include <QTableView>
+#include <QTextEdit>
+
+#define ORDERNONE 0
+#define ORDERALL 0xff
+#define ORDEROPEN 0xf
+#define ORDERPAY 1
+#define ORDERREFUND 2
+#define ORDERUNSENT 4
+#define ORDERRESERVE 8
+
+#define req (MSInterface::instance())
+
+MOverview::MOverview(QString pk)
+{
+ profilekey=pk;
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle("MagicSmoke: "+req->currentUser()+"@"+QSettings().value("profiles/"+pk+"/name").toString());
+ rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000);
+ rtimer.start();
+ connect(&rtimer,SIGNAL(timeout()),this,SLOT(refreshData()));
+ //check backup timing
+ int btm=QSettings().value("profiles/"+pk+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+pk+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //earliest allowed backup is 30s from now
+ if(btm<30)btm=30;
+ //start timer
+ baktimer.start(btm*1000);
+ connect(&baktimer,SIGNAL(timeout()),this,SLOT(doBackup()));
+ }
+
+ //menu
+ QMenuBar*mb=menuBar();
+ QMenu*m=mb->addMenu(tr("&Session"));
+ m->addAction(tr("&Re-Login"),this,SLOT(relogin()));
+ m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword()))
+ ->setEnabled(req->hasRight(req->RChangeMyPassword));
+ m->addSeparator();
+ m->addAction(tr("&Edit Templates..."),req,SLOT(editTemplates()));
+ m->addAction(tr("&Update Templates Now"),req,SLOT(updateTemplates()));
+ m->addSeparator();
+ m->addAction(tr("&Close Session"),this,SLOT(close()));
+
+ m=mb->addMenu(tr("&Event"));
+ m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
+ ->setEnabled(req->hasRight(req->RGetEvent));
+ m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
+ m->addSeparator();
+ showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
+ showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
+ showoldevents->setCheckable(true);
+ showoldevents->setChecked(QSettings().value("profiles/"+pk+"/showOldEvents",false).toBool());
+
+ m=mb->addMenu(tr("&Customer"));
+ m->addAction(tr("&Show all customers"),this,SLOT(customerMgmt()));
+
+ m=mb->addMenu(tr("C&art"));
+ m->addAction(tr("Add &Ticket"),this,SLOT(cartAddTicket()));
+ m->addAction(tr("Add &Voucher"),this,SLOT(cartAddVoucher()));
+ m->addAction(tr("&Remove Item"),this,SLOT(cartRemoveItem()));
+ m->addAction(tr("&Abort Shopping"),this,SLOT(initCart()));
+ m->addSeparator();
+ m->addAction(tr("&Update Shipping Options"),this,SLOT(updateShipping()));
+
+ m=mb->addMenu(tr("&Misc"));
+ m->addAction(tr("Return &ticket..."),this,SLOT(ticketReturn()));
+ m->addAction(tr("Return &voucher..."),this,SLOT(voucherReturn()));
+ m->addSeparator();
+ m->addAction(tr("Edit &Shipping Options..."),this,SLOT(editShipping()));
+ m->addSeparator();
+ m->addAction(tr("&Deduct from voucher..."),this,SLOT(deductVoucher()));
+ m->addSeparator();
+ m->addAction(tr("&Money Log for voucher..."),this,SLOT(moneylogVoucher()));
+ m->addAction(tr("Money Log for &user..."),this,SLOT(moneylogUser()));
+
+ m=mb->addMenu(tr("C&onfigure"));
+ m->addAction(tr("&Auto-Refresh settings..."),this,SLOT(setRefresh()));
+ m->addAction(tr("&Server Access settings..."),this,SLOT(webSettings()));
+
+ m=mb->addMenu(tr("&Admin"));
+ m->addAction(tr("Backup &Settings..."),this,SLOT(backupSettings()))
+ ->setEnabled(req->hasRight(req->RBackup));
+ m->addAction(tr("&Backup now..."),this,SLOT(doBackup()))
+ ->setEnabled(req->hasRight(req->RBackup));
+
+ mb->addMenu(MApplication::helpMenu());
+
+ //tabs
+ setCentralWidget(tab=new QTabWidget);
+ connect(tab,SIGNAL(currentChanged(int)),this,SLOT(tabChanged()));
+
+ //Event tab
+ tab->addTab(eventtab=new QWidget,tr("Events"));
+ QVBoxLayout*vl;QHBoxLayout*hl;
+ eventtab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(eventtable=new QTableView,10);
+ eventtable->setModel(eventmodel=new QStandardItemModel(this));
+ eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
+ eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ QPushButton*p;
+ vl->addWidget(p=new QPushButton(tr("New Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
+ p->setEnabled(req->hasRole("createevent"));
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
+ p->setEnabled(req->hasRole("geteventdata"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+ p->setEnabled(req->hasRole("createorder"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
+ p->setEnabled(req->hasRole("eventsummary"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
+ p->setEnabled(req->hasRole("cancelevent"));
+ connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
+ vl->addStretch(10);
+
+ //Shopping Cart Tab
+ tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
+ carttab->setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ QVBoxLayout*vl2;
+ hl->addLayout(vl2=new QVBoxLayout,2);
+ vl2->addWidget(carttable=new QTableView,10);
+ carttable->setModel(cartmodel=new QStandardItemModel(this));
+ carttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ carttable->setItemDelegate(new MCartTableDelegate(this));
+ QHBoxLayout*hl2;
+ vl2->addLayout(hl2=new QHBoxLayout,0);
+ hl2->addStretch(10);
+ hl2->addWidget(p=new QPushButton(tr("Add Ticket")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddTicket()));
+ hl2->addWidget(p=new QPushButton(tr("Add Voucher")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddVoucher()));
+ hl2->addWidget(p=new QPushButton(tr("Remove Item")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartRemoveItem()));
+ QFrame*frm;
+ hl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::VLine);
+ hl->addLayout(vl2=new QVBoxLayout,1);
+ vl2->addWidget(p=new QPushButton(tr("Customer:")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setCustomer()));
+ vl2->addWidget(cartcustomer=new QLabel("...\n \n \n "));
+ vl2->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Shipping Method:")),0);
+ vl2->addWidget(cartship=new QComboBox,0);
+ cartship->setEditable(false);
+ vl2->addWidget(new QLabel(tr("Delivery Address:")),0);
+ vl2->addWidget(cartaddr=new QTextEdit);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Comments:")),0);
+ vl2->addWidget(cartcomment=new QTextEdit);
+ vl2->addStretch(10);
+ vl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("Check Order")));
+ p->setEnabled(req->hasRole("checkorder"));
+ connect(p,SIGNAL(clicked()),this,SLOT(cartOrder()));
+ hl->addWidget(p=new QPushButton(tr("Clear")));
+ connect(p,SIGNAL(clicked()),this,SLOT(initCart()));
+
+ //Order List Tab
+ tab->addTab(ordertab=new QWidget,tr("Order List"));
+ ordertab->setLayout(hl=new QHBoxLayout);
+ hl->addLayout(vl=new QVBoxLayout,10);
+ vl->addWidget(ordermode=new QComboBox,0);
+ ordermode->addItem(tr("-select mode-"),ORDERNONE);
+ ordermode->addItem(tr("All Orders"),ORDERALL);
+ ordermode->addItem(tr("Open Orders"),ORDEROPEN);
+ ordermode->addItem(tr("Open Reservations"),ORDERRESERVE);
+ ordermode->addItem(tr("Outstanding Payments"),ORDERPAY);
+ ordermode->addItem(tr("Outstanding Refunds"),ORDERREFUND);
+ ordermode->addItem(tr("Undelivered Orders"),ORDERUNSENT);
+ //make sure this entry is the last one, since we use count()-1 to select it
+ ordermode->addItem(tr("-search result-"),ORDERNONE);
+ connect(ordermode,SIGNAL(currentIndexChanged(int)),this,SLOT(updateOrders()));
+ vl->addWidget(ordertable=new QTableView);
+ ordertable->setModel(ordermodel=new QStandardItemModel(this));
+ ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ connect(ordertable,SIGNAL(doubleClicked(const QModelIndex&)),this,SLOT(orderDetails()));
+ hl->addLayout(vl=new QVBoxLayout,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->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Find by Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByTicket()));
+ p->setEnabled(req->hasRole("orderbyticket"));
+ vl->addWidget(p=new QPushButton(tr("Find by Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByEvent()));
+ p->setEnabled(req->hasRole("getordersbyevents"));
+ vl->addWidget(p=new QPushButton(tr("Find by Customer...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByCustomer()));
+ p->setEnabled(req->hasRole("getorderlist"));
+ vl->addWidget(p=new QPushButton(tr("Find by Order ID...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByOrder()));
+ p->setEnabled(req->hasRole("getorder"));
+ vl->addStretch(10);
+
+ //Entrance Control Tab
+ tab->addTab(entrancetab=new QWidget,tr("Entrance"));
+ entrancetab->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(entranceevent=new QComboBox,0);
+ entranceevent->setEditable(false);
+ vl->addSpacing(30);
+ vl->addWidget(new QLabel(tr("Enter or scan Ticket-ID:")),0);
+ vl->addWidget(entrancescan=new QLineEdit,0);
+ connect(entrancescan,SIGNAL(editingFinished()),this,SLOT(entranceValidate()));
+ vl->addWidget(entrancelabel=new QLabel(" "),10);
+ entrancelabel->setAutoFillBackground(true);
+ QFont fnt=entrancelabel->font();
+ fnt.setBold(true);fnt.setPointSize(24);
+ entrancelabel->setFont(fnt);
+ entrancelabel->setAlignment(Qt::AlignCenter);
+
+ //user tab
+ tab->addTab(usertab=new QWidget,tr("Users"));
+ usertab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(usertable=new QTableView,10);
+ usertable->setModel(usermodel=new QStandardItemModel(this));
+ usertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ usertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newUser()));
+ p->setEnabled(req->hasRole("adduser"));
+ vl->addWidget(p=new QPushButton(tr("Delete User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteUser()));
+ p->setEnabled(req->hasRole("deleteuser"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Description...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserDescription()));
+ p->setEnabled(req->hasRole("setuserdescription"));
+ vl->addWidget(p=new QPushButton(tr("Hosts...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserHosts()));
+ p->setEnabled(req->hasRole("getuserhosts"));
+ vl->addWidget(p=new QPushButton(tr("Roles...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserRoles()));
+ p->setEnabled(req->hasRole("getuseracl"));
+ vl->addWidget(p=new QPushButton(tr("Set Password...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setUserPassword()));
+ p->setEnabled(req->hasRole("setpasswd"));
+ vl->addStretch(10);
+
+ //host tab
+ tab->addTab(hosttab=new QWidget,tr("Hosts"));
+ hosttab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(hosttable=new QTableView,10);
+ hosttable->setModel(hostmodel=new QStandardItemModel(this));
+ hosttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ hosttable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(thishostbutton=p=new QPushButton(tr("Add This Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(addThisHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Delete Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteHost()));
+ p->setEnabled(req->hasRole("deletehost"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Generate New Key...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(changeHostKey()));
+ p->setEnabled(req->hasRole("sethostkey"));
+ vl->addWidget(p=new QPushButton(tr("Import...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(importHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Export...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(exportHost()));
+ p->setEnabled(req->hasRole("gethostkey"));
+ vl->addStretch(10);
+
+ //status bar
+ statusBar()->setSizeGripEnabled(true);
+
+ //make sure webrequest knows its settings
+ webSettings(false);
+ //fill tables
+ if(req->hasRight(req->RGetAllEvents)){
+ updateEvents();
+ }else{
+ eventtab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(eventtab),false);
+ }
+ if(!req->hasRole("createorder")&&!req->hasRole("createsale")){
+ carttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(carttab),false);
+ }else{
+ initCart();
+ }
+ updateShipping();
+ if(req->hasRole("getorderlist")){
+ updateOrders();
+ }else{
+ ordertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(ordertab),false);
+ }
+ if(req->hasRole("getusers")){
+ updateUsers();
+ }else{
+ usertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(usertab),false);
+ }
+ if(req->hasRole("gethosts")){
+ updateHosts();
+ }else{
+ hosttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(hosttab),false);
+ }
+}
+
+void MOverview::updateEvents()
+{
+ MTGetAllEvents gae=req->queryGetAllEvents();
+ if(gae.stage()!=gae.Success){
+ qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
+ return;
+ }
+ QList<MOEvent>evl=gae.getevents();
+ eventmodel->clear();
+ eventmodel->insertColumns(0,6);
+ eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
+ QDateTime now=QDateTime::currentDateTime();
+ for(int i=0,j=0;i<evl.size();i++){
+ QDateTime stime=QDateTime::fromTime_t(evl[i].start());
+ if(stime<now && !showoldevents->isChecked())continue;
+ eventmodel->insertRow(j);
+ eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
+ eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
+ eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
+ eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
+ eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
+ eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
+ eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
+ j++;
+ }
+ eventtable->resizeColumnsToContents();
+ //in case this was called from changing the check state
+ QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showoldevents->isChecked());
+}
+
+void MOverview::closeEvent(QCloseEvent*ce)
+{
+ //make sure session is deleted
+ req->logout();
+ //actually close window
+ QMainWindow::closeEvent(ce);
+}
+
+MOverview::~MOverview()
+{
+ //free requestor
+ req->deleteLater();
+}
+
+void MOverview::relogin()
+{
+ setEnabled(false);
+ if(!req->relogin())
+ QMessageBox::warning(this,tr("Warning"),tr("I was unable to renew the login at the server."));
+ setEnabled(true);
+}
+
+void MOverview::newEvent()
+{
+ MEventEditor ed(this);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::editEvent()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventEditor ed(this,id);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::eventSummary()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventSummary ed(this,id);
+ ed.exec();
+}
+
+void MOverview::eventCancel()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MTGetEvent getev=MTGetEvent::query(id);
+ if(!getev.hasError()){
+ bool ok;
+ MOEvent ev=getev.getevent();
+ QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
+ if(!ok)return;
+ MTCancelEvent cev=MTCancelEvent::query(id,r);
+ if(!cev.hasError())
+ QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
+ else
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
+ }
+}
+
+void MOverview::updateShipping()
+{
+ cartship->clear();
+ cartship->addItem(tr("(No Shipping)"),-1);
+ MTGetAllShipping sh=MTGetAllShipping::query();
+ QList<MOShipping>ship=sh.getshipping();
+ for(int i=0;i<ship.size();i++)
+ cartship->addItem(ship[i].description(),(int)ship[i].id());
+}
+
+void MOverview::updateUsers()
+{
+ MTGetAllUsers au=req->queryGetAllUsers();
+ if(au.hasError())return;
+ QList<MOUser>usl=au.getusers();
+ usermodel->clear();
+ usermodel->insertColumns(0,2);
+ usermodel->insertRows(0,usl.size());
+ usermodel->setHorizontalHeaderLabels(QStringList()<<tr("Login Name")<<tr("Description"));
+ for(int i=0;i<usl.size();i++){
+ usermodel->setData(usermodel->index(i,0),usl[i].name().value());
+ usermodel->setData(usermodel->index(i,1),usl[i].description().value());
+ }
+ usertable->resizeColumnsToContents();
+}
+
+void MOverview::newUser()
+{
+ //get name
+ QString name;
+ while(1){
+ bool ok;
+ name=QInputDialog::getText(this,tr("New User"),tr("Please enter new user name (only letters, digits, and underscore allowed):"),QLineEdit::Normal,name,&ok);
+ if(!ok)
+ return;
+ if(QRegExp("[A-Za-z0-9_\\.,:-]+").exactMatch(name))
+ break;
+ if(QMessageBox::warning(this,tr("Error"),tr("The user name must contain only letters, digits, dots and underscores and must be at least one character long!"),QMessageBox::Retry|QMessageBox::Abort)!=QMessageBox::Retry)
+ return;
+ }
+ //get password
+ QString pwd=QInputDialog::getText(this,tr("Password"),tr("Please enter an initial password for the user:"),QLineEdit::Password);
+ //send request
+ req->queryCreateUser(name,pwd,"");
+ //update display
+ updateUsers();
+}
+
+void MOverview::deleteUser()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //make sure user wants this
+ if(QMessageBox::question(this,tr("Delete User?"),tr("Really delete user '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //get replacement
+ bool ok;
+ QStringList rplc;
+ rplc<<tr("(Nobody)","this is a username for no user, the string must contain '(' to distinguish it from the others");
+ for(int i=0;i<usermodel->rowCount();i++)
+ rplc<<usermodel->data(usermodel->index(i,0)).toString();
+ QString rp=QInputDialog::getItem(this,tr("Delete User"),tr("Select which user will inherit this users database objects:"),rplc,0,false,&ok);
+ if(!ok)return;
+ //delete
+ MTDeleteUser ret=req->queryDeleteUser(name,rp);
+ if(ret.hasError())
+ QMessageBox::warning(this,tr("Error"),tr("Cannot delete user: %1").arg(ret.errorString()));
+ updateUsers();
+}
+
+void MOverview::editUserDescription()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ QString descr=usermodel->data(usermodel->index(sel.row(),1)).toString();
+ //edit descr
+ bool ok;
+ descr=QInputDialog::getText(this,tr("Edit Description"),tr("Descriptionof user %1:").arg(name),QLineEdit::Normal,descr,&ok);
+ if(ok)
+ req->querySetUserDescription(name,descr);
+ //update
+ updateUsers();
+}
+
+void MOverview::editUserRoles()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MOUser usr(req,name);
+ MCheckList acl=usr.getRoles();
+ MCheckDialog cd(this,acl,"Edit ACL of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setRoles(cd.getCheckList());*/
+}
+
+void MOverview::editUserHosts()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MUser usr(req,name);
+ MCheckList acl=usr.getHosts();
+ MCheckDialog cd(this,acl,"Edit hosts of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setHosts(cd.getCheckList());*/
+}
+
+void MOverview::setMyPassword()
+{
+ MPasswordChange pc(this);
+ if(pc.exec()==QDialog::Accepted){
+ MTChangeMyPassword cmp=MTChangeMyPassword::query(pc.oldPassword(),pc.newPassword());
+ if(cmp.hasError())
+ QMessageBox::warning(this,tr("Warning"),tr("Error setting password: %1").arg(cmp.errorString()));
+ }
+}
+void MOverview::setUserPassword()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //get new password
+ MPasswordChange pc(this,name);
+ if(pc.exec()!=QDialog::Accepted)return;
+ QString p=pc.newPassword();
+ if(p==""){
+ QMessageBox::warning(this,tr("Warning"),tr("The password must be non-empty and both lines must match"));
+ return;
+ }
+ //...
+ MUser usr(req,name);
+ usr.changePassword(p);*/
+}
+
+void MOverview::updateHosts()
+{/*TODO
+ bool foundThis=false;
+ QString thisHost=req->hostName();
+ QList<MHost>hsl=req->getAllHosts();
+ hostmodel->clear();
+ hostmodel->insertColumns(0,2);
+ hostmodel->insertRows(0,hsl.size());
+ hostmodel->setHorizontalHeaderLabels(QStringList()<<tr("Host Name")<<tr("Host Key"));
+ for(int i=0;i<hsl.size();i++){
+ hostmodel->setData(hostmodel->index(i,0),hsl[i].hostId());
+ hostmodel->setData(hostmodel->index(i,1),hsl[i].hostKey());
+ if(thisHost==hsl[i].hostId())
+ foundThis=true;
+ }
+ hosttable->resizeColumnsToContents();
+ thishostbutton->setEnabled(!foundThis && req->hasRole("addhost"));*/
+}
+
+void MOverview::newHost()
+{/*TODO
+ //get Host Name
+ QString hname;
+ do{
+ bool ok;
+ hname=QInputDialog::getText(this,tr("Create New Host"),tr("Please enter a host name:"),QLineEdit::Normal,hname,&ok);
+ if(!ok)return;
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname))continue;
+ }while(false);
+ //create it
+ MHost hst(req,hname);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The key of this new host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.create();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::addThisHost()
+{/*TODO
+ MHost hst(req,req->hostName(),QSettings().value("hostkey").toString());
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::deleteHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Delete this Host?"),tr("Really delete host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //delete it
+ MHost(req,name).deleteHost();
+ updateHosts();*/
+}
+
+void MOverview::changeHostKey()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Change Host Key?"),tr("Really change the key of host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //change it
+ MHost hst(req,name);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The new key of this host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.save();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::importHost()
+{/*TODO
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptOpen);
+ fdlg.setFileMode(QFileDialog::ExistingFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::ReadOnly)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ //read content (max: 10k to limit potential damage)
+ QStringList fc=QString::fromAscii(fd.read(10240)).split("\n",QString::SkipEmptyParts);
+ fd.close();
+ //check content
+ if(fc.size()<3){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ if(fc[0].trimmed()!="MagicSmokeHostKey"){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ QString hname=fc[1].trimmed();
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name."));
+ return;
+ }
+ QString key=fc[2].trimmed();
+ if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key."));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ if(chk!=fc[3].trimmed()){
+ QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file."));
+ return;
+ }
+ //save
+ MHost hst(req,hname,key);
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::exportHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ QString key=hostmodel->data(hostmodel->index(sel.row(),1)).toString();
+ if(name[0]=='_' || key==""){
+ QMessageBox::warning(this,tr("Warning"),tr("This host cannot be exported."));
+ return;
+ }
+ //save
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptSave);
+ fdlg.setFileMode(QFileDialog::AnyFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ QString out="MagicSmokeHostKey\n"+name+"\n"+key+"\n"+chk;
+ fd.write(out.toAscii());
+ fd.close();*/
+}
+
+
+void MOverview::initCart()
+{
+ //clear cart
+ cartmodel->clear();
+ cartmodel->setHorizontalHeaderLabels(QStringList()<<tr("Amount")<<tr("Title")<<tr("Start Time"));
+ //clear customer
+ customer=MCustomer();
+ cartcustomer->setText("");
+ //clear address/comment
+ cartaddr->setPlainText("");
+ cartcomment->setPlainText("");
+ //clear shipping
+ cartship->setCurrentIndex(0);
+}
+
+void MOverview::setCustomer()
+{/*TODO
+ MCustomerListDialog mcl(req,this,true,customer.customerID());
+ if(mcl.exec()!=QDialog::Accepted)return;
+ customer=mcl.getCustomer();
+ cartcustomer->setText(customer.getNameAddress());*/
+}
+
+static const int CART_TICKET=1;
+static const int CART_VOUCHER=2;
+
+static const int CART_IDROLE=Qt::UserRole;//ticket id
+static const int CART_PRICEROLE=Qt::UserRole;//voucher price
+static const int CART_VALUEROLE=Qt::UserRole+1;//voucher value
+static const int CART_TYPEROLE=Qt::UserRole+2;//which is it? ticket or voucher?
+
+void MOverview::cartAddTicket()
+{
+ //create ticket selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Event to order Ticket"));
+ QTableView*tv;
+ QHBoxLayout*hl;
+ QVBoxLayout*vl;
+ dlg.setLayout(vl=new QVBoxLayout);
+ vl->addWidget(tv=new QTableView,10);
+ tv->setModel(eventmodel);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->resizeColumnsToContents();
+ vl->addSpacing(15);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Select")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ connect(tv,SIGNAL(doubleClicked(const QModelIndex&)),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ QModelIndex idx=tv->currentIndex();
+ if(!idx.isValid())return;
+ int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt();
+ if(id<0)return;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(idx.row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(idx.row(),0)));
+ carttable->resizeColumnsToContents();
+ }
+}
+
+void MOverview::eventOrderTicket()
+{
+ //get selected event
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ //activate order tab
+ tab->setCurrentWidget(carttab);
+ //insert event into table
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(ilst[0].row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(ilst[0].row(),0)));
+ carttable->resizeColumnsToContents();
+}
+
+void MOverview::cartAddVoucher()
+{/*TODO
+ //create voucher selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Voucher"));
+ QComboBox*cp,*cv;
+ QHBoxLayout*hl;
+ QGridLayout*gl;
+ QStandardItemModel mdl;
+ QRegExpValidator regv(priceRegExp(),this);
+ QList<int>prc=req->getVoucherPrices();
+ mdl.insertRows(0,prc.size());
+ mdl.insertColumns(0,1);
+ for(int i=0;i<prc.size();i++)mdl.setData(mdl.index(i,0),cent2str(prc[i]));
+ dlg.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Select voucher price and value:")),0,0,1,2);
+ if(req->hasRole("_anypricevoucher")){
+ gl->addWidget(new QLabel(tr("Price:")),1,0);
+ gl->addWidget(cp=new QComboBox,1,1);
+ cp->setModel(&mdl);
+ cp->setEditable(true);
+ cp->setValidator(®v);
+ }else cp=0;
+ gl->addWidget(new QLabel(tr("Value:")),2,0);
+ gl->addWidget(cv=new QComboBox,2,1);
+ cv->setModel(&mdl);
+ cv->setEditable(req->hasRole("_anyvoucher"));
+ cv->setValidator(®v);
+ gl->setRowMinimumHeight(3,15);
+ gl->setColumnStretch(0,0);
+ gl->setColumnStretch(1,1);
+ gl->setRowStretch(3,1);
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ int price,value;
+ value=str2cent(cv->currentText());
+ if(req->hasRole("_anypricevoucher") && cp)
+ price=str2cent(cp->currentText());
+ else
+ price=value;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),price,CART_PRICEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),value,CART_VALUEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_VOUCHER,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (price: %1, value %2)").arg(cent2str(price)).arg(cent2str(value)));
+ carttable->resizeColumnsToContents();
+ }*/
+}
+
+void MOverview::cartRemoveItem()
+{
+ //get selection
+ QModelIndex idx=carttable->currentIndex();
+ if(!idx.isValid())return;
+ //remove row
+ cartmodel->removeRow(idx.row());
+}
+
+void MOverview::cartOrder()
+{
+ //sanity checks
+ if(cartmodel->rowCount()<1){
+ QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it."));
+ return;
+ }
+ if(!customer.isValid()){
+ QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!"));
+ return;
+ }
+ ///////////////
+ //create order
+ QDomDocument doc;
+ QDomElement root=doc.createElement("Order");
+ root.setAttribute("customer",customer.id());
+ //is there a delivery address
+ QString s=cartaddr->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement da=doc.createElement("DeliveryAddress");
+ da.appendChild(doc.createTextNode(s));
+ root.appendChild(da);
+ }
+ //is there a comment?
+ s=cartcomment->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement cc=doc.createElement("Comment");
+ cc.appendChild(doc.createTextNode(s));
+ root.appendChild(cc);
+ }
+ //scan tickets & scan vouchers
+ for(int i=0;i<cartmodel->rowCount();i++){
+ QModelIndex idx=cartmodel->index(i,0);
+ int tp=cartmodel->data(idx,CART_TYPEROLE).toInt();
+ if(tp==CART_TICKET){
+ int amt=cartmodel->data(idx).toInt();
+ int evid=cartmodel->data(idx,CART_IDROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Ticket");
+ tc.setAttribute("event",evid);
+ root.appendChild(tc);
+ }
+ }else
+ if(tp==CART_VOUCHER){
+ int amt=cartmodel->data(idx).toInt();
+ int price=cartmodel->data(idx,CART_PRICEROLE).toInt();
+ int value=cartmodel->data(idx,CART_VALUEROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Voucher");
+ tc.setAttribute("price",price);
+ tc.setAttribute("value",value);
+ root.appendChild(tc);
+ }
+
+ }
+ }
+ //set shipping info
+ if(cartship->currentIndex()>0){
+ QDomElement si=doc.createElement("Shipping");
+ si.setAttribute("type",cartship->itemData(cartship->currentIndex()).toInt());
+ root.appendChild(si);
+ }
+ //finalize
+ doc.appendChild(root);
+ //send
+ /*TODO
+ if(req->request("checkorder",doc.toByteArray())==false){
+ QMessageBox::warning(this,tr("Error"),tr("The request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Error"),tr("A problem occurred during the order: %1").arg(qApp->translate("php::",req->responseBody())));
+ return;
+ }
+ //parse result
+ QDomDocument rdoc;
+ rdoc.setContent(req->responseBody());
+ //display order and give user chance to actually order it
+ MOrderWindow *ow=new MOrderWindow(this,req,MOrder(req,rdoc.documentElement()));
+ ow->show();
+ //empty the cart
+ initCart();*/
+}
+
+void MOverview::customerMgmt()
+{/*TODO
+ MCustomerListDialog mcl(req,this);
+ mcl.exec();*/
+}
+
+void MOverview::editShipping()
+{/*TODO
+ MShippingEditor se(req,this);
+ se.exec();
+ updateShipping();*/
+}
+
+void MOverview::tabChanged()
+{/*TODO
+ QWidget*w=tab->currentWidget();
+ if(w==entrancetab){
+ //fill combobox from eventmodel
+ int ci=entranceevent->currentIndex();
+ int cev=-1;
+ if(ci>=0)cev=entranceevent->itemData(ci).toInt();
+ ci=-1;
+ entranceevent->clear();
+ for(int i=0;i<eventmodel->rowCount();i++){
+ QString ev=eventmodel->data(eventmodel->index(i,0)).toString()+" "+
+ eventmodel->data(eventmodel->index(i,1)).toString();
+ int eid=eventmodel->data(eventmodel->index(i,0),Qt::UserRole).toInt();
+ entranceevent->addItem(ev,eid);
+ if(eid==cev)ci=i;
+ }
+ if(ci>=0)entranceevent->setCurrentIndex(ci);
+ //set focus on scanner
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");
+ }*/
+}
+
+void MOverview::entranceValidate()
+{/*TODO
+ //get event ID
+ int ci=entranceevent->currentIndex();
+ if(ci<0)return;
+ int cev=entranceevent->itemData(ci).toInt();
+ //check content
+ QString tid=entrancescan->text().trimmed();
+ entrancescan->setText("");
+ //avoid spurious events
+ if(tid=="")return;
+ //avoid double scans
+ QDateTime now=QDateTime::currentDateTime();
+ if(tid==lastbarcode && lastbcscan.addSecs(20)>=now)
+ return;
+ lastbarcode=tid;
+ lastbcscan=now;
+ //reset display
+ QPalette pal=entrancelabel->palette();
+ QPalette::ColorRole rl=QPalette::Window;
+ pal.setColor(rl,Qt::lightGray);
+ entrancelabel->setPalette(pal);
+ entrancelabel->setText(tr("searching...","entrance control"));
+ //ask the server
+ MTicket tick(req,tid);
+ //decide what to do
+ if(!tick.isValid()){
+ entrancelabel->setText(tr("Ticket \"%1\" Not Valid").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.eventID()!=cev){
+ entrancelabel->setText(tr("Ticket \"%1\" is not for this event.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.status()==MTicket::Used){
+ entrancelabel->setText(tr("Ticket \"%1\" has already been used").arg(tid));
+ pal.setColor(rl,Qt::magenta);
+ }else
+ if(tick.status()!=MTicket::Bought){
+ entrancelabel->setText(tr("Ticket \"%1\" has not been bought.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.paymentStatus()==MTicket::PSOk){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedRefund){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok; the Order has a refund").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedPayment){
+ entrancelabel->setText(tr("Ticket \"%1\" is not paid for!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else{
+ entrancelabel->setText(tr("Ticket \"%1\" cannot be accepted, please check the order!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }
+
+ entrancelabel->setPalette(pal);
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");*/
+}
+
+//helper: finds out whether an order should be printed.
+static inline bool candoUpdateOrders(int omode,const MOrder&ord)
+{
+ if(omode==ORDERALL)return true;
+ if((omode&ORDERPAY)!=0 && ord.needsPayment())return true;
+ if((omode&ORDERREFUND)!=0 && ord.needsRefund())return true;
+ if((omode&ORDERUNSENT)!=0 && !ord.isSent())return true;
+ if((omode&ORDERRESERVE)!=0 && ord.isReservation())return true;
+ return false;
+}
+
+void MOverview::updateOrders()
+{/*TODO
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ int omode=ordermode->itemData(ordermode->currentIndex()).toInt();
+ if(omode==ORDERNONE)return;
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ if(!candoUpdateOrders(omode,orders[i]))continue;
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ int cid=orders[i].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ cl++;
+ }
+ ordertable->resizeColumnsToContents();*/
+}
+
+void MOverview::orderDetails()
+{/*TODO
+ //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::orderByTicket()
+{/*TODO
+ //get selected order
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Enter Ticket"),tr("Please enter the ID of one of the tickets of the order you seek:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ //request it
+ if(!req->request("orderbyticket",tid.toUtf8())){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to query server."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),qApp->translate("php::",req->responseBody()));
+ return;
+ }
+ int id=req->responseBody().trimmed().toInt(&ok);
+ if(!ok || id<0){
+ QMessageBox::warning(this,tr("Warning"),tr("Server returned an invalid order ID."));
+ return;
+ }
+ //open order window
+ MOrderWindow *om=new MOrderWindow(this,req,MOrder(req,id));
+ om->setAttribute(Qt::WA_DeleteOnClose);
+ om->show();*/
+}
+
+void MOverview::orderByEvent()
+{/*TODO
+ //display selection dialog
+ QDialog d(this);
+ d.setWindowTitle(tr("Select Event"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ QTableView*tv;
+ vl->addWidget(tv=new QTableView,10);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->setModel(eventmodel);
+ tv->resizeColumnsToContents();
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ //wait for user
+ if(d.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ QModelIndexList ilst=tv->selectionModel()->selectedIndexes();
+ if(ilst.size()<1){
+ qDebug("nothing selected");
+ return;
+ }
+ //get events
+ QList<int>eventids;
+ for(int i=0;i<ilst.size();i++){
+ int eid=eventmodel->data(eventmodel->index(ilst[i].row(),0),Qt::UserRole).toInt();
+ if(!eventids.contains(eid))eventids.append(eid);
+ }
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getOrdersByEvents(eventids);
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ for(int cl=0;cl<orders.size();cl++){
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[cl].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[cl].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[cl].amountPaidString());
+ int cid=orders[cl].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByCustomer()
+{/*TODO
+ //display selection dialog
+ MCustomerListDialog mcl(req,this,true);
+ //wait for user
+ if(mcl.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ MCustomer cst=mcl.getCustomer();
+ if(!cst.isValid()){
+ qDebug("nothing selected");
+ return;
+ }
+ qint64 custid=cst.customerID();
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ //filter
+ if(orders[i].customerID()!=custid)continue;
+ //put into table
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ ordermodel->setData(ordermodel->index(cl,3),cst.name());
+ //count up
+ cl++;
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByOrder()
+{/*TODO
+ //ask for OrderID
+ bool ok;
+ int oid=QInputDialog::getInteger(this,tr("Enter Order ID"),tr("Please enter the ID of the order you want to display:"),0,0,2147483647,1,&ok);
+ if(!ok)return;
+ //display
+ MOrder ord(req,oid);
+ if(!ord.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This order does not exist."));
+ return;
+ }
+ MOrderWindow *ow=new MOrderWindow(this,req,ord);
+ ow->show();*/
+}
+
+void MOverview::ticketReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Ticket"),tr("Please enter the ticket ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MTicket tick(req,tid);
+ if(!tick.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid ticket."));
+ return;
+ }
+ //check state
+ if(tick.status()!=MTicket::Bought && tick.status()!=MTicket::Reserved){
+ QMessageBox::warning(this,tr("Warning"),tr("This ticket cannot be returned, it has already been used or is in the wrong state."));
+ return;
+ }
+ //submit
+ QString r=tick.ticketReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::voucherReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Voucher"),tr("Please enter the voucher ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MVoucher vouc(req,tid);
+ if(!vouc.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid voucher."));
+ return;
+ }
+ //check state
+ if(vouc.isUsed()){
+ QMessageBox::warning(this,tr("Warning"),tr("This voucher cannot be returned, it has already been used."));
+ return;
+ }
+ //submit
+ QString r=vouc.voucherReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::deductVoucher()
+{/*TODO
+ //get voucher ID and amount
+ QDialog d;
+ d.setWindowTitle(tr("Deduct from Voucher"));
+ QGridLayout *gl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Using a voucher to pay outside the system.")),0,0,1,2);
+
+ QLineEdit*vid;
+ MCentSpinBox*cent;
+ gl->addWidget(new QLabel(tr("Amount to deduct:")),1,0);
+ gl->addWidget(cent=new MCentSpinBox,1,1);
+ gl->addWidget(new QLabel(tr("Voucher ID:")),2,0);
+ gl->addWidget(vid=new QLineEdit,2,1);
+
+ gl->setRowMinimumHeight(3,15);
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ if(vid->text().trimmed()=="" || cent->value()<=0)return;
+ //query server
+ QByteArray r=vid->text().trimmed().toAscii()+"\n"+QString::number(cent->value()).toAscii();
+ if(!req->request("usevoucheroutside",r)){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ QStringList sl=QString::fromAscii(req->responseBody().trimmed()).split("\n");
+ int tak=-1,rem=-1;
+ if(sl.size()>0)tak=sl[0].trimmed().toInt();
+ if(sl.size()>1)rem=sl[1].trimmed().toInt();
+ QMessageBox::information(this,tr("Deducted from Voucher"),tr("Value taken from voucher: %1\nValue remaining on voucher: %2").arg(cent2str(tak)).arg(cent2str(rem)));*/
+}
+
+void MOverview::refreshData()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ if(set.value("refreshEvents",false).toBool() && req->hasRole("geteventlist"))
+ updateEvents();
+ if(set.value("refreshUsers",false).toBool() && req->hasRole("getusers"))
+ updateUsers();
+ if(set.value("refreshHosts",false).toBool() && req->hasRole("gethosts"))
+ updateHosts();
+ if(set.value("refreshShipping",false).toBool() && req->hasRole("getshipping"))
+ updateShipping();
+}
+
+void MOverview::setRefresh()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //dialog
+ QDialog d;
+ d.setWindowTitle(tr("Refresh Settings"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Refresh Rate (minutes):")),1);
+ QSpinBox*rate;
+ hl->addWidget(rate=new QSpinBox,0);
+ rate->setRange(1,999);
+ rate->setValue(set.value("refresh",300).toInt()/60);
+ QCheckBox *rev,*rus,*rho,*rsh;
+ vl->addWidget(rev=new QCheckBox(tr("refresh &event list")));
+ rev->setChecked(set.value("refreshEvents",false).toBool());
+ vl->addWidget(rus=new QCheckBox(tr("refresh &user list")));
+ rus->setChecked(set.value("refreshUsers",false).toBool());
+ vl->addWidget(rho=new QCheckBox(tr("refresh &host list")));
+ rho->setChecked(set.value("refreshHosts",false).toBool());
+ vl->addWidget(rsh=new QCheckBox(tr("refresh &shipping list")));
+ rho->setChecked(set.value("refreshShipping",false).toBool());
+ vl->addSpacing(15);
+ vl->addStretch(10);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ set.setValue("refreshEvents",rev->isChecked());
+ set.setValue("refreshUsers",rus->isChecked());
+ set.setValue("refreshHosts",rho->isChecked());
+ set.setValue("refreshShipping",rsh->isChecked());
+ set.setValue("refresh",rate->value()*60);
+ //reset timer
+ rtimer.stop();
+ rtimer.setInterval(rate->value()*60000);
+ rtimer.start();
+}
+
+void MOverview::webSettings(bool showdlg)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //get settings
+ MSInterface::LogLevel lvl=MSInterface::LogLevel(set.value("webloglevel", MSInterface::LogOnError).toInt());
+ int timeout=set.value("webtimeout",30).toInt();
+ //dialog
+ if(showdlg){
+ QDialog d;
+ d.setWindowTitle(tr("Server Access Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Request Timeout (seconds):")),0,0);
+ QSpinBox*tmout;
+ gl->addWidget(tmout=new QSpinBox,0,1);
+ tmout->setRange(10,999);
+ tmout->setValue(timeout);
+ QComboBox *log;
+ gl->addWidget(new QLabel(tr("Log Level:")),1,0);
+ gl->addWidget(log=new QComboBox,1,1);
+ log->addItem(tr("Minimal Logging"),MSInterface::LogMinimal);
+ log->addItem(tr("Log Details on Error"),MSInterface::LogOnError);
+ log->addItem(tr("Always Log Details"),MSInterface::LogDetailed);
+ switch(lvl){
+ case MSInterface::LogMinimal:log->setCurrentIndex(0);break;
+ case MSInterface::LogOnError:log->setCurrentIndex(1);break;
+ case MSInterface::LogDetailed:log->setCurrentIndex(2);break;
+ }
+ gl->setRowMinimumHeight(2,15);
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ lvl=MSInterface::LogLevel(log->itemData(log->currentIndex()).toInt());
+ timeout=tmout->value();
+ set.setValue("webloglevel",lvl);
+ set.setValue("webtimeout",timeout);
+ }
+ //reset webrequest
+ req->setLogLevel(lvl);
+ req->setWebTimeout(timeout*1000);
+}
+
+void MOverview::doBackup()
+{
+ baktimer.stop();
+ //sanity check
+ if(!req->hasRight(req->RBackup))return;
+ //get settings
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ //get data
+ MTBackup bc;
+ bc=MTBackup::query();
+ if(bc.stage()!=bc.Success){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup failed with error (%2): %1").arg(bc.errorString()).arg(bc.errorType()));
+ return;
+ }
+ if(bc.getbackup().isNull()||bc.getbackup().value().isEmpty()){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup returned empty."));
+ return;
+ }
+ //rotate files
+ QFile(path+"."+QString::number(gens)).remove();
+ for(int i=gens-1;i>=0;i--){
+ if(i)
+ QFile(path+"."+QString::number(i)).rename(path+"."+QString::number(i+1));
+ else
+ QFile(path).rename(path+".1");
+ }
+ //store new data
+ QFile fd(path);
+ if(fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ fd.write(bc.getbackup().value().toAscii());
+ fd.close();
+ set.setValue("backuptime",QDateTime::currentDateTime().toTime_t());
+ QMessageBox::information(this,tr("Backup"),tr("The backup was successful."));
+ int tm=set.value("backupinterval",0).toInt()*86400000;
+ if(tm)baktimer.start(tm);
+ }else
+ QMessageBox::warning(this,tr("Warning"),tr("Cannot create backup file."));
+}
+
+void MOverview::backupSettings()
+{
+ //show dialog
+ MBackupDialog d(this,profilekey);
+ d.exec();
+ //reset timer
+ int btm=QSettings().value("profiles/"+profilekey+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+profilekey+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //start timer
+ baktimer.start(btm*1000);
+ }
+}
+
+void MOverview::moneylogVoucher()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("Voucher ID"),tr("Please enter voucher ID to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"voucher\n"+vid).exec();*/
+}
+
+void MOverview::moneylogUser()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("User"),tr("Please enter login name of user to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"user\n"+vid).exec();*/
+}
+
+
+/**********************************************/
+
+MBackupDialog::MBackupDialog(QWidget*par,QString pk)
+ :QDialog(par),profilekey(pk)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ int tm=set.value("backupinterval",0).toInt();
+ //dialog
+ setWindowTitle(tr("Backup Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ setLayout(gl=new QGridLayout);
+ QPushButton*p;
+ gl->addWidget(new QLabel(tr("Backup File:")),0,0);
+ gl->addWidget(lpath=new QLineEdit(path),0,1);
+ gl->addWidget(p=new QPushButton(tr("...")),0,2);
+ connect(p,SIGNAL(clicked()),this,SLOT(getpath()));
+
+ gl->addWidget(new QLabel(tr("Generations to keep:")),1,0);
+ gl->addWidget(gener=new QSpinBox,1,1,1,2);
+ gener->setRange(1,16);
+ gener->setValue(gens);
+
+ gl->addWidget(new QLabel(tr("Automatic Backup:")),2,0);
+ gl->addWidget(autob=new QCheckBox,2,1,1,2);
+ autob->setChecked(tm>0);
+
+ gl->addWidget(new QLabel(tr("Interval in days:")),3,0);
+ gl->addWidget(interv=new QSpinBox,3,1,1,2);
+ interv->setRange(1,24);
+ interv->setValue(tm>0?tm:1);
+
+ gl->setRowMinimumHeight(4,15);
+ gl->addLayout(hl=new QHBoxLayout,5,0,1,3);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ connect(p,SIGNAL(clicked()),this,SLOT(save()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+void MBackupDialog::getpath()
+{
+ QString path=QFileDialog::getSaveFileName(this,tr("Backup File"),lpath->text());
+ if(path!="")lpath->setText(path);
+}
+
+void MBackupDialog::save()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ set.setValue("backupfile",lpath->text());
+ set.setValue("backupgenerations",gener->value());
+ set.setValue("backupinterval",autob->isChecked()?interv->value():0);
+}
+/**********************************************/
+
+MPasswordChange::MPasswordChange(QWidget*par,QString user)
+ :QDialog(par)
+{
+ oldpwd=newpwd1=newpwd2=0;
+ if(user=="")
+ setWindowTitle(tr("Change my password"));
+ else
+ setWindowTitle(tr("Reset password of user \"%1\"").arg(user));
+ QGridLayout*gl;
+ setLayout(gl=new QGridLayout);
+ if(user==""){
+ gl->addWidget(new QLabel(tr("Old Password:")),0,0);
+ gl->addWidget(oldpwd=new QLineEdit,0,1);
+ oldpwd->setEchoMode(QLineEdit::Password);
+ }
+ gl->addWidget(new QLabel(tr("New Password:")),1,0);
+ gl->addWidget(newpwd1=new QLineEdit,1,1);
+ newpwd1->setEchoMode(QLineEdit::Password);
+ gl->addWidget(new QLabel(tr("Repeat Password:")),2,0);
+ gl->addWidget(newpwd2=new QLineEdit,2,1);
+ newpwd2->setEchoMode(QLineEdit::Password);
+
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Set Password")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+QString MPasswordChange::oldPassword()
+{
+ if(oldpwd)return oldpwd->text();
+ return "";
+}
+
+QString MPasswordChange::newPassword()
+{
+ if(newpwd1==0 || newpwd2==0)return "";
+ if(newpwd1->text()!=newpwd2->text())return "";
+ return newpwd1->text();
+}
+
+
+/********************************************************************************/
+
+MCartTableDelegate::MCartTableDelegate(QObject*p)
+ :QItemDelegate(p)
+{
+}
+
+QWidget *MCartTableDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &/* option */,
+ const QModelIndex & index ) const
+{
+ //base class
+ if(index.column()!=0)return 0;
+
+ QSpinBox *editor = new QSpinBox(parent);
+ editor->setRange(1,1000);
+ editor->installEventFilter(const_cast<MCartTableDelegate*>(this));
+ return editor;
+}
+
+void MCartTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0)
+ ((QSpinBox*)editor)->setValue(index.model()->data(index).toInt());
+}
+
+void MCartTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0){
+ int newval=((QSpinBox*)editor)->value();
+ model->setData(index,newval);
+ }
+}
--- /dev/null
+//
+// C++ Interface: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_OVERVIEW_H
+#define MAGICSMOKE_OVERVIEW_H
+
+#include <QDateTime>
+#include <QDialog>
+#include <QItemDelegate>
+#include <QMainWindow>
+#include <QTimer>
+
+#include "customer.h"
+
+class QAction;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class QStandardItemModel;
+class QTabWidget;
+class QTableView;
+
+class MSInterface;
+
+/**Main Overview Window*/
+class MOverview:public QMainWindow
+{
+ Q_OBJECT
+ public:
+ /**construct the window with web-request/session handler and QSettings-key for current profile*/
+ MOverview(QString);
+ ~MOverview();
+ protected:
+ /**handle closing the window: close the session too*/
+ void closeEvent(QCloseEvent*);
+ private slots:
+ /**try to log in again*/
+ void relogin();
+
+ /**create a new event*/
+ void newEvent();
+ /**edit existing event*/
+ void editEvent();
+ /**update list of events*/
+ void updateEvents();
+ /**order ticket from event tab*/
+ void eventOrderTicket();
+ /**open event summary*/
+ void eventSummary();
+ /**cancel the event*/
+ void eventCancel();
+
+ /**update shipping info*/
+ void updateShipping();
+
+ /**get all orders, update list*/
+ void updateOrders();
+ /**open order detail window*/
+ void orderDetails();
+
+ /**update list of users*/
+ void updateUsers();
+ /**create new user*/
+ void newUser();
+ /**delete selected user*/
+ void deleteUser();
+ /**set users description*/
+ void editUserDescription();
+ /**set users roles*/
+ void editUserRoles();
+ /**set users hosts*/
+ void editUserHosts();
+ /**set my own password*/
+ void setMyPassword();
+ /**set a users password*/
+ void setUserPassword();
+
+ /**update list of hosts*/
+ void updateHosts();
+ /**create new host*/
+ void newHost();
+ /**create a database entry for this host*/
+ void addThisHost();
+ /**delete a host*/
+ void deleteHost();
+ /**generate a new key*/
+ void changeHostKey();
+ /**import host from file*/
+ void importHost();
+ /**export host to file*/
+ void exportHost();
+
+ /**decide what customer to use*/
+ void setCustomer();
+ /**initialize cart tab*/
+ void initCart();
+ /**add a ticket to the cart*/
+ void cartAddTicket();
+ /**add a voucher to the cart*/
+ void cartAddVoucher();
+ /**remove item from the cart*/
+ void cartRemoveItem();
+ /**check the order on the server*/
+ void cartOrder();
+
+ /**manage customers*/
+ void customerMgmt();
+
+ /**edit shipping options*/
+ void editShipping();
+
+ /**generic check which tab is active*/
+ void tabChanged();
+
+ /**react on entry in Entrance tab*/
+ void entranceValidate();
+
+ /**return a ticket*/
+ void ticketReturn();
+ /**return a voucher*/
+ void voucherReturn();
+ /**find an order by ticket*/
+ void orderByTicket();
+ /**find/select orders by event*/
+ void orderByEvent();
+ /**find/select orders by customer*/
+ void orderByCustomer();
+ /**find and display order by order ID*/
+ void orderByOrder();
+ /**deduct some money from a voucher (to pay outside the system)*/
+ void deductVoucher();
+
+ /**money log for voucher*/
+ void moneylogVoucher();
+ /**money log for user*/
+ void moneylogUser();
+
+ /**refresh data that we can refresh*/
+ void refreshData();
+ /**set refresh timeout*/
+ void setRefresh();
+
+ /**web request settings dialog; shows the dialog per default, just copies settings from registry to webrequest object if false*/
+ void webSettings(bool dlg=true);
+
+ /**do a backup now*/
+ void doBackup();
+
+ /**settings for backup*/
+ void backupSettings();
+
+ private:
+ //the profile associated with this session
+ QString profilekey;
+ //widgets
+ QTabWidget*tab;
+ QWidget*eventtab,*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
+ QTableView*eventtable,*usertable,*hosttable,*carttable,*ordertable;
+ QStandardItemModel*eventmodel,*usermodel,*hostmodel,*cartmodel,*ordermodel;
+ QPushButton*thishostbutton;
+ QLabel*cartcustomer,*entrancelabel;
+ QTextEdit *cartaddr,*cartcomment;
+ QComboBox*ordermode,*cartship,*entranceevent;
+ QLineEdit*entrancescan;
+ //event list
+ QAction*showoldevents;
+ //cart
+ MCustomer customer;
+ //barcode cache
+ QString lastbarcode;
+ QDateTime lastbcscan;
+ //refresh timers
+ QTimer rtimer,baktimer;
+};
+
+/**Helper dialog for changing passwords*/
+class MPasswordChange:public QDialog
+{
+ Q_OBJECT
+ public:
+ /**creates a password change dialog, if user is empty it is presumed to change own password*/
+ MPasswordChange(QWidget*parent,QString user=QString());
+
+ /**if own password: return old password*/
+ QString oldPassword();
+ /**returns new password, or empty if the two lines don't match*/
+ QString newPassword();
+ private:
+ QLineEdit *oldpwd,*newpwd1,*newpwd2;
+};
+
+/**Helper class for shopping cart: allow editing amount, but nothing else*/
+class MCartTableDelegate:public QItemDelegate
+{
+ public:
+ MCartTableDelegate(QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void setEditorData(QWidget *editor, const QModelIndex &index) const;
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const;
+};
+
+/**Helper class for Backup settings*/
+class MBackupDialog:public QDialog
+{
+ Q_OBJECT
+ public:
+ MBackupDialog(QWidget*,QString);
+
+ private slots:
+ void getpath();
+ void save();
+ private:
+ QLineEdit*lpath;
+ QSpinBox*interv,*gener;
+ QCheckBox*autob;
+ QString profilekey;
+};
+
+#endif
--- /dev/null
+//
+// C++ Implementation: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "centbox.h"
+#include "checkdlg.h"
+#include "eventedit.h"
+#include "eventsummary.h"
+#include "main.h"
+#include "misc.h"
+#include "moneylog.h"
+#include "msinterface.h"
+#include "orderwin.h"
+#include "overview.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCryptographicHash>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFile>
+#include <QFileDialog>
+#include <QFrame>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSettings>
+#include <QSpinBox>
+#include <QStandardItemModel>
+#include <QStatusBar>
+#include <QTabWidget>
+#include <QTableView>
+#include <QTextEdit>
+
+#define ORDERNONE 0
+#define ORDERALL 0xff
+#define ORDEROPEN 0xf
+#define ORDERPAY 1
+#define ORDERREFUND 2
+#define ORDERUNSENT 4
+#define ORDERRESERVE 8
+
+#define req (MSInterface::instance())
+
+MOverview::MOverview(QString pk)
+{
+ profilekey=pk;
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle("MagicSmoke: "+req->currentUser()+"@"+QSettings().value("profiles/"+pk+"/name").toString());
+ rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000);
+ rtimer.start();
+ connect(&rtimer,SIGNAL(timeout()),this,SLOT(refreshData()));
+ //check backup timing
+ int btm=QSettings().value("profiles/"+pk+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+pk+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //earliest allowed backup is 30s from now
+ if(btm<30)btm=30;
+ //start timer
+ baktimer.start(btm*1000);
+ connect(&baktimer,SIGNAL(timeout()),this,SLOT(doBackup()));
+ }
+
+ //menu
+ QMenuBar*mb=menuBar();
+ QMenu*m=mb->addMenu(tr("&Session"));
+ m->addAction(tr("&Re-Login"),this,SLOT(relogin()));
+ m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword()))
+ ->setEnabled(req->hasRight(req->RChangeMyPassword));
+ m->addSeparator();
+ m->addAction(tr("&Edit Templates..."),req,SLOT(editTemplates()));
+ m->addAction(tr("&Update Templates Now"),req,SLOT(updateTemplates()));
+ m->addSeparator();
+ m->addAction(tr("&Close Session"),this,SLOT(close()));
+
+ m=mb->addMenu(tr("&Event"));
+ m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
+ ->setEnabled(req->hasRight(req->RGetEvent));
+ m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
+ m->addSeparator();
+ showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
+ showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
+ showoldevents->setCheckable(true);
+ showoldevents->setChecked(QSettings().value("profiles/"+pk+"/showOldEvents",false).toBool());
+
+ m=mb->addMenu(tr("&Customer"));
+ m->addAction(tr("&Show all customers"),this,SLOT(customerMgmt()));
+
+ m=mb->addMenu(tr("C&art"));
+ m->addAction(tr("Add &Ticket"),this,SLOT(cartAddTicket()));
+ m->addAction(tr("Add &Voucher"),this,SLOT(cartAddVoucher()));
+ m->addAction(tr("&Remove Item"),this,SLOT(cartRemoveItem()));
+ m->addAction(tr("&Abort Shopping"),this,SLOT(initCart()));
+ m->addSeparator();
+ m->addAction(tr("&Update Shipping Options"),this,SLOT(updateShipping()));
+
+ m=mb->addMenu(tr("&Misc"));
+ m->addAction(tr("Return &ticket..."),this,SLOT(ticketReturn()));
+ m->addAction(tr("Return &voucher..."),this,SLOT(voucherReturn()));
+ m->addSeparator();
+ m->addAction(tr("Edit &Shipping Options..."),this,SLOT(editShipping()));
+ m->addSeparator();
+ m->addAction(tr("&Deduct from voucher..."),this,SLOT(deductVoucher()));
+ m->addSeparator();
+ m->addAction(tr("&Money Log for voucher..."),this,SLOT(moneylogVoucher()));
+ m->addAction(tr("Money Log for &user..."),this,SLOT(moneylogUser()));
+
+ m=mb->addMenu(tr("C&onfigure"));
+ m->addAction(tr("&Auto-Refresh settings..."),this,SLOT(setRefresh()));
+ m->addAction(tr("&Server Access settings..."),this,SLOT(webSettings()));
+
+ m=mb->addMenu(tr("&Admin"));
+ m->addAction(tr("Backup &Settings..."),this,SLOT(backupSettings()))
+ ->setEnabled(req->hasRight(req->RBackup));
+ m->addAction(tr("&Backup now..."),this,SLOT(doBackup()))
+ ->setEnabled(req->hasRight(req->RBackup));
+
+ mb->addMenu(MApplication::helpMenu());
+
+ //tabs
+ setCentralWidget(tab=new QTabWidget);
+ connect(tab,SIGNAL(currentChanged(int)),this,SLOT(tabChanged()));
+
+ //Event tab
+ tab->addTab(eventtab=new QWidget,tr("Events"));
+ QVBoxLayout*vl;QHBoxLayout*hl;
+ eventtab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(eventtable=new QTableView,10);
+ eventtable->setModel(eventmodel=new QStandardItemModel(this));
+ eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
+ eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ QPushButton*p;
+ vl->addWidget(p=new QPushButton(tr("New Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
+ p->setEnabled(req->hasRole("createevent"));
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
+ p->setEnabled(req->hasRole("geteventdata"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+ p->setEnabled(req->hasRole("createorder"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
+ p->setEnabled(req->hasRole("eventsummary"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
+ p->setEnabled(req->hasRole("cancelevent"));
+ connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
+ vl->addStretch(10);
+
+ //Shopping Cart Tab
+ tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
+ carttab->setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ QVBoxLayout*vl2;
+ hl->addLayout(vl2=new QVBoxLayout,2);
+ vl2->addWidget(carttable=new QTableView,10);
+ carttable->setModel(cartmodel=new QStandardItemModel(this));
+ carttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ carttable->setItemDelegate(new MCartTableDelegate(this));
+ QHBoxLayout*hl2;
+ vl2->addLayout(hl2=new QHBoxLayout,0);
+ hl2->addStretch(10);
+ hl2->addWidget(p=new QPushButton(tr("Add Ticket")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddTicket()));
+ hl2->addWidget(p=new QPushButton(tr("Add Voucher")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddVoucher()));
+ hl2->addWidget(p=new QPushButton(tr("Remove Item")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartRemoveItem()));
+ QFrame*frm;
+ hl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::VLine);
+ hl->addLayout(vl2=new QVBoxLayout,1);
+ vl2->addWidget(p=new QPushButton(tr("Customer:")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setCustomer()));
+ vl2->addWidget(cartcustomer=new QLabel("...\n \n \n "));
+ vl2->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Shipping Method:")),0);
+ vl2->addWidget(cartship=new QComboBox,0);
+ cartship->setEditable(false);
+ vl2->addWidget(new QLabel(tr("Delivery Address:")),0);
+ vl2->addWidget(cartaddr=new QTextEdit);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Comments:")),0);
+ vl2->addWidget(cartcomment=new QTextEdit);
+ vl2->addStretch(10);
+ vl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("Check Order")));
+ p->setEnabled(req->hasRole("checkorder"));
+ connect(p,SIGNAL(clicked()),this,SLOT(cartOrder()));
+ hl->addWidget(p=new QPushButton(tr("Clear")));
+ connect(p,SIGNAL(clicked()),this,SLOT(initCart()));
+
+ //Order List Tab
+ tab->addTab(ordertab=new QWidget,tr("Order List"));
+ ordertab->setLayout(hl=new QHBoxLayout);
+ hl->addLayout(vl=new QVBoxLayout,10);
+ vl->addWidget(ordermode=new QComboBox,0);
+ ordermode->addItem(tr("-select mode-"),ORDERNONE);
+ ordermode->addItem(tr("All Orders"),ORDERALL);
+ ordermode->addItem(tr("Open Orders"),ORDEROPEN);
+ ordermode->addItem(tr("Open Reservations"),ORDERRESERVE);
+ ordermode->addItem(tr("Outstanding Payments"),ORDERPAY);
+ ordermode->addItem(tr("Outstanding Refunds"),ORDERREFUND);
+ ordermode->addItem(tr("Undelivered Orders"),ORDERUNSENT);
+ //make sure this entry is the last one, since we use count()-1 to select it
+ ordermode->addItem(tr("-search result-"),ORDERNONE);
+ connect(ordermode,SIGNAL(currentIndexChanged(int)),this,SLOT(updateOrders()));
+ vl->addWidget(ordertable=new QTableView);
+ ordertable->setModel(ordermodel=new QStandardItemModel(this));
+ ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ connect(ordertable,SIGNAL(doubleClicked(const QModelIndex&)),this,SLOT(orderDetails()));
+ hl->addLayout(vl=new QVBoxLayout,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->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Find by Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByTicket()));
+ p->setEnabled(req->hasRole("orderbyticket"));
+ vl->addWidget(p=new QPushButton(tr("Find by Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByEvent()));
+ p->setEnabled(req->hasRole("getordersbyevents"));
+ vl->addWidget(p=new QPushButton(tr("Find by Customer...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByCustomer()));
+ p->setEnabled(req->hasRole("getorderlist"));
+ vl->addWidget(p=new QPushButton(tr("Find by Order ID...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByOrder()));
+ p->setEnabled(req->hasRole("getorder"));
+ vl->addStretch(10);
+
+ //Entrance Control Tab
+ tab->addTab(entrancetab=new QWidget,tr("Entrance"));
+ entrancetab->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(entranceevent=new QComboBox,0);
+ entranceevent->setEditable(false);
+ vl->addSpacing(30);
+ vl->addWidget(new QLabel(tr("Enter or scan Ticket-ID:")),0);
+ vl->addWidget(entrancescan=new QLineEdit,0);
+ connect(entrancescan,SIGNAL(editingFinished()),this,SLOT(entranceValidate()));
+ vl->addWidget(entrancelabel=new QLabel(" "),10);
+ entrancelabel->setAutoFillBackground(true);
+ QFont fnt=entrancelabel->font();
+ fnt.setBold(true);fnt.setPointSize(24);
+ entrancelabel->setFont(fnt);
+ entrancelabel->setAlignment(Qt::AlignCenter);
+
+ //user tab
+ tab->addTab(usertab=new QWidget,tr("Users"));
+ usertab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(usertable=new QTableView,10);
+ usertable->setModel(usermodel=new QStandardItemModel(this));
+ usertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ usertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newUser()));
+ p->setEnabled(req->hasRole("adduser"));
+ vl->addWidget(p=new QPushButton(tr("Delete User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteUser()));
+ p->setEnabled(req->hasRole("deleteuser"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Description...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserDescription()));
+ p->setEnabled(req->hasRole("setuserdescription"));
+ vl->addWidget(p=new QPushButton(tr("Hosts...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserHosts()));
+ p->setEnabled(req->hasRole("getuserhosts"));
+ vl->addWidget(p=new QPushButton(tr("Roles...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserRoles()));
+ p->setEnabled(req->hasRole("getuseracl"));
+ vl->addWidget(p=new QPushButton(tr("Set Password...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setUserPassword()));
+ p->setEnabled(req->hasRole("setpasswd"));
+ vl->addStretch(10);
+
+ //host tab
+ tab->addTab(hosttab=new QWidget,tr("Hosts"));
+ hosttab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(hosttable=new QTableView,10);
+ hosttable->setModel(hostmodel=new QStandardItemModel(this));
+ hosttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ hosttable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(thishostbutton=p=new QPushButton(tr("Add This Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(addThisHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Delete Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteHost()));
+ p->setEnabled(req->hasRole("deletehost"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Generate New Key...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(changeHostKey()));
+ p->setEnabled(req->hasRole("sethostkey"));
+ vl->addWidget(p=new QPushButton(tr("Import...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(importHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Export...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(exportHost()));
+ p->setEnabled(req->hasRole("gethostkey"));
+ vl->addStretch(10);
+
+ //status bar
+ statusBar()->setSizeGripEnabled(true);
+
+ //make sure webrequest knows its settings
+ webSettings(false);
+ //fill tables
+ if(req->hasRight(req->RGetAllEvents)){
+ updateEvents();
+ }else{
+ eventtab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(eventtab),false);
+ }
+ if(!req->hasRole("createorder")&&!req->hasRole("createsale")){
+ carttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(carttab),false);
+ }else{
+ initCart();
+ }
+ updateShipping();
+ if(req->hasRole("getorderlist")){
+ updateOrders();
+ }else{
+ ordertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(ordertab),false);
+ }
+ if(req->hasRole("getusers")){
+ updateUsers();
+ }else{
+ usertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(usertab),false);
+ }
+ if(req->hasRole("gethosts")){
+ updateHosts();
+ }else{
+ hosttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(hosttab),false);
+ }
+}
+
+void MOverview::updateEvents()
+{
+ MTGetAllEvents gae=req->queryGetAllEvents();
+ if(gae.stage()!=gae.Success){
+ qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
+ return;
+ }
+ QList<MOEvent>evl=gae.getevents();
+ eventmodel->clear();
+ eventmodel->insertColumns(0,6);
+ eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
+ QDateTime now=QDateTime::currentDateTime();
+ for(int i=0,j=0;i<evl.size();i++){
+ QDateTime stime=QDateTime::fromTime_t(evl[i].start());
+ if(stime<now && !showoldevents->isChecked())continue;
+ eventmodel->insertRow(j);
+ eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
+ eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
+ eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
+ eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
+ eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
+ eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
+ eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
+ j++;
+ }
+ eventtable->resizeColumnsToContents();
+ //in case this was called from changing the check state
+ QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showoldevents->isChecked());
+}
+
+void MOverview::closeEvent(QCloseEvent*ce)
+{
+ //make sure session is deleted
+ req->logout();
+ //actually close window
+ QMainWindow::closeEvent(ce);
+}
+
+MOverview::~MOverview()
+{
+ //free requestor
+ req->deleteLater();
+}
+
+void MOverview::relogin()
+{
+ setEnabled(false);
+ if(!req->relogin())
+ QMessageBox::warning(this,tr("Warning"),tr("I was unable to renew the login at the server."));
+ setEnabled(true);
+}
+
+void MOverview::newEvent()
+{
+ MEventEditor ed(this);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::editEvent()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventEditor ed(this,id);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::eventSummary()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventSummary ed(this,id);
+ ed.exec();
+}
+
+void MOverview::eventCancel()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MTGetEvent getev=MTGetEvent::query(id);
+ if(!getev.hasError()){
+ bool ok;
+ MOEvent ev=getev.getevent();
+ QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
+ if(!ok)return;
+ MTCancelEvent cev=MTCancelEvent::query(id,r);
+ if(!cev.hasError())
+ QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
+ else
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
+ }
+}
+
+void MOverview::updateShipping()
+{
+ cartship->clear();
+ cartship->addItem(tr("(No Shipping)"),-1);
+ MTGetAllShipping sh=MTGetAllShipping::query();
+ QList<MOShipping>ship=sh.getshipping();
+ for(int i=0;i<ship.size();i++)
+ cartship->addItem(ship[i].description(),(int)ship[i].id());
+}
+
+void MOverview::updateUsers()
+{
+ MTGetAllUsers au=req->queryGetAllUsers();
+ if(au.hasError())return;
+ QList<MOUser>usl=au.getusers();
+ usermodel->clear();
+ usermodel->insertColumns(0,2);
+ usermodel->insertRows(0,usl.size());
+ usermodel->setHorizontalHeaderLabels(QStringList()<<tr("Login Name")<<tr("Description"));
+ for(int i=0;i<usl.size();i++){
+ usermodel->setData(usermodel->index(i,0),usl[i].name().value());
+ usermodel->setData(usermodel->index(i,1),usl[i].description().value());
+ }
+ usertable->resizeColumnsToContents();
+}
+
+void MOverview::newUser()
+{
+ //get name
+ QString name;
+ while(1){
+ bool ok;
+ name=QInputDialog::getText(this,tr("New User"),tr("Please enter new user name (only letters, digits, and underscore allowed):"),QLineEdit::Normal,name,&ok);
+ if(!ok)
+ return;
+ if(QRegExp("[A-Za-z0-9_\\.,:-]+").exactMatch(name))
+ break;
+ if(QMessageBox::warning(this,tr("Error"),tr("The user name must contain only letters, digits, dots and underscores and must be at least one character long!"),QMessageBox::Retry|QMessageBox::Abort)!=QMessageBox::Retry)
+ return;
+ }
+ //get password
+ QString pwd=QInputDialog::getText(this,tr("Password"),tr("Please enter an initial password for the user:"),QLineEdit::Password);
+ //send request
+ req->queryCreateUser(name,pwd,"");
+ //update display
+ updateUsers();
+}
+
+void MOverview::deleteUser()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //make sure user wants this
+ if(QMessageBox::question(this,tr("Delete User?"),tr("Really delete user '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //get replacement
+ bool ok;
+ QStringList rplc;
+ rplc<<tr("(Nobody)","this is a username for no user, the string must contain '(' to distinguish it from the others");
+ for(int i=0;i<usermodel->rowCount();i++)
+ rplc<<usermodel->data(usermodel->index(i,0)).toString();
+ QString rp=QInputDialog::getItem(this,tr("Delete User"),tr("Select which user will inherit this users database objects:"),rplc,0,false,&ok);
+ if(!ok)return;
+ //delete
+ MTDeleteUser ret=req->queryDeleteUser(name,rp);
+ if(ret.hasError())
+ QMessageBox::warning(this,tr("Error"),tr("Cannot delete user: %1").arg(ret.errorString()));
+ updateUsers();
+}
+
+void MOverview::editUserDescription()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ QString descr=usermodel->data(usermodel->index(sel.row(),1)).toString();
+ //edit descr
+ bool ok;
+ descr=QInputDialog::getText(this,tr("Edit Description"),tr("Descriptionof user %1:").arg(name),QLineEdit::Normal,descr,&ok);
+ if(ok)
+ req->querySetUserDescription(name,descr);
+ //update
+ updateUsers();
+}
+
+void MOverview::editUserRoles()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MOUser usr(req,name);
+ MCheckList acl=usr.getRoles();
+ MCheckDialog cd(this,acl,"Edit ACL of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setRoles(cd.getCheckList());*/
+}
+
+void MOverview::editUserHosts()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MUser usr(req,name);
+ MCheckList acl=usr.getHosts();
+ MCheckDialog cd(this,acl,"Edit hosts of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setHosts(cd.getCheckList());*/
+}
+
+void MOverview::setMyPassword()
+{
+ MPasswordChange pc(this);
+ if(pc.exec()==QDialog::Accepted){
+ MTChangeMyPassword cmp=MTChangeMyPassword::query(pc.oldPassword(),pc.newPassword());
+ if(cmp.hasError())
+ QMessageBox::warning(this,tr("Warning"),tr("Error setting password: %1").arg(cmp.errorString()));
+ }
+}
+void MOverview::setUserPassword()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //get new password
+ MPasswordChange pc(this,name);
+ if(pc.exec()!=QDialog::Accepted)return;
+ QString p=pc.newPassword();
+ if(p==""){
+ QMessageBox::warning(this,tr("Warning"),tr("The password must be non-empty and both lines must match"));
+ return;
+ }
+ //...
+ MUser usr(req,name);
+ usr.changePassword(p);*/
+}
+
+void MOverview::updateHosts()
+{/*TODO
+ bool foundThis=false;
+ QString thisHost=req->hostName();
+ QList<MHost>hsl=req->getAllHosts();
+ hostmodel->clear();
+ hostmodel->insertColumns(0,2);
+ hostmodel->insertRows(0,hsl.size());
+ hostmodel->setHorizontalHeaderLabels(QStringList()<<tr("Host Name")<<tr("Host Key"));
+ for(int i=0;i<hsl.size();i++){
+ hostmodel->setData(hostmodel->index(i,0),hsl[i].hostId());
+ hostmodel->setData(hostmodel->index(i,1),hsl[i].hostKey());
+ if(thisHost==hsl[i].hostId())
+ foundThis=true;
+ }
+ hosttable->resizeColumnsToContents();
+ thishostbutton->setEnabled(!foundThis && req->hasRole("addhost"));*/
+}
+
+void MOverview::newHost()
+{/*TODO
+ //get Host Name
+ QString hname;
+ do{
+ bool ok;
+ hname=QInputDialog::getText(this,tr("Create New Host"),tr("Please enter a host name:"),QLineEdit::Normal,hname,&ok);
+ if(!ok)return;
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname))continue;
+ }while(false);
+ //create it
+ MHost hst(req,hname);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The key of this new host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.create();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::addThisHost()
+{/*TODO
+ MHost hst(req,req->hostName(),QSettings().value("hostkey").toString());
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::deleteHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Delete this Host?"),tr("Really delete host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //delete it
+ MHost(req,name).deleteHost();
+ updateHosts();*/
+}
+
+void MOverview::changeHostKey()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Change Host Key?"),tr("Really change the key of host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //change it
+ MHost hst(req,name);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The new key of this host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.save();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::importHost()
+{/*TODO
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptOpen);
+ fdlg.setFileMode(QFileDialog::ExistingFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::ReadOnly)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ //read content (max: 10k to limit potential damage)
+ QStringList fc=QString::fromAscii(fd.read(10240)).split("\n",QString::SkipEmptyParts);
+ fd.close();
+ //check content
+ if(fc.size()<3){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ if(fc[0].trimmed()!="MagicSmokeHostKey"){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ QString hname=fc[1].trimmed();
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name."));
+ return;
+ }
+ QString key=fc[2].trimmed();
+ if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key."));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ if(chk!=fc[3].trimmed()){
+ QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file."));
+ return;
+ }
+ //save
+ MHost hst(req,hname,key);
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::exportHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ QString key=hostmodel->data(hostmodel->index(sel.row(),1)).toString();
+ if(name[0]=='_' || key==""){
+ QMessageBox::warning(this,tr("Warning"),tr("This host cannot be exported."));
+ return;
+ }
+ //save
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptSave);
+ fdlg.setFileMode(QFileDialog::AnyFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ QString out="MagicSmokeHostKey\n"+name+"\n"+key+"\n"+chk;
+ fd.write(out.toAscii());
+ fd.close();*/
+}
+
+
+void MOverview::initCart()
+{
+ //clear cart
+ cartmodel->clear();
+ cartmodel->setHorizontalHeaderLabels(QStringList()<<tr("Amount")<<tr("Title")<<tr("Start Time"));
+ //clear customer
+ customer=MCustomer();
+ cartcustomer->setText("");
+ //clear address/comment
+ cartaddr->setPlainText("");
+ cartcomment->setPlainText("");
+ //clear shipping
+ cartship->setCurrentIndex(0);
+}
+
+void MOverview::setCustomer()
+{/*TODO
+ MCustomerListDialog mcl(req,this,true,customer.customerID());
+ if(mcl.exec()!=QDialog::Accepted)return;
+ customer=mcl.getCustomer();
+ cartcustomer->setText(customer.getNameAddress());*/
+}
+
+static const int CART_TICKET=1;
+static const int CART_VOUCHER=2;
+
+static const int CART_IDROLE=Qt::UserRole;//ticket id
+static const int CART_PRICEROLE=Qt::UserRole;//voucher price
+static const int CART_VALUEROLE=Qt::UserRole+1;//voucher value
+static const int CART_TYPEROLE=Qt::UserRole+2;//which is it? ticket or voucher?
+
+void MOverview::cartAddTicket()
+{
+ //create ticket selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Event to order Ticket"));
+ QTableView*tv;
+ QHBoxLayout*hl;
+ QVBoxLayout*vl;
+ dlg.setLayout(vl=new QVBoxLayout);
+ vl->addWidget(tv=new QTableView,10);
+ tv->setModel(eventmodel);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->resizeColumnsToContents();
+ vl->addSpacing(15);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Select")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ connect(tv,SIGNAL(doubleClicked(const QModelIndex&)),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ QModelIndex idx=tv->currentIndex();
+ if(!idx.isValid())return;
+ int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt();
+ if(id<0)return;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(idx.row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(idx.row(),0)));
+ carttable->resizeColumnsToContents();
+ }
+}
+
+void MOverview::eventOrderTicket()
+{
+ //get selected event
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ //activate order tab
+ tab->setCurrentWidget(carttab);
+ //insert event into table
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(ilst[0].row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(ilst[0].row(),0)));
+ carttable->resizeColumnsToContents();
+}
+
+void MOverview::cartAddVoucher()
+{/*TODO
+ //create voucher selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Voucher"));
+ QComboBox*cp,*cv;
+ QHBoxLayout*hl;
+ QGridLayout*gl;
+ QStandardItemModel mdl;
+ QRegExpValidator regv(priceRegExp(),this);
+ QList<int>prc=req->getVoucherPrices();
+ mdl.insertRows(0,prc.size());
+ mdl.insertColumns(0,1);
+ for(int i=0;i<prc.size();i++)mdl.setData(mdl.index(i,0),cent2str(prc[i]));
+ dlg.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Select voucher price and value:")),0,0,1,2);
+ if(req->hasRole("_anypricevoucher")){
+ gl->addWidget(new QLabel(tr("Price:")),1,0);
+ gl->addWidget(cp=new QComboBox,1,1);
+ cp->setModel(&mdl);
+ cp->setEditable(true);
+ cp->setValidator(®v);
+ }else cp=0;
+ gl->addWidget(new QLabel(tr("Value:")),2,0);
+ gl->addWidget(cv=new QComboBox,2,1);
+ cv->setModel(&mdl);
+ cv->setEditable(req->hasRole("_anyvoucher"));
+ cv->setValidator(®v);
+ gl->setRowMinimumHeight(3,15);
+ gl->setColumnStretch(0,0);
+ gl->setColumnStretch(1,1);
+ gl->setRowStretch(3,1);
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ int price,value;
+ value=str2cent(cv->currentText());
+ if(req->hasRole("_anypricevoucher") && cp)
+ price=str2cent(cp->currentText());
+ else
+ price=value;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),price,CART_PRICEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),value,CART_VALUEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_VOUCHER,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (price: %1, value %2)").arg(cent2str(price)).arg(cent2str(value)));
+ carttable->resizeColumnsToContents();
+ }*/
+}
+
+void MOverview::cartRemoveItem()
+{
+ //get selection
+ QModelIndex idx=carttable->currentIndex();
+ if(!idx.isValid())return;
+ //remove row
+ cartmodel->removeRow(idx.row());
+}
+
+void MOverview::cartOrder()
+{
+ //sanity checks
+ if(cartmodel->rowCount()<1){
+ QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it."));
+ return;
+ }
+ if(!customer.isValid()){
+ QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!"));
+ return;
+ }
+ ///////////////
+ //create order
+ QDomDocument doc;
+ QDomElement root=doc.createElement("Order");
+ root.setAttribute("customer",customer.id());
+ //is there a delivery address
+ QString s=cartaddr->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement da=doc.createElement("DeliveryAddress");
+ da.appendChild(doc.createTextNode(s));
+ root.appendChild(da);
+ }
+ //is there a comment?
+ s=cartcomment->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement cc=doc.createElement("Comment");
+ cc.appendChild(doc.createTextNode(s));
+ root.appendChild(cc);
+ }
+ //scan tickets & scan vouchers
+ for(int i=0;i<cartmodel->rowCount();i++){
+ QModelIndex idx=cartmodel->index(i,0);
+ int tp=cartmodel->data(idx,CART_TYPEROLE).toInt();
+ if(tp==CART_TICKET){
+ int amt=cartmodel->data(idx).toInt();
+ int evid=cartmodel->data(idx,CART_IDROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Ticket");
+ tc.setAttribute("event",evid);
+ root.appendChild(tc);
+ }
+ }else
+ if(tp==CART_VOUCHER){
+ int amt=cartmodel->data(idx).toInt();
+ int price=cartmodel->data(idx,CART_PRICEROLE).toInt();
+ int value=cartmodel->data(idx,CART_VALUEROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Voucher");
+ tc.setAttribute("price",price);
+ tc.setAttribute("value",value);
+ root.appendChild(tc);
+ }
+
+ }
+ }
+ //set shipping info
+ if(cartship->currentIndex()>0){
+ QDomElement si=doc.createElement("Shipping");
+ si.setAttribute("type",cartship->itemData(cartship->currentIndex()).toInt());
+ root.appendChild(si);
+ }
+ //finalize
+ doc.appendChild(root);
+ //send
+ /*TODO
+ if(req->request("checkorder",doc.toByteArray())==false){
+ QMessageBox::warning(this,tr("Error"),tr("The request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Error"),tr("A problem occurred during the order: %1").arg(qApp->translate("php::",req->responseBody())));
+ return;
+ }
+ //parse result
+ QDomDocument rdoc;
+ rdoc.setContent(req->responseBody());
+ //display order and give user chance to actually order it
+ MOrderWindow *ow=new MOrderWindow(this,req,MOrder(req,rdoc.documentElement()));
+ ow->show();
+ //empty the cart
+ initCart();*/
+}
+
+void MOverview::customerMgmt()
+{/*TODO
+ MCustomerListDialog mcl(req,this);
+ mcl.exec();*/
+}
+
+void MOverview::editShipping()
+{/*TODO
+ MShippingEditor se(req,this);
+ se.exec();
+ updateShipping();*/
+}
+
+void MOverview::tabChanged()
+{/*TODO
+ QWidget*w=tab->currentWidget();
+ if(w==entrancetab){
+ //fill combobox from eventmodel
+ int ci=entranceevent->currentIndex();
+ int cev=-1;
+ if(ci>=0)cev=entranceevent->itemData(ci).toInt();
+ ci=-1;
+ entranceevent->clear();
+ for(int i=0;i<eventmodel->rowCount();i++){
+ QString ev=eventmodel->data(eventmodel->index(i,0)).toString()+" "+
+ eventmodel->data(eventmodel->index(i,1)).toString();
+ int eid=eventmodel->data(eventmodel->index(i,0),Qt::UserRole).toInt();
+ entranceevent->addItem(ev,eid);
+ if(eid==cev)ci=i;
+ }
+ if(ci>=0)entranceevent->setCurrentIndex(ci);
+ //set focus on scanner
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");
+ }*/
+}
+
+void MOverview::entranceValidate()
+{/*TODO
+ //get event ID
+ int ci=entranceevent->currentIndex();
+ if(ci<0)return;
+ int cev=entranceevent->itemData(ci).toInt();
+ //check content
+ QString tid=entrancescan->text().trimmed();
+ entrancescan->setText("");
+ //avoid spurious events
+ if(tid=="")return;
+ //avoid double scans
+ QDateTime now=QDateTime::currentDateTime();
+ if(tid==lastbarcode && lastbcscan.addSecs(20)>=now)
+ return;
+ lastbarcode=tid;
+ lastbcscan=now;
+ //reset display
+ QPalette pal=entrancelabel->palette();
+ QPalette::ColorRole rl=QPalette::Window;
+ pal.setColor(rl,Qt::lightGray);
+ entrancelabel->setPalette(pal);
+ entrancelabel->setText(tr("searching...","entrance control"));
+ //ask the server
+ MTicket tick(req,tid);
+ //decide what to do
+ if(!tick.isValid()){
+ entrancelabel->setText(tr("Ticket \"%1\" Not Valid").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.eventID()!=cev){
+ entrancelabel->setText(tr("Ticket \"%1\" is not for this event.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.status()==MTicket::Used){
+ entrancelabel->setText(tr("Ticket \"%1\" has already been used").arg(tid));
+ pal.setColor(rl,Qt::magenta);
+ }else
+ if(tick.status()!=MTicket::Bought){
+ entrancelabel->setText(tr("Ticket \"%1\" has not been bought.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.paymentStatus()==MTicket::PSOk){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedRefund){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok; the Order has a refund").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedPayment){
+ entrancelabel->setText(tr("Ticket \"%1\" is not paid for!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else{
+ entrancelabel->setText(tr("Ticket \"%1\" cannot be accepted, please check the order!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }
+
+ entrancelabel->setPalette(pal);
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");*/
+}
+
+//helper: finds out whether an order should be printed.
+static inline bool candoUpdateOrders(int omode,const MOrder&ord)
+{
+ if(omode==ORDERALL)return true;
+ if((omode&ORDERPAY)!=0 && ord.needsPayment())return true;
+ if((omode&ORDERREFUND)!=0 && ord.needsRefund())return true;
+ if((omode&ORDERUNSENT)!=0 && !ord.isSent())return true;
+ if((omode&ORDERRESERVE)!=0 && ord.isReservation())return true;
+ return false;
+}
+
+void MOverview::updateOrders()
+{/*TODO
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ int omode=ordermode->itemData(ordermode->currentIndex()).toInt();
+ if(omode==ORDERNONE)return;
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ if(!candoUpdateOrders(omode,orders[i]))continue;
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ int cid=orders[i].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ cl++;
+ }
+ ordertable->resizeColumnsToContents();*/
+}
+
+void MOverview::orderDetails()
+{/*TODO
+ //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::orderByTicket()
+{/*TODO
+ //get selected order
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Enter Ticket"),tr("Please enter the ID of one of the tickets of the order you seek:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ //request it
+ if(!req->request("orderbyticket",tid.toUtf8())){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to query server."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),qApp->translate("php::",req->responseBody()));
+ return;
+ }
+ int id=req->responseBody().trimmed().toInt(&ok);
+ if(!ok || id<0){
+ QMessageBox::warning(this,tr("Warning"),tr("Server returned an invalid order ID."));
+ return;
+ }
+ //open order window
+ MOrderWindow *om=new MOrderWindow(this,req,MOrder(req,id));
+ om->setAttribute(Qt::WA_DeleteOnClose);
+ om->show();*/
+}
+
+void MOverview::orderByEvent()
+{/*TODO
+ //display selection dialog
+ QDialog d(this);
+ d.setWindowTitle(tr("Select Event"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ QTableView*tv;
+ vl->addWidget(tv=new QTableView,10);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->setModel(eventmodel);
+ tv->resizeColumnsToContents();
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ //wait for user
+ if(d.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ QModelIndexList ilst=tv->selectionModel()->selectedIndexes();
+ if(ilst.size()<1){
+ qDebug("nothing selected");
+ return;
+ }
+ //get events
+ QList<int>eventids;
+ for(int i=0;i<ilst.size();i++){
+ int eid=eventmodel->data(eventmodel->index(ilst[i].row(),0),Qt::UserRole).toInt();
+ if(!eventids.contains(eid))eventids.append(eid);
+ }
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getOrdersByEvents(eventids);
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ for(int cl=0;cl<orders.size();cl++){
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[cl].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[cl].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[cl].amountPaidString());
+ int cid=orders[cl].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByCustomer()
+{/*TODO
+ //display selection dialog
+ MCustomerListDialog mcl(req,this,true);
+ //wait for user
+ if(mcl.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ MCustomer cst=mcl.getCustomer();
+ if(!cst.isValid()){
+ qDebug("nothing selected");
+ return;
+ }
+ qint64 custid=cst.customerID();
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ //filter
+ if(orders[i].customerID()!=custid)continue;
+ //put into table
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ ordermodel->setData(ordermodel->index(cl,3),cst.name());
+ //count up
+ cl++;
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByOrder()
+{/*TODO
+ //ask for OrderID
+ bool ok;
+ int oid=QInputDialog::getInteger(this,tr("Enter Order ID"),tr("Please enter the ID of the order you want to display:"),0,0,2147483647,1,&ok);
+ if(!ok)return;
+ //display
+ MOrder ord(req,oid);
+ if(!ord.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This order does not exist."));
+ return;
+ }
+ MOrderWindow *ow=new MOrderWindow(this,req,ord);
+ ow->show();*/
+}
+
+void MOverview::ticketReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Ticket"),tr("Please enter the ticket ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MTicket tick(req,tid);
+ if(!tick.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid ticket."));
+ return;
+ }
+ //check state
+ if(tick.status()!=MTicket::Bought && tick.status()!=MTicket::Reserved){
+ QMessageBox::warning(this,tr("Warning"),tr("This ticket cannot be returned, it has already been used or is in the wrong state."));
+ return;
+ }
+ //submit
+ QString r=tick.ticketReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::voucherReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Voucher"),tr("Please enter the voucher ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MVoucher vouc(req,tid);
+ if(!vouc.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid voucher."));
+ return;
+ }
+ //check state
+ if(vouc.isUsed()){
+ QMessageBox::warning(this,tr("Warning"),tr("This voucher cannot be returned, it has already been used."));
+ return;
+ }
+ //submit
+ QString r=vouc.voucherReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::deductVoucher()
+{/*TODO
+ //get voucher ID and amount
+ QDialog d;
+ d.setWindowTitle(tr("Deduct from Voucher"));
+ QGridLayout *gl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Using a voucher to pay outside the system.")),0,0,1,2);
+
+ QLineEdit*vid;
+ MCentSpinBox*cent;
+ gl->addWidget(new QLabel(tr("Amount to deduct:")),1,0);
+ gl->addWidget(cent=new MCentSpinBox,1,1);
+ gl->addWidget(new QLabel(tr("Voucher ID:")),2,0);
+ gl->addWidget(vid=new QLineEdit,2,1);
+
+ gl->setRowMinimumHeight(3,15);
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ if(vid->text().trimmed()=="" || cent->value()<=0)return;
+ //query server
+ QByteArray r=vid->text().trimmed().toAscii()+"\n"+QString::number(cent->value()).toAscii();
+ if(!req->request("usevoucheroutside",r)){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ QStringList sl=QString::fromAscii(req->responseBody().trimmed()).split("\n");
+ int tak=-1,rem=-1;
+ if(sl.size()>0)tak=sl[0].trimmed().toInt();
+ if(sl.size()>1)rem=sl[1].trimmed().toInt();
+ QMessageBox::information(this,tr("Deducted from Voucher"),tr("Value taken from voucher: %1\nValue remaining on voucher: %2").arg(cent2str(tak)).arg(cent2str(rem)));*/
+}
+
+void MOverview::refreshData()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ if(set.value("refreshEvents",false).toBool() && req->hasRole("geteventlist"))
+ updateEvents();
+ if(set.value("refreshUsers",false).toBool() && req->hasRole("getusers"))
+ updateUsers();
+ if(set.value("refreshHosts",false).toBool() && req->hasRole("gethosts"))
+ updateHosts();
+ if(set.value("refreshShipping",false).toBool() && req->hasRole("getshipping"))
+ updateShipping();
+}
+
+void MOverview::setRefresh()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //dialog
+ QDialog d;
+ d.setWindowTitle(tr("Refresh Settings"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Refresh Rate (minutes):")),1);
+ QSpinBox*rate;
+ hl->addWidget(rate=new QSpinBox,0);
+ rate->setRange(1,999);
+ rate->setValue(set.value("refresh",300).toInt()/60);
+ QCheckBox *rev,*rus,*rho,*rsh;
+ vl->addWidget(rev=new QCheckBox(tr("refresh &event list")));
+ rev->setChecked(set.value("refreshEvents",false).toBool());
+ vl->addWidget(rus=new QCheckBox(tr("refresh &user list")));
+ rus->setChecked(set.value("refreshUsers",false).toBool());
+ vl->addWidget(rho=new QCheckBox(tr("refresh &host list")));
+ rho->setChecked(set.value("refreshHosts",false).toBool());
+ vl->addWidget(rsh=new QCheckBox(tr("refresh &shipping list")));
+ rho->setChecked(set.value("refreshShipping",false).toBool());
+ vl->addSpacing(15);
+ vl->addStretch(10);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ set.setValue("refreshEvents",rev->isChecked());
+ set.setValue("refreshUsers",rus->isChecked());
+ set.setValue("refreshHosts",rho->isChecked());
+ set.setValue("refreshShipping",rsh->isChecked());
+ set.setValue("refresh",rate->value()*60);
+ //reset timer
+ rtimer.stop();
+ rtimer.setInterval(rate->value()*60000);
+ rtimer.start();
+}
+
+void MOverview::webSettings(bool showdlg)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //get settings
+ MSInterface::LogLevel lvl=MSInterface::LogLevel(set.value("webloglevel", MSInterface::LogOnError).toInt());
+ int timeout=set.value("webtimeout",30).toInt();
+ //dialog
+ if(showdlg){
+ QDialog d;
+ d.setWindowTitle(tr("Server Access Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Request Timeout (seconds):")),0,0);
+ QSpinBox*tmout;
+ gl->addWidget(tmout=new QSpinBox,0,1);
+ tmout->setRange(10,999);
+ tmout->setValue(timeout);
+ QComboBox *log;
+ gl->addWidget(new QLabel(tr("Log Level:")),1,0);
+ gl->addWidget(log=new QComboBox,1,1);
+ log->addItem(tr("Minimal Logging"),MSInterface::LogMinimal);
+ log->addItem(tr("Log Details on Error"),MSInterface::LogOnError);
+ log->addItem(tr("Always Log Details"),MSInterface::LogDetailed);
+ switch(lvl){
+ case MSInterface::LogMinimal:log->setCurrentIndex(0);break;
+ case MSInterface::LogOnError:log->setCurrentIndex(1);break;
+ case MSInterface::LogDetailed:log->setCurrentIndex(2);break;
+ }
+ gl->setRowMinimumHeight(2,15);
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ lvl=MSInterface::LogLevel(log->itemData(log->currentIndex()).toInt());
+ timeout=tmout->value();
+ set.setValue("webloglevel",lvl);
+ set.setValue("webtimeout",timeout);
+ }
+ //reset webrequest
+ req->setLogLevel(lvl);
+ req->setWebTimeout(timeout*1000);
+}
+
+void MOverview::doBackup()
+{
+ baktimer.stop();
+ //sanity check
+ if(!req->hasRight(req->RBackup))return;
+ //get settings
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ //get data
+ MTBackup bc;
+ bc=MTBackup::query();
+ if(bc.stage()!=bc.Success){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup failed with error (%2): %1").arg(bc.errorString()).arg(bc.errorType()));
+ return;
+ }
+ if(bc.getbackup().isNull()||bc.getbackup().value().isEmpty()){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup returned empty."));
+ return;
+ }
+ //rotate files
+ QFile(path+"."+QString::number(gens)).remove();
+ for(int i=gens-1;i>=0;i--){
+ if(i)
+ QFile(path+"."+QString::number(i)).rename(path+"."+QString::number(i+1));
+ else
+ QFile(path).rename(path+".1");
+ }
+ //store new data
+ QFile fd(path);
+ if(fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ fd.write(bc.getbackup().value().toAscii());
+ fd.close();
+ set.setValue("backuptime",QDateTime::currentDateTime().toTime_t());
+ QMessageBox::information(this,tr("Backup"),tr("The backup was successful."));
+ int tm=set.value("backupinterval",0).toInt()*86400000;
+ if(tm)baktimer.start(tm);
+ }else
+ QMessageBox::warning(this,tr("Warning"),tr("Cannot create backup file."));
+}
+
+void MOverview::backupSettings()
+{
+ //show dialog
+ MBackupDialog d(this,profilekey);
+ d.exec();
+ //reset timer
+ int btm=QSettings().value("profiles/"+profilekey+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+profilekey+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //start timer
+ baktimer.start(btm*1000);
+ }
+}
+
+void MOverview::moneylogVoucher()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("Voucher ID"),tr("Please enter voucher ID to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"voucher\n"+vid).exec();*/
+}
+
+void MOverview::moneylogUser()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("User"),tr("Please enter login name of user to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"user\n"+vid).exec();*/
+}
+
+
+/**********************************************/
+
+MBackupDialog::MBackupDialog(QWidget*par,QString pk)
+ :QDialog(par),profilekey(pk)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ int tm=set.value("backupinterval",0).toInt();
+ //dialog
+ setWindowTitle(tr("Backup Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ setLayout(gl=new QGridLayout);
+ QPushButton*p;
+ gl->addWidget(new QLabel(tr("Backup File:")),0,0);
+ gl->addWidget(lpath=new QLineEdit(path),0,1);
+ gl->addWidget(p=new QPushButton(tr("...")),0,2);
+ connect(p,SIGNAL(clicked()),this,SLOT(getpath()));
+
+ gl->addWidget(new QLabel(tr("Generations to keep:")),1,0);
+ gl->addWidget(gener=new QSpinBox,1,1,1,2);
+ gener->setRange(1,16);
+ gener->setValue(gens);
+
+ gl->addWidget(new QLabel(tr("Automatic Backup:")),2,0);
+ gl->addWidget(autob=new QCheckBox,2,1,1,2);
+ autob->setChecked(tm>0);
+
+ gl->addWidget(new QLabel(tr("Interval in days:")),3,0);
+ gl->addWidget(interv=new QSpinBox,3,1,1,2);
+ interv->setRange(1,24);
+ interv->setValue(tm>0?tm:1);
+
+ gl->setRowMinimumHeight(4,15);
+ gl->addLayout(hl=new QHBoxLayout,5,0,1,3);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ connect(p,SIGNAL(clicked()),this,SLOT(save()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+void MBackupDialog::getpath()
+{
+ QString path=QFileDialog::getSaveFileName(this,tr("Backup File"),lpath->text());
+ if(path!="")lpath->setText(path);
+}
+
+void MBackupDialog::save()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ set.setValue("backupfile",lpath->text());
+ set.setValue("backupgenerations",gener->value());
+ set.setValue("backupinterval",autob->isChecked()?interv->value():0);
+}
+/**********************************************/
+
+MPasswordChange::MPasswordChange(QWidget*par,QString user)
+ :QDialog(par)
+{
+ oldpwd=newpwd1=newpwd2=0;
+ if(user=="")
+ setWindowTitle(tr("Change my password"));
+ else
+ setWindowTitle(tr("Reset password of user \"%1\"").arg(user));
+ QGridLayout*gl;
+ setLayout(gl=new QGridLayout);
+ if(user==""){
+ gl->addWidget(new QLabel(tr("Old Password:")),0,0);
+ gl->addWidget(oldpwd=new QLineEdit,0,1);
+ oldpwd->setEchoMode(QLineEdit::Password);
+ }
+ gl->addWidget(new QLabel(tr("New Password:")),1,0);
+ gl->addWidget(newpwd1=new QLineEdit,1,1);
+ newpwd1->setEchoMode(QLineEdit::Password);
+ gl->addWidget(new QLabel(tr("Repeat Password:")),2,0);
+ gl->addWidget(newpwd2=new QLineEdit,2,1);
+ newpwd2->setEchoMode(QLineEdit::Password);
+
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Set Password")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+QString MPasswordChange::oldPassword()
+{
+ if(oldpwd)return oldpwd->text();
+ return "";
+}
+
+QString MPasswordChange::newPassword()
+{
+ if(newpwd1==0 || newpwd2==0)return "";
+ if(newpwd1->text()!=newpwd2->text())return "";
+ return newpwd1->text();
+}
+
+
+/********************************************************************************/
+
+MCartTableDelegate::MCartTableDelegate(QObject*p)
+ :QItemDelegate(p)
+{
+}
+
+QWidget *MCartTableDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &/* option */,
+ const QModelIndex & index ) const
+{
+ //base class
+ if(index.column()!=0)return 0;
+
+ QSpinBox *editor = new QSpinBox(parent);
+ editor->setRange(1,1000);
+ editor->installEventFilter(const_cast<MCartTableDelegate*>(this));
+ return editor;
+}
+
+void MCartTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0)
+ ((QSpinBox*)editor)->setValue(index.model()->data(index).toInt());
+}
+
+void MCartTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0){
+ int newval=((QSpinBox*)editor)->value();
+ model->setData(index,newval);
+ }
+}
--- /dev/null
+//
+// C++ Interface: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_OVERVIEW_H
+#define MAGICSMOKE_OVERVIEW_H
+
+#include <QDateTime>
+#include <QDialog>
+#include <QItemDelegate>
+#include <QMainWindow>
+#include <QTimer>
+
+#include "customer.h"
+
+class QAction;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class QStandardItemModel;
+class QTabWidget;
+class QTableView;
+
+class MSInterface;
+
+/**Main Overview Window*/
+class MOverview:public QMainWindow
+{
+ Q_OBJECT
+ public:
+ /**construct the window with web-request/session handler and QSettings-key for current profile*/
+ MOverview(QString);
+ ~MOverview();
+ protected:
+ /**handle closing the window: close the session too*/
+ void closeEvent(QCloseEvent*);
+ private slots:
+ /**try to log in again*/
+ void relogin();
+
+ /**create a new event*/
+ void newEvent();
+ /**edit existing event*/
+ void editEvent();
+ /**update list of events*/
+ void updateEvents();
+ /**order ticket from event tab*/
+ void eventOrderTicket();
+ /**open event summary*/
+ void eventSummary();
+ /**cancel the event*/
+ void eventCancel();
+
+ /**update shipping info*/
+ void updateShipping();
+
+ /**get all orders, update list*/
+ void updateOrders();
+ /**open order detail window*/
+ void orderDetails();
+
+ /**update list of users*/
+ void updateUsers();
+ /**create new user*/
+ void newUser();
+ /**delete selected user*/
+ void deleteUser();
+ /**set users description*/
+ void editUserDescription();
+ /**set users roles*/
+ void editUserRoles();
+ /**set users hosts*/
+ void editUserHosts();
+ /**set my own password*/
+ void setMyPassword();
+ /**set a users password*/
+ void setUserPassword();
+
+ /**update list of hosts*/
+ void updateHosts();
+ /**create new host*/
+ void newHost();
+ /**create a database entry for this host*/
+ void addThisHost();
+ /**delete a host*/
+ void deleteHost();
+ /**generate a new key*/
+ void changeHostKey();
+ /**import host from file*/
+ void importHost();
+ /**export host to file*/
+ void exportHost();
+
+ /**decide what customer to use*/
+ void setCustomer();
+ /**initialize cart tab*/
+ void initCart();
+ /**add a ticket to the cart*/
+ void cartAddTicket();
+ /**add a voucher to the cart*/
+ void cartAddVoucher();
+ /**remove item from the cart*/
+ void cartRemoveItem();
+ /**check the order on the server*/
+ void cartOrder();
+
+ /**manage customers*/
+ void customerMgmt();
+
+ /**edit shipping options*/
+ void editShipping();
+
+ /**generic check which tab is active*/
+ void tabChanged();
+
+ /**react on entry in Entrance tab*/
+ void entranceValidate();
+
+ /**return a ticket*/
+ void ticketReturn();
+ /**return a voucher*/
+ void voucherReturn();
+ /**find an order by ticket*/
+ void orderByTicket();
+ /**find/select orders by event*/
+ void orderByEvent();
+ /**find/select orders by customer*/
+ void orderByCustomer();
+ /**find and display order by order ID*/
+ void orderByOrder();
+ /**deduct some money from a voucher (to pay outside the system)*/
+ void deductVoucher();
+
+ /**money log for voucher*/
+ void moneylogVoucher();
+ /**money log for user*/
+ void moneylogUser();
+
+ /**refresh data that we can refresh*/
+ void refreshData();
+ /**set refresh timeout*/
+ void setRefresh();
+
+ /**web request settings dialog; shows the dialog per default, just copies settings from registry to webrequest object if false*/
+ void webSettings(bool dlg=true);
+
+ /**do a backup now*/
+ void doBackup();
+
+ /**settings for backup*/
+ void backupSettings();
+
+ private:
+ //the profile associated with this session
+ QString profilekey;
+ //widgets
+ QTabWidget*tab;
+ QWidget*eventtab,*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
+ QTableView*eventtable,*usertable,*hosttable,*carttable,*ordertable;
+ QStandardItemModel*eventmodel,*usermodel,*hostmodel,*cartmodel,*ordermodel;
+ QPushButton*thishostbutton;
+ QLabel*cartcustomer,*entrancelabel;
+ QTextEdit *cartaddr,*cartcomment;
+ QComboBox*ordermode,*cartship,*entranceevent;
+ QLineEdit*entrancescan;
+ //event list
+ QAction*showoldevents;
+ //cart
+ MCustomer customer;
+ //barcode cache
+ QString lastbarcode;
+ QDateTime lastbcscan;
+ //refresh timers
+ QTimer rtimer,baktimer;
+};
+
+/**Helper dialog for changing passwords*/
+class MPasswordChange:public QDialog
+{
+ Q_OBJECT
+ public:
+ /**creates a password change dialog, if user is empty it is presumed to change own password*/
+ MPasswordChange(QWidget*parent,QString user=QString());
+
+ /**if own password: return old password*/
+ QString oldPassword();
+ /**returns new password, or empty if the two lines don't match*/
+ QString newPassword();
+ private:
+ QLineEdit *oldpwd,*newpwd1,*newpwd2;
+};
+
+/**Helper class for shopping cart: allow editing amount, but nothing else*/
+class MCartTableDelegate:public QItemDelegate
+{
+ public:
+ MCartTableDelegate(QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void setEditorData(QWidget *editor, const QModelIndex &index) const;
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const;
+};
+
+/**Helper class for Backup settings*/
+class MBackupDialog:public QDialog
+{
+ Q_OBJECT
+ public:
+ MBackupDialog(QWidget*,QString);
+
+ private slots:
+ void getpath();
+ void save();
+ private:
+ QLineEdit*lpath;
+ QSpinBox*interv,*gener;
+ QCheckBox*autob;
+ QString profilekey;
+};
+
+#endif
--- /dev/null
+//
+// C++ Implementation: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "centbox.h"
+#include "checkdlg.h"
+#include "eventedit.h"
+#include "eventsummary.h"
+#include "main.h"
+#include "misc.h"
+#include "moneylog.h"
+#include "msinterface.h"
+#include "orderwin.h"
+#include "overview.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCryptographicHash>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFile>
+#include <QFileDialog>
+#include <QFrame>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSettings>
+#include <QSpinBox>
+#include <QStandardItemModel>
+#include <QStatusBar>
+#include <QTabWidget>
+#include <QTableView>
+#include <QTextEdit>
+
+#define ORDERNONE 0
+#define ORDERALL 0xff
+#define ORDEROPEN 0xf
+#define ORDERPAY 1
+#define ORDERREFUND 2
+#define ORDERUNSENT 4
+#define ORDERRESERVE 8
+
+#define req (MSInterface::instance())
+
+MOverview::MOverview(QString pk)
+{
+ profilekey=pk;
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle("MagicSmoke: "+req->currentUser()+"@"+QSettings().value("profiles/"+pk+"/name").toString());
+ rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000);
+ rtimer.start();
+ connect(&rtimer,SIGNAL(timeout()),this,SLOT(refreshData()));
+ //check backup timing
+ int btm=QSettings().value("profiles/"+pk+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+pk+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //earliest allowed backup is 30s from now
+ if(btm<30)btm=30;
+ //start timer
+ baktimer.start(btm*1000);
+ connect(&baktimer,SIGNAL(timeout()),this,SLOT(doBackup()));
+ }
+
+ //menu
+ QMenuBar*mb=menuBar();
+ QMenu*m=mb->addMenu(tr("&Session"));
+ m->addAction(tr("&Re-Login"),this,SLOT(relogin()));
+ m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword()))
+ ->setEnabled(req->hasRight(req->RChangeMyPassword));
+ m->addSeparator();
+ m->addAction(tr("&Edit Templates..."),req,SLOT(editTemplates()));
+ m->addAction(tr("&Update Templates Now"),req,SLOT(updateTemplates()));
+ m->addSeparator();
+ m->addAction(tr("&Close Session"),this,SLOT(close()));
+
+ m=mb->addMenu(tr("&Event"));
+ m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
+ ->setEnabled(req->hasRight(req->RGetEvent));
+ m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
+ m->addSeparator();
+ showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
+ showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
+ showoldevents->setCheckable(true);
+ showoldevents->setChecked(QSettings().value("profiles/"+pk+"/showOldEvents",false).toBool());
+
+ m=mb->addMenu(tr("&Customer"));
+ m->addAction(tr("&Show all customers"),this,SLOT(customerMgmt()));
+
+ m=mb->addMenu(tr("C&art"));
+ m->addAction(tr("Add &Ticket"),this,SLOT(cartAddTicket()));
+ m->addAction(tr("Add &Voucher"),this,SLOT(cartAddVoucher()));
+ m->addAction(tr("&Remove Item"),this,SLOT(cartRemoveItem()));
+ m->addAction(tr("&Abort Shopping"),this,SLOT(initCart()));
+ m->addSeparator();
+ m->addAction(tr("&Update Shipping Options"),this,SLOT(updateShipping()));
+
+ m=mb->addMenu(tr("&Misc"));
+ m->addAction(tr("Return &ticket..."),this,SLOT(ticketReturn()));
+ m->addAction(tr("Return &voucher..."),this,SLOT(voucherReturn()));
+ m->addSeparator();
+ m->addAction(tr("Edit &Shipping Options..."),this,SLOT(editShipping()));
+ m->addSeparator();
+ m->addAction(tr("&Deduct from voucher..."),this,SLOT(deductVoucher()));
+ m->addSeparator();
+ m->addAction(tr("&Money Log for voucher..."),this,SLOT(moneylogVoucher()));
+ m->addAction(tr("Money Log for &user..."),this,SLOT(moneylogUser()));
+
+ m=mb->addMenu(tr("C&onfigure"));
+ m->addAction(tr("&Auto-Refresh settings..."),this,SLOT(setRefresh()));
+ m->addAction(tr("&Server Access settings..."),this,SLOT(webSettings()));
+
+ m=mb->addMenu(tr("&Admin"));
+ m->addAction(tr("Backup &Settings..."),this,SLOT(backupSettings()))
+ ->setEnabled(req->hasRight(req->RBackup));
+ m->addAction(tr("&Backup now..."),this,SLOT(doBackup()))
+ ->setEnabled(req->hasRight(req->RBackup));
+
+ mb->addMenu(MApplication::helpMenu());
+
+ //tabs
+ setCentralWidget(tab=new QTabWidget);
+ connect(tab,SIGNAL(currentChanged(int)),this,SLOT(tabChanged()));
+
+ //Event tab
+ tab->addTab(eventtab=new QWidget,tr("Events"));
+ QVBoxLayout*vl;QHBoxLayout*hl;
+ eventtab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(eventtable=new QTableView,10);
+ eventtable->setModel(eventmodel=new QStandardItemModel(this));
+ eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
+ eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ QPushButton*p;
+ vl->addWidget(p=new QPushButton(tr("New Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
+ p->setEnabled(req->hasRole("createevent"));
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
+ p->setEnabled(req->hasRole("geteventdata"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+ p->setEnabled(req->hasRole("createorder"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
+ p->setEnabled(req->hasRole("eventsummary"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
+ p->setEnabled(req->hasRole("cancelevent"));
+ connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
+ vl->addStretch(10);
+
+ //Shopping Cart Tab
+ tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
+ carttab->setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ QVBoxLayout*vl2;
+ hl->addLayout(vl2=new QVBoxLayout,2);
+ vl2->addWidget(carttable=new QTableView,10);
+ carttable->setModel(cartmodel=new QStandardItemModel(this));
+ carttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ carttable->setItemDelegate(new MCartTableDelegate(this));
+ QHBoxLayout*hl2;
+ vl2->addLayout(hl2=new QHBoxLayout,0);
+ hl2->addStretch(10);
+ hl2->addWidget(p=new QPushButton(tr("Add Ticket")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddTicket()));
+ hl2->addWidget(p=new QPushButton(tr("Add Voucher")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddVoucher()));
+ hl2->addWidget(p=new QPushButton(tr("Remove Item")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartRemoveItem()));
+ QFrame*frm;
+ hl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::VLine);
+ hl->addLayout(vl2=new QVBoxLayout,1);
+ vl2->addWidget(p=new QPushButton(tr("Customer:")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setCustomer()));
+ vl2->addWidget(cartcustomer=new QLabel("...\n \n \n "));
+ vl2->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Shipping Method:")),0);
+ vl2->addWidget(cartship=new QComboBox,0);
+ cartship->setEditable(false);
+ vl2->addWidget(new QLabel(tr("Delivery Address:")),0);
+ vl2->addWidget(cartaddr=new QTextEdit);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Comments:")),0);
+ vl2->addWidget(cartcomment=new QTextEdit);
+ vl2->addStretch(10);
+ vl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("Check Order")));
+ p->setEnabled(req->hasRole("checkorder"));
+ connect(p,SIGNAL(clicked()),this,SLOT(cartOrder()));
+ hl->addWidget(p=new QPushButton(tr("Clear")));
+ connect(p,SIGNAL(clicked()),this,SLOT(initCart()));
+
+ //Order List Tab
+ tab->addTab(ordertab=new QWidget,tr("Order List"));
+ ordertab->setLayout(hl=new QHBoxLayout);
+ hl->addLayout(vl=new QVBoxLayout,10);
+ vl->addWidget(ordermode=new QComboBox,0);
+ ordermode->addItem(tr("-select mode-"),ORDERNONE);
+ ordermode->addItem(tr("All Orders"),ORDERALL);
+ ordermode->addItem(tr("Open Orders"),ORDEROPEN);
+ ordermode->addItem(tr("Open Reservations"),ORDERRESERVE);
+ ordermode->addItem(tr("Outstanding Payments"),ORDERPAY);
+ ordermode->addItem(tr("Outstanding Refunds"),ORDERREFUND);
+ ordermode->addItem(tr("Undelivered Orders"),ORDERUNSENT);
+ //make sure this entry is the last one, since we use count()-1 to select it
+ ordermode->addItem(tr("-search result-"),ORDERNONE);
+ connect(ordermode,SIGNAL(currentIndexChanged(int)),this,SLOT(updateOrders()));
+ vl->addWidget(ordertable=new QTableView);
+ ordertable->setModel(ordermodel=new QStandardItemModel(this));
+ ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ connect(ordertable,SIGNAL(doubleClicked(const QModelIndex&)),this,SLOT(orderDetails()));
+ hl->addLayout(vl=new QVBoxLayout,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->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Find by Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByTicket()));
+ p->setEnabled(req->hasRole("orderbyticket"));
+ vl->addWidget(p=new QPushButton(tr("Find by Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByEvent()));
+ p->setEnabled(req->hasRole("getordersbyevents"));
+ vl->addWidget(p=new QPushButton(tr("Find by Customer...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByCustomer()));
+ p->setEnabled(req->hasRole("getorderlist"));
+ vl->addWidget(p=new QPushButton(tr("Find by Order ID...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByOrder()));
+ p->setEnabled(req->hasRole("getorder"));
+ vl->addStretch(10);
+
+ //Entrance Control Tab
+ tab->addTab(entrancetab=new QWidget,tr("Entrance"));
+ entrancetab->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(entranceevent=new QComboBox,0);
+ entranceevent->setEditable(false);
+ vl->addSpacing(30);
+ vl->addWidget(new QLabel(tr("Enter or scan Ticket-ID:")),0);
+ vl->addWidget(entrancescan=new QLineEdit,0);
+ connect(entrancescan,SIGNAL(editingFinished()),this,SLOT(entranceValidate()));
+ vl->addWidget(entrancelabel=new QLabel(" "),10);
+ entrancelabel->setAutoFillBackground(true);
+ QFont fnt=entrancelabel->font();
+ fnt.setBold(true);fnt.setPointSize(24);
+ entrancelabel->setFont(fnt);
+ entrancelabel->setAlignment(Qt::AlignCenter);
+
+ //user tab
+ tab->addTab(usertab=new QWidget,tr("Users"));
+ usertab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(usertable=new QTableView,10);
+ usertable->setModel(usermodel=new QStandardItemModel(this));
+ usertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ usertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newUser()));
+ p->setEnabled(req->hasRole("adduser"));
+ vl->addWidget(p=new QPushButton(tr("Delete User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteUser()));
+ p->setEnabled(req->hasRole("deleteuser"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Description...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserDescription()));
+ p->setEnabled(req->hasRole("setuserdescription"));
+ vl->addWidget(p=new QPushButton(tr("Hosts...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserHosts()));
+ p->setEnabled(req->hasRole("getuserhosts"));
+ vl->addWidget(p=new QPushButton(tr("Roles...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserRoles()));
+ p->setEnabled(req->hasRole("getuseracl"));
+ vl->addWidget(p=new QPushButton(tr("Set Password...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setUserPassword()));
+ p->setEnabled(req->hasRole("setpasswd"));
+ vl->addStretch(10);
+
+ //host tab
+ tab->addTab(hosttab=new QWidget,tr("Hosts"));
+ hosttab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(hosttable=new QTableView,10);
+ hosttable->setModel(hostmodel=new QStandardItemModel(this));
+ hosttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ hosttable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(thishostbutton=p=new QPushButton(tr("Add This Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(addThisHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Delete Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteHost()));
+ p->setEnabled(req->hasRole("deletehost"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Generate New Key...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(changeHostKey()));
+ p->setEnabled(req->hasRole("sethostkey"));
+ vl->addWidget(p=new QPushButton(tr("Import...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(importHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Export...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(exportHost()));
+ p->setEnabled(req->hasRole("gethostkey"));
+ vl->addStretch(10);
+
+ //status bar
+ statusBar()->setSizeGripEnabled(true);
+
+ //make sure webrequest knows its settings
+ webSettings(false);
+ //fill tables
+ if(req->hasRight(req->RGetAllEvents)){
+ updateEvents();
+ }else{
+ eventtab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(eventtab),false);
+ }
+ if(!req->hasRole("createorder")&&!req->hasRole("createsale")){
+ carttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(carttab),false);
+ }else{
+ initCart();
+ }
+ updateShipping();
+ if(req->hasRole("getorderlist")){
+ updateOrders();
+ }else{
+ ordertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(ordertab),false);
+ }
+ if(req->hasRole("getusers")){
+ updateUsers();
+ }else{
+ usertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(usertab),false);
+ }
+ if(req->hasRole("gethosts")){
+ updateHosts();
+ }else{
+ hosttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(hosttab),false);
+ }
+}
+
+void MOverview::updateEvents()
+{
+ MTGetAllEvents gae=req->queryGetAllEvents();
+ if(gae.stage()!=gae.Success){
+ qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
+ return;
+ }
+ QList<MOEvent>evl=gae.getevents();
+ eventmodel->clear();
+ eventmodel->insertColumns(0,6);
+ eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
+ QDateTime now=QDateTime::currentDateTime();
+ for(int i=0,j=0;i<evl.size();i++){
+ QDateTime stime=QDateTime::fromTime_t(evl[i].start());
+ if(stime<now && !showoldevents->isChecked())continue;
+ eventmodel->insertRow(j);
+ eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
+ eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
+ eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
+ eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
+ eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
+ eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
+ eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
+ j++;
+ }
+ eventtable->resizeColumnsToContents();
+ //in case this was called from changing the check state
+ QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showoldevents->isChecked());
+}
+
+void MOverview::closeEvent(QCloseEvent*ce)
+{
+ //make sure session is deleted
+ req->logout();
+ //actually close window
+ QMainWindow::closeEvent(ce);
+}
+
+MOverview::~MOverview()
+{
+ //free requestor
+ req->deleteLater();
+}
+
+void MOverview::relogin()
+{
+ setEnabled(false);
+ if(!req->relogin())
+ QMessageBox::warning(this,tr("Warning"),tr("I was unable to renew the login at the server."));
+ setEnabled(true);
+}
+
+void MOverview::newEvent()
+{
+ MEventEditor ed(this);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::editEvent()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventEditor ed(this,id);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::eventSummary()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventSummary ed(this,id);
+ ed.exec();
+}
+
+void MOverview::eventCancel()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MTGetEvent getev=MTGetEvent::query(id);
+ if(!getev.hasError()){
+ bool ok;
+ MOEvent ev=getev.getevent();
+ QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
+ if(!ok)return;
+ MTCancelEvent cev=MTCancelEvent::query(id,r);
+ if(!cev.hasError())
+ QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
+ else
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
+ }
+}
+
+void MOverview::updateShipping()
+{
+ cartship->clear();
+ cartship->addItem(tr("(No Shipping)"),-1);
+ MTGetAllShipping sh=MTGetAllShipping::query();
+ QList<MOShipping>ship=sh.getshipping();
+ for(int i=0;i<ship.size();i++)
+ cartship->addItem(ship[i].description(),(int)ship[i].id());
+}
+
+void MOverview::updateUsers()
+{
+ MTGetAllUsers au=req->queryGetAllUsers();
+ if(au.hasError())return;
+ QList<MOUser>usl=au.getusers();
+ usermodel->clear();
+ usermodel->insertColumns(0,2);
+ usermodel->insertRows(0,usl.size());
+ usermodel->setHorizontalHeaderLabels(QStringList()<<tr("Login Name")<<tr("Description"));
+ for(int i=0;i<usl.size();i++){
+ usermodel->setData(usermodel->index(i,0),usl[i].name().value());
+ usermodel->setData(usermodel->index(i,1),usl[i].description().value());
+ }
+ usertable->resizeColumnsToContents();
+}
+
+void MOverview::newUser()
+{
+ //get name
+ QString name;
+ while(1){
+ bool ok;
+ name=QInputDialog::getText(this,tr("New User"),tr("Please enter new user name (only letters, digits, and underscore allowed):"),QLineEdit::Normal,name,&ok);
+ if(!ok)
+ return;
+ if(QRegExp("[A-Za-z0-9_\\.,:-]+").exactMatch(name))
+ break;
+ if(QMessageBox::warning(this,tr("Error"),tr("The user name must contain only letters, digits, dots and underscores and must be at least one character long!"),QMessageBox::Retry|QMessageBox::Abort)!=QMessageBox::Retry)
+ return;
+ }
+ //get password
+ QString pwd=QInputDialog::getText(this,tr("Password"),tr("Please enter an initial password for the user:"),QLineEdit::Password);
+ //send request
+ req->queryCreateUser(name,pwd,"");
+ //update display
+ updateUsers();
+}
+
+void MOverview::deleteUser()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //make sure user wants this
+ if(QMessageBox::question(this,tr("Delete User?"),tr("Really delete user '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //get replacement
+ bool ok;
+ QStringList rplc;
+ rplc<<tr("(Nobody)","this is a username for no user, the string must contain '(' to distinguish it from the others");
+ for(int i=0;i<usermodel->rowCount();i++)
+ rplc<<usermodel->data(usermodel->index(i,0)).toString();
+ QString rp=QInputDialog::getItem(this,tr("Delete User"),tr("Select which user will inherit this users database objects:"),rplc,0,false,&ok);
+ if(!ok)return;
+ //delete
+ MTDeleteUser ret=req->queryDeleteUser(name,rp);
+ if(ret.hasError())
+ QMessageBox::warning(this,tr("Error"),tr("Cannot delete user: %1").arg(ret.errorString()));
+ updateUsers();
+}
+
+void MOverview::editUserDescription()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ QString descr=usermodel->data(usermodel->index(sel.row(),1)).toString();
+ //edit descr
+ bool ok;
+ descr=QInputDialog::getText(this,tr("Edit Description"),tr("Descriptionof user %1:").arg(name),QLineEdit::Normal,descr,&ok);
+ if(ok)
+ req->querySetUserDescription(name,descr);
+ //update
+ updateUsers();
+}
+
+void MOverview::editUserRoles()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MOUser usr(req,name);
+ MCheckList acl=usr.getRoles();
+ MCheckDialog cd(this,acl,"Edit ACL of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setRoles(cd.getCheckList());*/
+}
+
+void MOverview::editUserHosts()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MUser usr(req,name);
+ MCheckList acl=usr.getHosts();
+ MCheckDialog cd(this,acl,"Edit hosts of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setHosts(cd.getCheckList());*/
+}
+
+void MOverview::setMyPassword()
+{
+ MPasswordChange pc(this);
+ if(pc.exec()==QDialog::Accepted){
+ MTChangeMyPassword cmp=MTChangeMyPassword::query(pc.oldPassword(),pc.newPassword());
+ if(cmp.hasError())
+ QMessageBox::warning(this,tr("Warning"),tr("Error setting password: %1").arg(cmp.errorString()));
+ }
+}
+void MOverview::setUserPassword()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //get new password
+ MPasswordChange pc(this,name);
+ if(pc.exec()!=QDialog::Accepted)return;
+ QString p=pc.newPassword();
+ if(p==""){
+ QMessageBox::warning(this,tr("Warning"),tr("The password must be non-empty and both lines must match"));
+ return;
+ }
+ //...
+ MUser usr(req,name);
+ usr.changePassword(p);*/
+}
+
+void MOverview::updateHosts()
+{/*TODO
+ bool foundThis=false;
+ QString thisHost=req->hostName();
+ QList<MHost>hsl=req->getAllHosts();
+ hostmodel->clear();
+ hostmodel->insertColumns(0,2);
+ hostmodel->insertRows(0,hsl.size());
+ hostmodel->setHorizontalHeaderLabels(QStringList()<<tr("Host Name")<<tr("Host Key"));
+ for(int i=0;i<hsl.size();i++){
+ hostmodel->setData(hostmodel->index(i,0),hsl[i].hostId());
+ hostmodel->setData(hostmodel->index(i,1),hsl[i].hostKey());
+ if(thisHost==hsl[i].hostId())
+ foundThis=true;
+ }
+ hosttable->resizeColumnsToContents();
+ thishostbutton->setEnabled(!foundThis && req->hasRole("addhost"));*/
+}
+
+void MOverview::newHost()
+{/*TODO
+ //get Host Name
+ QString hname;
+ do{
+ bool ok;
+ hname=QInputDialog::getText(this,tr("Create New Host"),tr("Please enter a host name:"),QLineEdit::Normal,hname,&ok);
+ if(!ok)return;
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname))continue;
+ }while(false);
+ //create it
+ MHost hst(req,hname);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The key of this new host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.create();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::addThisHost()
+{/*TODO
+ MHost hst(req,req->hostName(),QSettings().value("hostkey").toString());
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::deleteHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Delete this Host?"),tr("Really delete host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //delete it
+ MHost(req,name).deleteHost();
+ updateHosts();*/
+}
+
+void MOverview::changeHostKey()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Change Host Key?"),tr("Really change the key of host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //change it
+ MHost hst(req,name);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The new key of this host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.save();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::importHost()
+{/*TODO
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptOpen);
+ fdlg.setFileMode(QFileDialog::ExistingFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::ReadOnly)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ //read content (max: 10k to limit potential damage)
+ QStringList fc=QString::fromAscii(fd.read(10240)).split("\n",QString::SkipEmptyParts);
+ fd.close();
+ //check content
+ if(fc.size()<3){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ if(fc[0].trimmed()!="MagicSmokeHostKey"){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ QString hname=fc[1].trimmed();
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name."));
+ return;
+ }
+ QString key=fc[2].trimmed();
+ if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key."));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ if(chk!=fc[3].trimmed()){
+ QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file."));
+ return;
+ }
+ //save
+ MHost hst(req,hname,key);
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::exportHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ QString key=hostmodel->data(hostmodel->index(sel.row(),1)).toString();
+ if(name[0]=='_' || key==""){
+ QMessageBox::warning(this,tr("Warning"),tr("This host cannot be exported."));
+ return;
+ }
+ //save
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptSave);
+ fdlg.setFileMode(QFileDialog::AnyFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ QString out="MagicSmokeHostKey\n"+name+"\n"+key+"\n"+chk;
+ fd.write(out.toAscii());
+ fd.close();*/
+}
+
+
+void MOverview::initCart()
+{
+ //clear cart
+ cartmodel->clear();
+ cartmodel->setHorizontalHeaderLabels(QStringList()<<tr("Amount")<<tr("Title")<<tr("Start Time"));
+ //clear customer
+ customer=MCustomer();
+ cartcustomer->setText("");
+ //clear address/comment
+ cartaddr->setPlainText("");
+ cartcomment->setPlainText("");
+ //clear shipping
+ cartship->setCurrentIndex(0);
+}
+
+void MOverview::setCustomer()
+{/*TODO
+ MCustomerListDialog mcl(req,this,true,customer.customerID());
+ if(mcl.exec()!=QDialog::Accepted)return;
+ customer=mcl.getCustomer();
+ cartcustomer->setText(customer.getNameAddress());*/
+}
+
+static const int CART_TICKET=1;
+static const int CART_VOUCHER=2;
+
+static const int CART_IDROLE=Qt::UserRole;//ticket id
+static const int CART_PRICEROLE=Qt::UserRole;//voucher price
+static const int CART_VALUEROLE=Qt::UserRole+1;//voucher value
+static const int CART_TYPEROLE=Qt::UserRole+2;//which is it? ticket or voucher?
+
+void MOverview::cartAddTicket()
+{
+ //create ticket selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Event to order Ticket"));
+ QTableView*tv;
+ QHBoxLayout*hl;
+ QVBoxLayout*vl;
+ dlg.setLayout(vl=new QVBoxLayout);
+ vl->addWidget(tv=new QTableView,10);
+ tv->setModel(eventmodel);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->resizeColumnsToContents();
+ vl->addSpacing(15);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Select")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ connect(tv,SIGNAL(doubleClicked(const QModelIndex&)),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ QModelIndex idx=tv->currentIndex();
+ if(!idx.isValid())return;
+ int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt();
+ if(id<0)return;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(idx.row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(idx.row(),0)));
+ carttable->resizeColumnsToContents();
+ }
+}
+
+void MOverview::eventOrderTicket()
+{
+ //get selected event
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ //activate order tab
+ tab->setCurrentWidget(carttab);
+ //insert event into table
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(ilst[0].row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(ilst[0].row(),0)));
+ carttable->resizeColumnsToContents();
+}
+
+void MOverview::cartAddVoucher()
+{/*TODO
+ //create voucher selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Voucher"));
+ QComboBox*cp,*cv;
+ QHBoxLayout*hl;
+ QGridLayout*gl;
+ QStandardItemModel mdl;
+ QRegExpValidator regv(priceRegExp(),this);
+ QList<int>prc=req->getVoucherPrices();
+ mdl.insertRows(0,prc.size());
+ mdl.insertColumns(0,1);
+ for(int i=0;i<prc.size();i++)mdl.setData(mdl.index(i,0),cent2str(prc[i]));
+ dlg.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Select voucher price and value:")),0,0,1,2);
+ if(req->hasRole("_anypricevoucher")){
+ gl->addWidget(new QLabel(tr("Price:")),1,0);
+ gl->addWidget(cp=new QComboBox,1,1);
+ cp->setModel(&mdl);
+ cp->setEditable(true);
+ cp->setValidator(®v);
+ }else cp=0;
+ gl->addWidget(new QLabel(tr("Value:")),2,0);
+ gl->addWidget(cv=new QComboBox,2,1);
+ cv->setModel(&mdl);
+ cv->setEditable(req->hasRole("_anyvoucher"));
+ cv->setValidator(®v);
+ gl->setRowMinimumHeight(3,15);
+ gl->setColumnStretch(0,0);
+ gl->setColumnStretch(1,1);
+ gl->setRowStretch(3,1);
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ int price,value;
+ value=str2cent(cv->currentText());
+ if(req->hasRole("_anypricevoucher") && cp)
+ price=str2cent(cp->currentText());
+ else
+ price=value;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),price,CART_PRICEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),value,CART_VALUEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_VOUCHER,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (price: %1, value %2)").arg(cent2str(price)).arg(cent2str(value)));
+ carttable->resizeColumnsToContents();
+ }*/
+}
+
+void MOverview::cartRemoveItem()
+{
+ //get selection
+ QModelIndex idx=carttable->currentIndex();
+ if(!idx.isValid())return;
+ //remove row
+ cartmodel->removeRow(idx.row());
+}
+
+void MOverview::cartOrder()
+{
+ //sanity checks
+ if(cartmodel->rowCount()<1){
+ QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it."));
+ return;
+ }
+ if(!customer.isValid()){
+ QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!"));
+ return;
+ }
+ ///////////////
+ //create order
+ QDomDocument doc;
+ QDomElement root=doc.createElement("Order");
+ root.setAttribute("customer",customer.id());
+ //is there a delivery address
+ QString s=cartaddr->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement da=doc.createElement("DeliveryAddress");
+ da.appendChild(doc.createTextNode(s));
+ root.appendChild(da);
+ }
+ //is there a comment?
+ s=cartcomment->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement cc=doc.createElement("Comment");
+ cc.appendChild(doc.createTextNode(s));
+ root.appendChild(cc);
+ }
+ //scan tickets & scan vouchers
+ for(int i=0;i<cartmodel->rowCount();i++){
+ QModelIndex idx=cartmodel->index(i,0);
+ int tp=cartmodel->data(idx,CART_TYPEROLE).toInt();
+ if(tp==CART_TICKET){
+ int amt=cartmodel->data(idx).toInt();
+ int evid=cartmodel->data(idx,CART_IDROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Ticket");
+ tc.setAttribute("event",evid);
+ root.appendChild(tc);
+ }
+ }else
+ if(tp==CART_VOUCHER){
+ int amt=cartmodel->data(idx).toInt();
+ int price=cartmodel->data(idx,CART_PRICEROLE).toInt();
+ int value=cartmodel->data(idx,CART_VALUEROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Voucher");
+ tc.setAttribute("price",price);
+ tc.setAttribute("value",value);
+ root.appendChild(tc);
+ }
+
+ }
+ }
+ //set shipping info
+ if(cartship->currentIndex()>0){
+ QDomElement si=doc.createElement("Shipping");
+ si.setAttribute("type",cartship->itemData(cartship->currentIndex()).toInt());
+ root.appendChild(si);
+ }
+ //finalize
+ doc.appendChild(root);
+ //send
+ /*TODO
+ if(req->request("checkorder",doc.toByteArray())==false){
+ QMessageBox::warning(this,tr("Error"),tr("The request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Error"),tr("A problem occurred during the order: %1").arg(qApp->translate("php::",req->responseBody())));
+ return;
+ }
+ //parse result
+ QDomDocument rdoc;
+ rdoc.setContent(req->responseBody());
+ //display order and give user chance to actually order it
+ MOrderWindow *ow=new MOrderWindow(this,req,MOrder(req,rdoc.documentElement()));
+ ow->show();
+ //empty the cart
+ initCart();*/
+}
+
+void MOverview::customerMgmt()
+{/*TODO
+ MCustomerListDialog mcl(req,this);
+ mcl.exec();*/
+}
+
+void MOverview::editShipping()
+{/*TODO
+ MShippingEditor se(req,this);
+ se.exec();
+ updateShipping();*/
+}
+
+void MOverview::tabChanged()
+{/*TODO
+ QWidget*w=tab->currentWidget();
+ if(w==entrancetab){
+ //fill combobox from eventmodel
+ int ci=entranceevent->currentIndex();
+ int cev=-1;
+ if(ci>=0)cev=entranceevent->itemData(ci).toInt();
+ ci=-1;
+ entranceevent->clear();
+ for(int i=0;i<eventmodel->rowCount();i++){
+ QString ev=eventmodel->data(eventmodel->index(i,0)).toString()+" "+
+ eventmodel->data(eventmodel->index(i,1)).toString();
+ int eid=eventmodel->data(eventmodel->index(i,0),Qt::UserRole).toInt();
+ entranceevent->addItem(ev,eid);
+ if(eid==cev)ci=i;
+ }
+ if(ci>=0)entranceevent->setCurrentIndex(ci);
+ //set focus on scanner
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");
+ }*/
+}
+
+void MOverview::entranceValidate()
+{/*TODO
+ //get event ID
+ int ci=entranceevent->currentIndex();
+ if(ci<0)return;
+ int cev=entranceevent->itemData(ci).toInt();
+ //check content
+ QString tid=entrancescan->text().trimmed();
+ entrancescan->setText("");
+ //avoid spurious events
+ if(tid=="")return;
+ //avoid double scans
+ QDateTime now=QDateTime::currentDateTime();
+ if(tid==lastbarcode && lastbcscan.addSecs(20)>=now)
+ return;
+ lastbarcode=tid;
+ lastbcscan=now;
+ //reset display
+ QPalette pal=entrancelabel->palette();
+ QPalette::ColorRole rl=QPalette::Window;
+ pal.setColor(rl,Qt::lightGray);
+ entrancelabel->setPalette(pal);
+ entrancelabel->setText(tr("searching...","entrance control"));
+ //ask the server
+ MTicket tick(req,tid);
+ //decide what to do
+ if(!tick.isValid()){
+ entrancelabel->setText(tr("Ticket \"%1\" Not Valid").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.eventID()!=cev){
+ entrancelabel->setText(tr("Ticket \"%1\" is not for this event.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.status()==MTicket::Used){
+ entrancelabel->setText(tr("Ticket \"%1\" has already been used").arg(tid));
+ pal.setColor(rl,Qt::magenta);
+ }else
+ if(tick.status()!=MTicket::Bought){
+ entrancelabel->setText(tr("Ticket \"%1\" has not been bought.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.paymentStatus()==MTicket::PSOk){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedRefund){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok; the Order has a refund").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedPayment){
+ entrancelabel->setText(tr("Ticket \"%1\" is not paid for!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else{
+ entrancelabel->setText(tr("Ticket \"%1\" cannot be accepted, please check the order!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }
+
+ entrancelabel->setPalette(pal);
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");*/
+}
+
+//helper: finds out whether an order should be printed.
+static inline bool candoUpdateOrders(int omode,const MOrder&ord)
+{
+ if(omode==ORDERALL)return true;
+ if((omode&ORDERPAY)!=0 && ord.needsPayment())return true;
+ if((omode&ORDERREFUND)!=0 && ord.needsRefund())return true;
+ if((omode&ORDERUNSENT)!=0 && !ord.isSent())return true;
+ if((omode&ORDERRESERVE)!=0 && ord.isReservation())return true;
+ return false;
+}
+
+void MOverview::updateOrders()
+{/*TODO
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ int omode=ordermode->itemData(ordermode->currentIndex()).toInt();
+ if(omode==ORDERNONE)return;
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ if(!candoUpdateOrders(omode,orders[i]))continue;
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ int cid=orders[i].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ cl++;
+ }
+ ordertable->resizeColumnsToContents();*/
+}
+
+void MOverview::orderDetails()
+{/*TODO
+ //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::orderByTicket()
+{/*TODO
+ //get selected order
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Enter Ticket"),tr("Please enter the ID of one of the tickets of the order you seek:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ //request it
+ if(!req->request("orderbyticket",tid.toUtf8())){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to query server."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),qApp->translate("php::",req->responseBody()));
+ return;
+ }
+ int id=req->responseBody().trimmed().toInt(&ok);
+ if(!ok || id<0){
+ QMessageBox::warning(this,tr("Warning"),tr("Server returned an invalid order ID."));
+ return;
+ }
+ //open order window
+ MOrderWindow *om=new MOrderWindow(this,req,MOrder(req,id));
+ om->setAttribute(Qt::WA_DeleteOnClose);
+ om->show();*/
+}
+
+void MOverview::orderByEvent()
+{/*TODO
+ //display selection dialog
+ QDialog d(this);
+ d.setWindowTitle(tr("Select Event"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ QTableView*tv;
+ vl->addWidget(tv=new QTableView,10);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->setModel(eventmodel);
+ tv->resizeColumnsToContents();
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ //wait for user
+ if(d.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ QModelIndexList ilst=tv->selectionModel()->selectedIndexes();
+ if(ilst.size()<1){
+ qDebug("nothing selected");
+ return;
+ }
+ //get events
+ QList<int>eventids;
+ for(int i=0;i<ilst.size();i++){
+ int eid=eventmodel->data(eventmodel->index(ilst[i].row(),0),Qt::UserRole).toInt();
+ if(!eventids.contains(eid))eventids.append(eid);
+ }
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getOrdersByEvents(eventids);
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ for(int cl=0;cl<orders.size();cl++){
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[cl].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[cl].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[cl].amountPaidString());
+ int cid=orders[cl].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByCustomer()
+{/*TODO
+ //display selection dialog
+ MCustomerListDialog mcl(req,this,true);
+ //wait for user
+ if(mcl.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ MCustomer cst=mcl.getCustomer();
+ if(!cst.isValid()){
+ qDebug("nothing selected");
+ return;
+ }
+ qint64 custid=cst.customerID();
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ //filter
+ if(orders[i].customerID()!=custid)continue;
+ //put into table
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ ordermodel->setData(ordermodel->index(cl,3),cst.name());
+ //count up
+ cl++;
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByOrder()
+{/*TODO
+ //ask for OrderID
+ bool ok;
+ int oid=QInputDialog::getInteger(this,tr("Enter Order ID"),tr("Please enter the ID of the order you want to display:"),0,0,2147483647,1,&ok);
+ if(!ok)return;
+ //display
+ MOrder ord(req,oid);
+ if(!ord.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This order does not exist."));
+ return;
+ }
+ MOrderWindow *ow=new MOrderWindow(this,req,ord);
+ ow->show();*/
+}
+
+void MOverview::ticketReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Ticket"),tr("Please enter the ticket ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MTicket tick(req,tid);
+ if(!tick.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid ticket."));
+ return;
+ }
+ //check state
+ if(tick.status()!=MTicket::Bought && tick.status()!=MTicket::Reserved){
+ QMessageBox::warning(this,tr("Warning"),tr("This ticket cannot be returned, it has already been used or is in the wrong state."));
+ return;
+ }
+ //submit
+ QString r=tick.ticketReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::voucherReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Voucher"),tr("Please enter the voucher ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MVoucher vouc(req,tid);
+ if(!vouc.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid voucher."));
+ return;
+ }
+ //check state
+ if(vouc.isUsed()){
+ QMessageBox::warning(this,tr("Warning"),tr("This voucher cannot be returned, it has already been used."));
+ return;
+ }
+ //submit
+ QString r=vouc.voucherReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::deductVoucher()
+{/*TODO
+ //get voucher ID and amount
+ QDialog d;
+ d.setWindowTitle(tr("Deduct from Voucher"));
+ QGridLayout *gl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Using a voucher to pay outside the system.")),0,0,1,2);
+
+ QLineEdit*vid;
+ MCentSpinBox*cent;
+ gl->addWidget(new QLabel(tr("Amount to deduct:")),1,0);
+ gl->addWidget(cent=new MCentSpinBox,1,1);
+ gl->addWidget(new QLabel(tr("Voucher ID:")),2,0);
+ gl->addWidget(vid=new QLineEdit,2,1);
+
+ gl->setRowMinimumHeight(3,15);
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ if(vid->text().trimmed()=="" || cent->value()<=0)return;
+ //query server
+ QByteArray r=vid->text().trimmed().toAscii()+"\n"+QString::number(cent->value()).toAscii();
+ if(!req->request("usevoucheroutside",r)){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ QStringList sl=QString::fromAscii(req->responseBody().trimmed()).split("\n");
+ int tak=-1,rem=-1;
+ if(sl.size()>0)tak=sl[0].trimmed().toInt();
+ if(sl.size()>1)rem=sl[1].trimmed().toInt();
+ QMessageBox::information(this,tr("Deducted from Voucher"),tr("Value taken from voucher: %1\nValue remaining on voucher: %2").arg(cent2str(tak)).arg(cent2str(rem)));*/
+}
+
+void MOverview::refreshData()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ if(set.value("refreshEvents",false).toBool() && req->hasRole("geteventlist"))
+ updateEvents();
+ if(set.value("refreshUsers",false).toBool() && req->hasRole("getusers"))
+ updateUsers();
+ if(set.value("refreshHosts",false).toBool() && req->hasRole("gethosts"))
+ updateHosts();
+ if(set.value("refreshShipping",false).toBool() && req->hasRole("getshipping"))
+ updateShipping();
+}
+
+void MOverview::setRefresh()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //dialog
+ QDialog d;
+ d.setWindowTitle(tr("Refresh Settings"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Refresh Rate (minutes):")),1);
+ QSpinBox*rate;
+ hl->addWidget(rate=new QSpinBox,0);
+ rate->setRange(1,999);
+ rate->setValue(set.value("refresh",300).toInt()/60);
+ QCheckBox *rev,*rus,*rho,*rsh;
+ vl->addWidget(rev=new QCheckBox(tr("refresh &event list")));
+ rev->setChecked(set.value("refreshEvents",false).toBool());
+ vl->addWidget(rus=new QCheckBox(tr("refresh &user list")));
+ rus->setChecked(set.value("refreshUsers",false).toBool());
+ vl->addWidget(rho=new QCheckBox(tr("refresh &host list")));
+ rho->setChecked(set.value("refreshHosts",false).toBool());
+ vl->addWidget(rsh=new QCheckBox(tr("refresh &shipping list")));
+ rho->setChecked(set.value("refreshShipping",false).toBool());
+ vl->addSpacing(15);
+ vl->addStretch(10);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ set.setValue("refreshEvents",rev->isChecked());
+ set.setValue("refreshUsers",rus->isChecked());
+ set.setValue("refreshHosts",rho->isChecked());
+ set.setValue("refreshShipping",rsh->isChecked());
+ set.setValue("refresh",rate->value()*60);
+ //reset timer
+ rtimer.stop();
+ rtimer.setInterval(rate->value()*60000);
+ rtimer.start();
+}
+
+void MOverview::webSettings(bool showdlg)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //get settings
+ MSInterface::LogLevel lvl=MSInterface::LogLevel(set.value("webloglevel", MSInterface::LogOnError).toInt());
+ int timeout=set.value("webtimeout",30).toInt();
+ //dialog
+ if(showdlg){
+ QDialog d;
+ d.setWindowTitle(tr("Server Access Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Request Timeout (seconds):")),0,0);
+ QSpinBox*tmout;
+ gl->addWidget(tmout=new QSpinBox,0,1);
+ tmout->setRange(10,999);
+ tmout->setValue(timeout);
+ QComboBox *log;
+ gl->addWidget(new QLabel(tr("Log Level:")),1,0);
+ gl->addWidget(log=new QComboBox,1,1);
+ log->addItem(tr("Minimal Logging"),MSInterface::LogMinimal);
+ log->addItem(tr("Log Details on Error"),MSInterface::LogOnError);
+ log->addItem(tr("Always Log Details"),MSInterface::LogDetailed);
+ switch(lvl){
+ case MSInterface::LogMinimal:log->setCurrentIndex(0);break;
+ case MSInterface::LogOnError:log->setCurrentIndex(1);break;
+ case MSInterface::LogDetailed:log->setCurrentIndex(2);break;
+ }
+ gl->setRowMinimumHeight(2,15);
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ lvl=MSInterface::LogLevel(log->itemData(log->currentIndex()).toInt());
+ timeout=tmout->value();
+ set.setValue("webloglevel",lvl);
+ set.setValue("webtimeout",timeout);
+ }
+ //reset webrequest
+ req->setLogLevel(lvl);
+ req->setWebTimeout(timeout*1000);
+}
+
+void MOverview::doBackup()
+{
+ baktimer.stop();
+ //sanity check
+ if(!req->hasRight(req->RBackup))return;
+ //get settings
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ //get data
+ MTBackup bc;
+ bc=MTBackup::query();
+ if(bc.stage()!=bc.Success){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup failed with error (%2): %1").arg(bc.errorString()).arg(bc.errorType()));
+ return;
+ }
+ if(bc.getbackup().isNull()||bc.getbackup().value().isEmpty()){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup returned empty."));
+ return;
+ }
+ //rotate files
+ QFile(path+"."+QString::number(gens)).remove();
+ for(int i=gens-1;i>=0;i--){
+ if(i)
+ QFile(path+"."+QString::number(i)).rename(path+"."+QString::number(i+1));
+ else
+ QFile(path).rename(path+".1");
+ }
+ //store new data
+ QFile fd(path);
+ if(fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ fd.write(bc.getbackup().value().toAscii());
+ fd.close();
+ set.setValue("backuptime",QDateTime::currentDateTime().toTime_t());
+ QMessageBox::information(this,tr("Backup"),tr("The backup was successful."));
+ int tm=set.value("backupinterval",0).toInt()*86400000;
+ if(tm)baktimer.start(tm);
+ }else
+ QMessageBox::warning(this,tr("Warning"),tr("Cannot create backup file."));
+}
+
+void MOverview::backupSettings()
+{
+ //show dialog
+ MBackupDialog d(this,profilekey);
+ d.exec();
+ //reset timer
+ int btm=QSettings().value("profiles/"+profilekey+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+profilekey+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //start timer
+ baktimer.start(btm*1000);
+ }
+}
+
+void MOverview::moneylogVoucher()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("Voucher ID"),tr("Please enter voucher ID to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"voucher\n"+vid).exec();*/
+}
+
+void MOverview::moneylogUser()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("User"),tr("Please enter login name of user to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"user\n"+vid).exec();*/
+}
+
+
+/**********************************************/
+
+MBackupDialog::MBackupDialog(QWidget*par,QString pk)
+ :QDialog(par),profilekey(pk)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ int tm=set.value("backupinterval",0).toInt();
+ //dialog
+ setWindowTitle(tr("Backup Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ setLayout(gl=new QGridLayout);
+ QPushButton*p;
+ gl->addWidget(new QLabel(tr("Backup File:")),0,0);
+ gl->addWidget(lpath=new QLineEdit(path),0,1);
+ gl->addWidget(p=new QPushButton(tr("...")),0,2);
+ connect(p,SIGNAL(clicked()),this,SLOT(getpath()));
+
+ gl->addWidget(new QLabel(tr("Generations to keep:")),1,0);
+ gl->addWidget(gener=new QSpinBox,1,1,1,2);
+ gener->setRange(1,16);
+ gener->setValue(gens);
+
+ gl->addWidget(new QLabel(tr("Automatic Backup:")),2,0);
+ gl->addWidget(autob=new QCheckBox,2,1,1,2);
+ autob->setChecked(tm>0);
+
+ gl->addWidget(new QLabel(tr("Interval in days:")),3,0);
+ gl->addWidget(interv=new QSpinBox,3,1,1,2);
+ interv->setRange(1,24);
+ interv->setValue(tm>0?tm:1);
+
+ gl->setRowMinimumHeight(4,15);
+ gl->addLayout(hl=new QHBoxLayout,5,0,1,3);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ connect(p,SIGNAL(clicked()),this,SLOT(save()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+void MBackupDialog::getpath()
+{
+ QString path=QFileDialog::getSaveFileName(this,tr("Backup File"),lpath->text());
+ if(path!="")lpath->setText(path);
+}
+
+void MBackupDialog::save()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ set.setValue("backupfile",lpath->text());
+ set.setValue("backupgenerations",gener->value());
+ set.setValue("backupinterval",autob->isChecked()?interv->value():0);
+}
+/**********************************************/
+
+MPasswordChange::MPasswordChange(QWidget*par,QString user)
+ :QDialog(par)
+{
+ oldpwd=newpwd1=newpwd2=0;
+ if(user=="")
+ setWindowTitle(tr("Change my password"));
+ else
+ setWindowTitle(tr("Reset password of user \"%1\"").arg(user));
+ QGridLayout*gl;
+ setLayout(gl=new QGridLayout);
+ if(user==""){
+ gl->addWidget(new QLabel(tr("Old Password:")),0,0);
+ gl->addWidget(oldpwd=new QLineEdit,0,1);
+ oldpwd->setEchoMode(QLineEdit::Password);
+ }
+ gl->addWidget(new QLabel(tr("New Password:")),1,0);
+ gl->addWidget(newpwd1=new QLineEdit,1,1);
+ newpwd1->setEchoMode(QLineEdit::Password);
+ gl->addWidget(new QLabel(tr("Repeat Password:")),2,0);
+ gl->addWidget(newpwd2=new QLineEdit,2,1);
+ newpwd2->setEchoMode(QLineEdit::Password);
+
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Set Password")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+QString MPasswordChange::oldPassword()
+{
+ if(oldpwd)return oldpwd->text();
+ return "";
+}
+
+QString MPasswordChange::newPassword()
+{
+ if(newpwd1==0 || newpwd2==0)return "";
+ if(newpwd1->text()!=newpwd2->text())return "";
+ return newpwd1->text();
+}
+
+
+/********************************************************************************/
+
+MCartTableDelegate::MCartTableDelegate(QObject*p)
+ :QItemDelegate(p)
+{
+}
+
+QWidget *MCartTableDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &/* option */,
+ const QModelIndex & index ) const
+{
+ //base class
+ if(index.column()!=0)return 0;
+
+ QSpinBox *editor = new QSpinBox(parent);
+ editor->setRange(1,1000);
+ editor->installEventFilter(const_cast<MCartTableDelegate*>(this));
+ return editor;
+}
+
+void MCartTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0)
+ ((QSpinBox*)editor)->setValue(index.model()->data(index).toInt());
+}
+
+void MCartTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0){
+ int newval=((QSpinBox*)editor)->value();
+ model->setData(index,newval);
+ }
+}
--- /dev/null
+//
+// C++ Interface: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_OVERVIEW_H
+#define MAGICSMOKE_OVERVIEW_H
+
+#include <QDateTime>
+#include <QDialog>
+#include <QItemDelegate>
+#include <QMainWindow>
+#include <QTimer>
+
+#include "customer.h"
+
+class QAction;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class QStandardItemModel;
+class QTabWidget;
+class QTableView;
+
+class MSInterface;
+
+/**Main Overview Window*/
+class MOverview:public QMainWindow
+{
+ Q_OBJECT
+ public:
+ /**construct the window with web-request/session handler and QSettings-key for current profile*/
+ MOverview(QString);
+ ~MOverview();
+ protected:
+ /**handle closing the window: close the session too*/
+ void closeEvent(QCloseEvent*);
+ private slots:
+ /**try to log in again*/
+ void relogin();
+
+ /**create a new event*/
+ void newEvent();
+ /**edit existing event*/
+ void editEvent();
+ /**update list of events*/
+ void updateEvents();
+ /**order ticket from event tab*/
+ void eventOrderTicket();
+ /**open event summary*/
+ void eventSummary();
+ /**cancel the event*/
+ void eventCancel();
+
+ /**update shipping info*/
+ void updateShipping();
+
+ /**get all orders, update list*/
+ void updateOrders();
+ /**open order detail window*/
+ void orderDetails();
+
+ /**update list of users*/
+ void updateUsers();
+ /**create new user*/
+ void newUser();
+ /**delete selected user*/
+ void deleteUser();
+ /**set users description*/
+ void editUserDescription();
+ /**set users roles*/
+ void editUserRoles();
+ /**set users hosts*/
+ void editUserHosts();
+ /**set my own password*/
+ void setMyPassword();
+ /**set a users password*/
+ void setUserPassword();
+
+ /**update list of hosts*/
+ void updateHosts();
+ /**create new host*/
+ void newHost();
+ /**create a database entry for this host*/
+ void addThisHost();
+ /**delete a host*/
+ void deleteHost();
+ /**generate a new key*/
+ void changeHostKey();
+ /**import host from file*/
+ void importHost();
+ /**export host to file*/
+ void exportHost();
+
+ /**decide what customer to use*/
+ void setCustomer();
+ /**initialize cart tab*/
+ void initCart();
+ /**add a ticket to the cart*/
+ void cartAddTicket();
+ /**add a voucher to the cart*/
+ void cartAddVoucher();
+ /**remove item from the cart*/
+ void cartRemoveItem();
+ /**check the order on the server*/
+ void cartOrder();
+
+ /**manage customers*/
+ void customerMgmt();
+
+ /**edit shipping options*/
+ void editShipping();
+
+ /**generic check which tab is active*/
+ void tabChanged();
+
+ /**react on entry in Entrance tab*/
+ void entranceValidate();
+
+ /**return a ticket*/
+ void ticketReturn();
+ /**return a voucher*/
+ void voucherReturn();
+ /**find an order by ticket*/
+ void orderByTicket();
+ /**find/select orders by event*/
+ void orderByEvent();
+ /**find/select orders by customer*/
+ void orderByCustomer();
+ /**find and display order by order ID*/
+ void orderByOrder();
+ /**deduct some money from a voucher (to pay outside the system)*/
+ void deductVoucher();
+
+ /**money log for voucher*/
+ void moneylogVoucher();
+ /**money log for user*/
+ void moneylogUser();
+
+ /**refresh data that we can refresh*/
+ void refreshData();
+ /**set refresh timeout*/
+ void setRefresh();
+
+ /**web request settings dialog; shows the dialog per default, just copies settings from registry to webrequest object if false*/
+ void webSettings(bool dlg=true);
+
+ /**do a backup now*/
+ void doBackup();
+
+ /**settings for backup*/
+ void backupSettings();
+
+ private:
+ //the profile associated with this session
+ QString profilekey;
+ //widgets
+ QTabWidget*tab;
+ QWidget*eventtab,*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
+ QTableView*eventtable,*usertable,*hosttable,*carttable,*ordertable;
+ QStandardItemModel*eventmodel,*usermodel,*hostmodel,*cartmodel,*ordermodel;
+ QPushButton*thishostbutton;
+ QLabel*cartcustomer,*entrancelabel;
+ QTextEdit *cartaddr,*cartcomment;
+ QComboBox*ordermode,*cartship,*entranceevent;
+ QLineEdit*entrancescan;
+ //event list
+ QAction*showoldevents;
+ //cart
+ MCustomer customer;
+ //barcode cache
+ QString lastbarcode;
+ QDateTime lastbcscan;
+ //refresh timers
+ QTimer rtimer,baktimer;
+};
+
+/**Helper dialog for changing passwords*/
+class MPasswordChange:public QDialog
+{
+ Q_OBJECT
+ public:
+ /**creates a password change dialog, if user is empty it is presumed to change own password*/
+ MPasswordChange(QWidget*parent,QString user=QString());
+
+ /**if own password: return old password*/
+ QString oldPassword();
+ /**returns new password, or empty if the two lines don't match*/
+ QString newPassword();
+ private:
+ QLineEdit *oldpwd,*newpwd1,*newpwd2;
+};
+
+/**Helper class for shopping cart: allow editing amount, but nothing else*/
+class MCartTableDelegate:public QItemDelegate
+{
+ public:
+ MCartTableDelegate(QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void setEditorData(QWidget *editor, const QModelIndex &index) const;
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const;
+};
+
+/**Helper class for Backup settings*/
+class MBackupDialog:public QDialog
+{
+ Q_OBJECT
+ public:
+ MBackupDialog(QWidget*,QString);
+
+ private slots:
+ void getpath();
+ void save();
+ private:
+ QLineEdit*lpath;
+ QSpinBox*interv,*gener;
+ QCheckBox*autob;
+ QString profilekey;
+};
+
+#endif
--- /dev/null
+//
+// C++ Implementation: event list tab
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "centbox.h"
+#include "eventedit.h"
+#include "eventsummary.h"
+#include "main.h"
+#include "misc.h"
+#include "msinterface.h"
+
+#include "eventstab.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QFrame>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSettings>
+#include <QSpinBox>
+#include <QStandardItemModel>
+#include <QTableView>
+#include <QTextEdit>
+
+#define req (MSInterface::instance())
+
+MEventsTab::MEventsTab(QString pk)
+{
+ profilekey=pk;
+ showoldevents=0;
+
+ //Event tab
+ QVBoxLayout*vl;QHBoxLayout*hl;
+ setLayout(hl=new QHBoxLayout);
+ hl->addWidget(eventtable=new QTableView,10);
+ eventtable->setModel(eventmodel=new QStandardItemModel(this));
+ eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
+ eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ QPushButton*p;
+ vl->addWidget(p=new QPushButton(tr("New Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
+ p->setEnabled(req->hasRole("createevent"));
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
+ p->setEnabled(req->hasRole("geteventdata"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+ p->setEnabled(req->hasRole("createorder"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
+ p->setEnabled(req->hasRole("eventsummary"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
+ p->setEnabled(req->hasRole("cancelevent"));
+ connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
+ vl->addStretch(10);
+
+ //fill tables
+ if(req->hasRight(req->RGetAllEvents)){
+ updateEvents();
+ }
+}
+
+QMenu*MEventsTab::menu()
+{
+ //menu
+ QMenu*m=new QMenu(tr("&Event"));
+ m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
+ ->setEnabled(req->hasRight(req->RGetEvent));
+ m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
+ m->addSeparator();
+ showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
+ showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
+ showoldevents->setCheckable(true);
+ showoldevents->setChecked(QSettings().value("profiles/"+profilekey+"/showOldEvents",false).toBool());
+
+ return m;
+}
+
+
+void MEventsTab::updateEvents()
+{
+ MTGetAllEvents gae=req->queryGetAllEvents();
+ if(gae.stage()!=gae.Success){
+ qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
+ return;
+ }
+ QList<MOEvent>evl=gae.getevents();
+ eventmodel->clear();
+ eventmodel->insertColumns(0,6);
+ eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
+ QDateTime now=QDateTime::currentDateTime();
+ bool showold;
+ if(showoldevents)showold=showoldevents->isChecked();
+ else showold=QSettings().value("profiles/"+profilekey+"/showOldEvents",false).toBool();
+ for(int i=0,j=0;i<evl.size();i++){
+ QDateTime stime=QDateTime::fromTime_t(evl[i].start());
+ if(stime<now && !showold)continue;
+ eventmodel->insertRow(j);
+ eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
+ eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
+ eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
+ eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
+ eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
+ eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
+ eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
+ j++;
+ }
+ eventtable->resizeColumnsToContents();
+ //in case this was called from changing the check state
+ if(showoldevents)
+ QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showold);
+}
+
+MEventsTab::~MEventsTab()
+{
+}
+
+void MEventsTab::newEvent()
+{
+ MEventEditor ed(this);
+ ed.exec();
+ updateEvents();
+}
+
+void MEventsTab::editEvent()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventEditor ed(this,id);
+ ed.exec();
+ updateEvents();
+}
+
+void MEventsTab::eventSummary()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventSummary ed(this,id);
+ ed.exec();
+}
+
+void MEventsTab::eventCancel()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MTGetEvent getev=MTGetEvent::query(id);
+ if(!getev.hasError()){
+ bool ok;
+ MOEvent ev=getev.getevent();
+ QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
+ if(!ok)return;
+ MTCancelEvent cev=MTCancelEvent::query(id,r);
+ if(!cev.hasError())
+ QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
+ else
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
+ }
+}
+
+int MEventsTab::currentEventId()const
+{
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return -1;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ return eventmodel->data(idx,Qt::UserRole).toInt();
+}
+
+QString MEventsTab::currentEventTitle()const
+{
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return "";
+ return eventmodel->data(eventmodel->index(ilst[0].row(),1)).toString();
+}
+
+QString MEventsTab::currentEventStart()const
+{
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return "";
+ return eventmodel->data(eventmodel->index(ilst[0].row(),0)).toString();
+}
--- /dev/null
+//
+// C++ Interface: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_EVENTSTAB_H
+#define MAGICSMOKE_EVENTSTAB_H
+
+#include <QDateTime>
+#include <QDialog>
+#include <QItemDelegate>
+#include <QMainWindow>
+#include <QTimer>
+
+class QAction;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class QStandardItemModel;
+class QTabWidget;
+class QTableView;
+
+class MSInterface;
+
+/**Main Overview Window: Event List Tab*/
+class MEventsTab:public QWidget
+{
+ Q_OBJECT
+ public:
+ /**construct the tab with QSettings-key for current profile*/
+ MEventsTab(QString);
+
+ /**create menu for this tab*/
+ QMenu*menu();
+
+ /**returns event table model*/
+ QStandardItemModel*eventModel(){return eventmodel;}
+ /**returns the currently selected event (as ID) or -1 if none is selected*/
+ int currentEventId()const;
+ /**returns the currently selected event start time as string*/
+ QString currentEventStart()const;
+ /**returns the currently selected event title*/
+ QString currentEventTitle()const;
+
+ /**destruct events list tab*/
+ ~MEventsTab();
+ private slots:
+ /**create a new event*/
+ void newEvent();
+ /**edit existing event*/
+ void editEvent();
+ /**open event summary*/
+ void eventSummary();
+ /**cancel the event*/
+ void eventCancel();
+ public slots:
+ /**update list of events*/
+ void updateEvents();
+
+ signals:
+ /**order ticket from event tab*/
+ void eventOrderTicket();
+
+ private:
+ //the profile associated with this session
+ QString profilekey;
+ //widgets
+ QTableView*eventtable;
+ QStandardItemModel*eventmodel;
+ //event list
+ QAction*showoldevents;
+ //refresh timers
+ QTimer rtimer;
+};
+
+#endif
HEADERS += \
- mwin/overview.h
+ mwin/overview.h \
+ mwin/eventstab.h
SOURCES += \
- mwin/overview.cpp
+ mwin/overview.cpp \
+ mwin/eventstab.cpp
INCLUDEPATH += ./mwin
\ No newline at end of file
--- /dev/null
+//
+// C++ Implementation: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "centbox.h"
+#include "checkdlg.h"
+#include "eventedit.h"
+#include "eventsummary.h"
+#include "main.h"
+#include "misc.h"
+#include "moneylog.h"
+#include "msinterface.h"
+#include "orderwin.h"
+#include "overview.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QCryptographicHash>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFile>
+#include <QFileDialog>
+#include <QFrame>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QSettings>
+#include <QSpinBox>
+#include <QStandardItemModel>
+#include <QStatusBar>
+#include <QTabWidget>
+#include <QTableView>
+#include <QTextEdit>
+
+#define ORDERNONE 0
+#define ORDERALL 0xff
+#define ORDEROPEN 0xf
+#define ORDERPAY 1
+#define ORDERREFUND 2
+#define ORDERUNSENT 4
+#define ORDERRESERVE 8
+
+#define req (MSInterface::instance())
+
+MOverview::MOverview(QString pk)
+{
+ profilekey=pk;
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle("MagicSmoke: "+req->currentUser()+"@"+QSettings().value("profiles/"+pk+"/name").toString());
+ rtimer.setInterval(QSettings().value("profiles/"+pk+"/refresh",300).toInt()*1000);
+ rtimer.start();
+ connect(&rtimer,SIGNAL(timeout()),this,SLOT(refreshData()));
+ //check backup timing
+ int btm=QSettings().value("profiles/"+pk+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+pk+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //earliest allowed backup is 30s from now
+ if(btm<30)btm=30;
+ //start timer
+ baktimer.start(btm*1000);
+ connect(&baktimer,SIGNAL(timeout()),this,SLOT(doBackup()));
+ }
+
+ //menu
+ QMenuBar*mb=menuBar();
+ QMenu*m=mb->addMenu(tr("&Session"));
+ m->addAction(tr("&Re-Login"),this,SLOT(relogin()));
+ m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword()))
+ ->setEnabled(req->hasRight(req->RChangeMyPassword));
+ m->addSeparator();
+ m->addAction(tr("&Edit Templates..."),req,SLOT(editTemplates()));
+ m->addAction(tr("&Update Templates Now"),req,SLOT(updateTemplates()));
+ m->addSeparator();
+ m->addAction(tr("&Close Session"),this,SLOT(close()));
+
+ m=mb->addMenu(tr("&Event"));
+ m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
+ ->setEnabled(req->hasRight(req->RGetAllEvents));
+ m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
+ ->setEnabled(req->hasRight(req->RGetEvent));
+ m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
+ m->addSeparator();
+ showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
+ showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
+ showoldevents->setCheckable(true);
+ showoldevents->setChecked(QSettings().value("profiles/"+pk+"/showOldEvents",false).toBool());
+
+ m=mb->addMenu(tr("&Customer"));
+ m->addAction(tr("&Show all customers"),this,SLOT(customerMgmt()));
+
+ m=mb->addMenu(tr("C&art"));
+ m->addAction(tr("Add &Ticket"),this,SLOT(cartAddTicket()));
+ m->addAction(tr("Add &Voucher"),this,SLOT(cartAddVoucher()));
+ m->addAction(tr("&Remove Item"),this,SLOT(cartRemoveItem()));
+ m->addAction(tr("&Abort Shopping"),this,SLOT(initCart()));
+ m->addSeparator();
+ m->addAction(tr("&Update Shipping Options"),this,SLOT(updateShipping()));
+
+ m=mb->addMenu(tr("&Misc"));
+ m->addAction(tr("Return &ticket..."),this,SLOT(ticketReturn()));
+ m->addAction(tr("Return &voucher..."),this,SLOT(voucherReturn()));
+ m->addSeparator();
+ m->addAction(tr("Edit &Shipping Options..."),this,SLOT(editShipping()));
+ m->addSeparator();
+ m->addAction(tr("&Deduct from voucher..."),this,SLOT(deductVoucher()));
+ m->addSeparator();
+ m->addAction(tr("&Money Log for voucher..."),this,SLOT(moneylogVoucher()));
+ m->addAction(tr("Money Log for &user..."),this,SLOT(moneylogUser()));
+
+ m=mb->addMenu(tr("C&onfigure"));
+ m->addAction(tr("&Auto-Refresh settings..."),this,SLOT(setRefresh()));
+ m->addAction(tr("&Server Access settings..."),this,SLOT(webSettings()));
+
+ m=mb->addMenu(tr("&Admin"));
+ m->addAction(tr("Backup &Settings..."),this,SLOT(backupSettings()))
+ ->setEnabled(req->hasRight(req->RBackup));
+ m->addAction(tr("&Backup now..."),this,SLOT(doBackup()))
+ ->setEnabled(req->hasRight(req->RBackup));
+
+ mb->addMenu(MApplication::helpMenu());
+
+ //tabs
+ setCentralWidget(tab=new QTabWidget);
+ connect(tab,SIGNAL(currentChanged(int)),this,SLOT(tabChanged()));
+
+ //Event tab
+ tab->addTab(eventtab=new QWidget,tr("Events"));
+ QVBoxLayout*vl;QHBoxLayout*hl;
+ eventtab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(eventtable=new QTableView,10);
+ eventtable->setModel(eventmodel=new QStandardItemModel(this));
+ eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
+ eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ QPushButton*p;
+ vl->addWidget(p=new QPushButton(tr("New Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
+ p->setEnabled(req->hasRole("createevent"));
+ vl->addWidget(p=new QPushButton(tr("Details...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
+ p->setEnabled(req->hasRole("geteventdata"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+ p->setEnabled(req->hasRole("createorder"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
+ p->setEnabled(req->hasRole("eventsummary"));
+ vl->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
+ p->setEnabled(req->hasRole("cancelevent"));
+ connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
+ vl->addStretch(10);
+
+ //Shopping Cart Tab
+ tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
+ carttab->setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ QVBoxLayout*vl2;
+ hl->addLayout(vl2=new QVBoxLayout,2);
+ vl2->addWidget(carttable=new QTableView,10);
+ carttable->setModel(cartmodel=new QStandardItemModel(this));
+ carttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ carttable->setItemDelegate(new MCartTableDelegate(this));
+ QHBoxLayout*hl2;
+ vl2->addLayout(hl2=new QHBoxLayout,0);
+ hl2->addStretch(10);
+ hl2->addWidget(p=new QPushButton(tr("Add Ticket")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddTicket()));
+ hl2->addWidget(p=new QPushButton(tr("Add Voucher")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartAddVoucher()));
+ hl2->addWidget(p=new QPushButton(tr("Remove Item")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(cartRemoveItem()));
+ QFrame*frm;
+ hl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::VLine);
+ hl->addLayout(vl2=new QVBoxLayout,1);
+ vl2->addWidget(p=new QPushButton(tr("Customer:")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setCustomer()));
+ vl2->addWidget(cartcustomer=new QLabel("...\n \n \n "));
+ vl2->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Shipping Method:")),0);
+ vl2->addWidget(cartship=new QComboBox,0);
+ cartship->setEditable(false);
+ vl2->addWidget(new QLabel(tr("Delivery Address:")),0);
+ vl2->addWidget(cartaddr=new QTextEdit);
+ vl2->addSpacing(10);
+ vl2->addWidget(new QLabel(tr("Comments:")),0);
+ vl2->addWidget(cartcomment=new QTextEdit);
+ vl2->addStretch(10);
+ vl->addWidget(frm=new QFrame,0);
+ frm->setFrameShape(QFrame::HLine);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("Check Order")));
+ p->setEnabled(req->hasRole("checkorder"));
+ connect(p,SIGNAL(clicked()),this,SLOT(cartOrder()));
+ hl->addWidget(p=new QPushButton(tr("Clear")));
+ connect(p,SIGNAL(clicked()),this,SLOT(initCart()));
+
+ //Order List Tab
+ tab->addTab(ordertab=new QWidget,tr("Order List"));
+ ordertab->setLayout(hl=new QHBoxLayout);
+ hl->addLayout(vl=new QVBoxLayout,10);
+ vl->addWidget(ordermode=new QComboBox,0);
+ ordermode->addItem(tr("-select mode-"),ORDERNONE);
+ ordermode->addItem(tr("All Orders"),ORDERALL);
+ ordermode->addItem(tr("Open Orders"),ORDEROPEN);
+ ordermode->addItem(tr("Open Reservations"),ORDERRESERVE);
+ ordermode->addItem(tr("Outstanding Payments"),ORDERPAY);
+ ordermode->addItem(tr("Outstanding Refunds"),ORDERREFUND);
+ ordermode->addItem(tr("Undelivered Orders"),ORDERUNSENT);
+ //make sure this entry is the last one, since we use count()-1 to select it
+ ordermode->addItem(tr("-search result-"),ORDERNONE);
+ connect(ordermode,SIGNAL(currentIndexChanged(int)),this,SLOT(updateOrders()));
+ vl->addWidget(ordertable=new QTableView);
+ ordertable->setModel(ordermodel=new QStandardItemModel(this));
+ ordertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ ordertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ connect(ordertable,SIGNAL(doubleClicked(const QModelIndex&)),this,SLOT(orderDetails()));
+ hl->addLayout(vl=new QVBoxLayout,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->addSpacing(15);
+ vl->addWidget(p=new QPushButton(tr("Find by Ticket...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByTicket()));
+ p->setEnabled(req->hasRole("orderbyticket"));
+ vl->addWidget(p=new QPushButton(tr("Find by Event...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByEvent()));
+ p->setEnabled(req->hasRole("getordersbyevents"));
+ vl->addWidget(p=new QPushButton(tr("Find by Customer...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByCustomer()));
+ p->setEnabled(req->hasRole("getorderlist"));
+ vl->addWidget(p=new QPushButton(tr("Find by Order ID...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(orderByOrder()));
+ p->setEnabled(req->hasRole("getorder"));
+ vl->addStretch(10);
+
+ //Entrance Control Tab
+ tab->addTab(entrancetab=new QWidget,tr("Entrance"));
+ entrancetab->setLayout(vl=new QVBoxLayout);
+ vl->addWidget(entranceevent=new QComboBox,0);
+ entranceevent->setEditable(false);
+ vl->addSpacing(30);
+ vl->addWidget(new QLabel(tr("Enter or scan Ticket-ID:")),0);
+ vl->addWidget(entrancescan=new QLineEdit,0);
+ connect(entrancescan,SIGNAL(editingFinished()),this,SLOT(entranceValidate()));
+ vl->addWidget(entrancelabel=new QLabel(" "),10);
+ entrancelabel->setAutoFillBackground(true);
+ QFont fnt=entrancelabel->font();
+ fnt.setBold(true);fnt.setPointSize(24);
+ entrancelabel->setFont(fnt);
+ entrancelabel->setAlignment(Qt::AlignCenter);
+
+ //user tab
+ tab->addTab(usertab=new QWidget,tr("Users"));
+ usertab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(usertable=new QTableView,10);
+ usertable->setModel(usermodel=new QStandardItemModel(this));
+ usertable->setSelectionMode(QAbstractItemView::SingleSelection);
+ usertable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newUser()));
+ p->setEnabled(req->hasRole("adduser"));
+ vl->addWidget(p=new QPushButton(tr("Delete User...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteUser()));
+ p->setEnabled(req->hasRole("deleteuser"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Description...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserDescription()));
+ p->setEnabled(req->hasRole("setuserdescription"));
+ vl->addWidget(p=new QPushButton(tr("Hosts...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserHosts()));
+ p->setEnabled(req->hasRole("getuserhosts"));
+ vl->addWidget(p=new QPushButton(tr("Roles...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(editUserRoles()));
+ p->setEnabled(req->hasRole("getuseracl"));
+ vl->addWidget(p=new QPushButton(tr("Set Password...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(setUserPassword()));
+ p->setEnabled(req->hasRole("setpasswd"));
+ vl->addStretch(10);
+
+ //host tab
+ tab->addTab(hosttab=new QWidget,tr("Hosts"));
+ hosttab->setLayout(hl=new QHBoxLayout);
+ hl->addWidget(hosttable=new QTableView,10);
+ hosttable->setModel(hostmodel=new QStandardItemModel(this));
+ hosttable->setSelectionMode(QAbstractItemView::SingleSelection);
+ hosttable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ hl->addSpacing(5);
+ hl->addLayout(vl=new QVBoxLayout,0);
+ vl->addWidget(p=new QPushButton(tr("New Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(newHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(thishostbutton=p=new QPushButton(tr("Add This Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(addThisHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Delete Host...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(deleteHost()));
+ p->setEnabled(req->hasRole("deletehost"));
+ vl->addSpacing(20);
+ vl->addWidget(p=new QPushButton(tr("Generate New Key...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(changeHostKey()));
+ p->setEnabled(req->hasRole("sethostkey"));
+ vl->addWidget(p=new QPushButton(tr("Import...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(importHost()));
+ p->setEnabled(req->hasRole("addhost"));
+ vl->addWidget(p=new QPushButton(tr("Export...")),0);
+ connect(p,SIGNAL(clicked()),this,SLOT(exportHost()));
+ p->setEnabled(req->hasRole("gethostkey"));
+ vl->addStretch(10);
+
+ //status bar
+ statusBar()->setSizeGripEnabled(true);
+
+ //make sure webrequest knows its settings
+ webSettings(false);
+ //fill tables
+ if(req->hasRight(req->RGetAllEvents)){
+ updateEvents();
+ }else{
+ eventtab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(eventtab),false);
+ }
+ if(!req->hasRole("createorder")&&!req->hasRole("createsale")){
+ carttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(carttab),false);
+ }else{
+ initCart();
+ }
+ updateShipping();
+ if(req->hasRole("getorderlist")){
+ updateOrders();
+ }else{
+ ordertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(ordertab),false);
+ }
+ if(req->hasRole("getusers")){
+ updateUsers();
+ }else{
+ usertab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(usertab),false);
+ }
+ if(req->hasRole("gethosts")){
+ updateHosts();
+ }else{
+ hosttab->setEnabled(false);
+ tab->setTabEnabled(tab->indexOf(hosttab),false);
+ }
+}
+
+void MOverview::updateEvents()
+{
+ MTGetAllEvents gae=req->queryGetAllEvents();
+ if(gae.stage()!=gae.Success){
+ qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
+ return;
+ }
+ QList<MOEvent>evl=gae.getevents();
+ eventmodel->clear();
+ eventmodel->insertColumns(0,6);
+ eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
+ QDateTime now=QDateTime::currentDateTime();
+ for(int i=0,j=0;i<evl.size();i++){
+ QDateTime stime=QDateTime::fromTime_t(evl[i].start());
+ if(stime<now && !showoldevents->isChecked())continue;
+ eventmodel->insertRow(j);
+ eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
+ eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
+ eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
+ eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
+ eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
+ eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
+ eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
+ j++;
+ }
+ eventtable->resizeColumnsToContents();
+ //in case this was called from changing the check state
+ QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showoldevents->isChecked());
+}
+
+void MOverview::closeEvent(QCloseEvent*ce)
+{
+ //make sure session is deleted
+ req->logout();
+ //actually close window
+ QMainWindow::closeEvent(ce);
+}
+
+MOverview::~MOverview()
+{
+ //free requestor
+ req->deleteLater();
+}
+
+void MOverview::relogin()
+{
+ setEnabled(false);
+ if(!req->relogin())
+ QMessageBox::warning(this,tr("Warning"),tr("I was unable to renew the login at the server."));
+ setEnabled(true);
+}
+
+void MOverview::newEvent()
+{
+ MEventEditor ed(this);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::editEvent()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventEditor ed(this,id);
+ ed.exec();
+ updateEvents();
+}
+
+void MOverview::eventSummary()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MEventSummary ed(this,id);
+ ed.exec();
+}
+
+void MOverview::eventCancel()
+{
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ MTGetEvent getev=MTGetEvent::query(id);
+ if(!getev.hasError()){
+ bool ok;
+ MOEvent ev=getev.getevent();
+ QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
+ if(!ok)return;
+ MTCancelEvent cev=MTCancelEvent::query(id,r);
+ if(!cev.hasError())
+ QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
+ else
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
+ }
+}
+
+void MOverview::updateShipping()
+{
+ cartship->clear();
+ cartship->addItem(tr("(No Shipping)"),-1);
+ MTGetAllShipping sh=MTGetAllShipping::query();
+ QList<MOShipping>ship=sh.getshipping();
+ for(int i=0;i<ship.size();i++)
+ cartship->addItem(ship[i].description(),(int)ship[i].id());
+}
+
+void MOverview::updateUsers()
+{
+ MTGetAllUsers au=req->queryGetAllUsers();
+ if(au.hasError())return;
+ QList<MOUser>usl=au.getusers();
+ usermodel->clear();
+ usermodel->insertColumns(0,2);
+ usermodel->insertRows(0,usl.size());
+ usermodel->setHorizontalHeaderLabels(QStringList()<<tr("Login Name")<<tr("Description"));
+ for(int i=0;i<usl.size();i++){
+ usermodel->setData(usermodel->index(i,0),usl[i].name().value());
+ usermodel->setData(usermodel->index(i,1),usl[i].description().value());
+ }
+ usertable->resizeColumnsToContents();
+}
+
+void MOverview::newUser()
+{
+ //get name
+ QString name;
+ while(1){
+ bool ok;
+ name=QInputDialog::getText(this,tr("New User"),tr("Please enter new user name (only letters, digits, and underscore allowed):"),QLineEdit::Normal,name,&ok);
+ if(!ok)
+ return;
+ if(QRegExp("[A-Za-z0-9_\\.,:-]+").exactMatch(name))
+ break;
+ if(QMessageBox::warning(this,tr("Error"),tr("The user name must contain only letters, digits, dots and underscores and must be at least one character long!"),QMessageBox::Retry|QMessageBox::Abort)!=QMessageBox::Retry)
+ return;
+ }
+ //get password
+ QString pwd=QInputDialog::getText(this,tr("Password"),tr("Please enter an initial password for the user:"),QLineEdit::Password);
+ //send request
+ req->queryCreateUser(name,pwd,"");
+ //update display
+ updateUsers();
+}
+
+void MOverview::deleteUser()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //make sure user wants this
+ if(QMessageBox::question(this,tr("Delete User?"),tr("Really delete user '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //get replacement
+ bool ok;
+ QStringList rplc;
+ rplc<<tr("(Nobody)","this is a username for no user, the string must contain '(' to distinguish it from the others");
+ for(int i=0;i<usermodel->rowCount();i++)
+ rplc<<usermodel->data(usermodel->index(i,0)).toString();
+ QString rp=QInputDialog::getItem(this,tr("Delete User"),tr("Select which user will inherit this users database objects:"),rplc,0,false,&ok);
+ if(!ok)return;
+ //delete
+ MTDeleteUser ret=req->queryDeleteUser(name,rp);
+ if(ret.hasError())
+ QMessageBox::warning(this,tr("Error"),tr("Cannot delete user: %1").arg(ret.errorString()));
+ updateUsers();
+}
+
+void MOverview::editUserDescription()
+{
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ QString descr=usermodel->data(usermodel->index(sel.row(),1)).toString();
+ //edit descr
+ bool ok;
+ descr=QInputDialog::getText(this,tr("Edit Description"),tr("Descriptionof user %1:").arg(name),QLineEdit::Normal,descr,&ok);
+ if(ok)
+ req->querySetUserDescription(name,descr);
+ //update
+ updateUsers();
+}
+
+void MOverview::editUserRoles()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MOUser usr(req,name);
+ MCheckList acl=usr.getRoles();
+ MCheckDialog cd(this,acl,"Edit ACL of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setRoles(cd.getCheckList());*/
+}
+
+void MOverview::editUserHosts()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname & descr
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //...
+ MUser usr(req,name);
+ MCheckList acl=usr.getHosts();
+ MCheckDialog cd(this,acl,"Edit hosts of user "+name);
+ if(cd.exec()==QDialog::Accepted)
+ usr.setHosts(cd.getCheckList());*/
+}
+
+void MOverview::setMyPassword()
+{
+ MPasswordChange pc(this);
+ if(pc.exec()==QDialog::Accepted){
+ MTChangeMyPassword cmp=MTChangeMyPassword::query(pc.oldPassword(),pc.newPassword());
+ if(cmp.hasError())
+ QMessageBox::warning(this,tr("Warning"),tr("Error setting password: %1").arg(cmp.errorString()));
+ }
+}
+void MOverview::setUserPassword()
+{/*TODO
+ //get selection
+ QModelIndex sel=usertable->currentIndex();
+ if(!sel.isValid())return;
+ //get uname
+ QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+ //get new password
+ MPasswordChange pc(this,name);
+ if(pc.exec()!=QDialog::Accepted)return;
+ QString p=pc.newPassword();
+ if(p==""){
+ QMessageBox::warning(this,tr("Warning"),tr("The password must be non-empty and both lines must match"));
+ return;
+ }
+ //...
+ MUser usr(req,name);
+ usr.changePassword(p);*/
+}
+
+void MOverview::updateHosts()
+{/*TODO
+ bool foundThis=false;
+ QString thisHost=req->hostName();
+ QList<MHost>hsl=req->getAllHosts();
+ hostmodel->clear();
+ hostmodel->insertColumns(0,2);
+ hostmodel->insertRows(0,hsl.size());
+ hostmodel->setHorizontalHeaderLabels(QStringList()<<tr("Host Name")<<tr("Host Key"));
+ for(int i=0;i<hsl.size();i++){
+ hostmodel->setData(hostmodel->index(i,0),hsl[i].hostId());
+ hostmodel->setData(hostmodel->index(i,1),hsl[i].hostKey());
+ if(thisHost==hsl[i].hostId())
+ foundThis=true;
+ }
+ hosttable->resizeColumnsToContents();
+ thishostbutton->setEnabled(!foundThis && req->hasRole("addhost"));*/
+}
+
+void MOverview::newHost()
+{/*TODO
+ //get Host Name
+ QString hname;
+ do{
+ bool ok;
+ hname=QInputDialog::getText(this,tr("Create New Host"),tr("Please enter a host name:"),QLineEdit::Normal,hname,&ok);
+ if(!ok)return;
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname))continue;
+ }while(false);
+ //create it
+ MHost hst(req,hname);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The key of this new host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.create();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::addThisHost()
+{/*TODO
+ MHost hst(req,req->hostName(),QSettings().value("hostkey").toString());
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::deleteHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Delete this Host?"),tr("Really delete host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //delete it
+ MHost(req,name).deleteHost();
+ updateHosts();*/
+}
+
+void MOverview::changeHostKey()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ //ask
+ if(QMessageBox::question(this,tr("Change Host Key?"),tr("Really change the key of host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return;
+ //change it
+ MHost hst(req,name);
+ int e=hst.newKey();
+ if(e<128){
+ if(QMessageBox::warning(this,tr("Warning"),tr("The new key of this host could only be generated with %n bits entropy. Store anyway?","",e).arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes)
+ return;
+ }
+ hst.save();
+ //update
+ updateHosts();*/
+}
+
+void MOverview::importHost()
+{/*TODO
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptOpen);
+ fdlg.setFileMode(QFileDialog::ExistingFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::ReadOnly)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ //read content (max: 10k to limit potential damage)
+ QStringList fc=QString::fromAscii(fd.read(10240)).split("\n",QString::SkipEmptyParts);
+ fd.close();
+ //check content
+ if(fc.size()<3){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ if(fc[0].trimmed()!="MagicSmokeHostKey"){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file."));
+ return;
+ }
+ QString hname=fc[1].trimmed();
+ if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name."));
+ return;
+ }
+ QString key=fc[2].trimmed();
+ if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){
+ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key."));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ if(chk!=fc[3].trimmed()){
+ QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file."));
+ return;
+ }
+ //save
+ MHost hst(req,hname,key);
+ hst.create();
+ updateHosts();*/
+}
+
+void MOverview::exportHost()
+{/*TODO
+ //get selection
+ QModelIndex sel=hosttable->currentIndex();
+ if(!sel.isValid())return;
+ //get hname
+ QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString();
+ QString key=hostmodel->data(hostmodel->index(sel.row(),1)).toString();
+ if(name[0]=='_' || key==""){
+ QMessageBox::warning(this,tr("Warning"),tr("This host cannot be exported."));
+ return;
+ }
+ //save
+ QStringList fn;
+ QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)");
+ fdlg.setDefaultSuffix("mshk");
+ fdlg.setAcceptMode(QFileDialog::AcceptSave);
+ fdlg.setFileMode(QFileDialog::AnyFile);
+ if(!fdlg.exec())return;
+ fn=fdlg.selectedFiles();
+ if(fn.size()!=1)return;
+ QFile fd(fn[0]);
+ if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString()));
+ return;
+ }
+ QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex();
+ QString out="MagicSmokeHostKey\n"+name+"\n"+key+"\n"+chk;
+ fd.write(out.toAscii());
+ fd.close();*/
+}
+
+
+void MOverview::initCart()
+{
+ //clear cart
+ cartmodel->clear();
+ cartmodel->setHorizontalHeaderLabels(QStringList()<<tr("Amount")<<tr("Title")<<tr("Start Time"));
+ //clear customer
+ customer=MCustomer();
+ cartcustomer->setText("");
+ //clear address/comment
+ cartaddr->setPlainText("");
+ cartcomment->setPlainText("");
+ //clear shipping
+ cartship->setCurrentIndex(0);
+}
+
+void MOverview::setCustomer()
+{/*TODO
+ MCustomerListDialog mcl(req,this,true,customer.customerID());
+ if(mcl.exec()!=QDialog::Accepted)return;
+ customer=mcl.getCustomer();
+ cartcustomer->setText(customer.getNameAddress());*/
+}
+
+static const int CART_TICKET=1;
+static const int CART_VOUCHER=2;
+
+static const int CART_IDROLE=Qt::UserRole;//ticket id
+static const int CART_PRICEROLE=Qt::UserRole;//voucher price
+static const int CART_VALUEROLE=Qt::UserRole+1;//voucher value
+static const int CART_TYPEROLE=Qt::UserRole+2;//which is it? ticket or voucher?
+
+void MOverview::cartAddTicket()
+{
+ //create ticket selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Event to order Ticket"));
+ QTableView*tv;
+ QHBoxLayout*hl;
+ QVBoxLayout*vl;
+ dlg.setLayout(vl=new QVBoxLayout);
+ vl->addWidget(tv=new QTableView,10);
+ tv->setModel(eventmodel);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->resizeColumnsToContents();
+ vl->addSpacing(15);
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Select")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ connect(tv,SIGNAL(doubleClicked(const QModelIndex&)),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ QModelIndex idx=tv->currentIndex();
+ if(!idx.isValid())return;
+ int id=eventmodel->data(eventmodel->index(idx.row(),0),Qt::UserRole).toInt();
+ if(id<0)return;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(idx.row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(idx.row(),0)));
+ carttable->resizeColumnsToContents();
+ }
+}
+
+void MOverview::eventOrderTicket()
+{
+ //get selected event
+ int id;
+ QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
+ if(ilst.size()<1)return;
+ QModelIndex idx=eventmodel->index(ilst[0].row(),0);
+ id=eventmodel->data(idx,Qt::UserRole).toInt();
+ if(id<0)return;
+ //activate order tab
+ tab->setCurrentWidget(carttab);
+ //insert event into table
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(ilst[0].row(),1)));
+ cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(ilst[0].row(),0)));
+ carttable->resizeColumnsToContents();
+}
+
+void MOverview::cartAddVoucher()
+{/*TODO
+ //create voucher selection dialog
+ QDialog dlg;
+ dlg.setWindowTitle(tr("Select Voucher"));
+ QComboBox*cp,*cv;
+ QHBoxLayout*hl;
+ QGridLayout*gl;
+ QStandardItemModel mdl;
+ QRegExpValidator regv(priceRegExp(),this);
+ QList<int>prc=req->getVoucherPrices();
+ mdl.insertRows(0,prc.size());
+ mdl.insertColumns(0,1);
+ for(int i=0;i<prc.size();i++)mdl.setData(mdl.index(i,0),cent2str(prc[i]));
+ dlg.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Select voucher price and value:")),0,0,1,2);
+ if(req->hasRole("_anypricevoucher")){
+ gl->addWidget(new QLabel(tr("Price:")),1,0);
+ gl->addWidget(cp=new QComboBox,1,1);
+ cp->setModel(&mdl);
+ cp->setEditable(true);
+ cp->setValidator(®v);
+ }else cp=0;
+ gl->addWidget(new QLabel(tr("Value:")),2,0);
+ gl->addWidget(cv=new QComboBox,2,1);
+ cv->setModel(&mdl);
+ cv->setEditable(req->hasRole("_anyvoucher"));
+ cv->setValidator(®v);
+ gl->setRowMinimumHeight(3,15);
+ gl->setColumnStretch(0,0);
+ gl->setColumnStretch(1,1);
+ gl->setRowStretch(3,1);
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&dlg,SLOT(reject()));
+ //wait for it
+ if(dlg.exec()==QDialog::Accepted){
+ //get selection
+ int price,value;
+ value=str2cent(cv->currentText());
+ if(req->hasRole("_anypricevoucher") && cp)
+ price=str2cent(cp->currentText());
+ else
+ price=value;
+ //copy to cart
+ int cr=cartmodel->rowCount();
+ cartmodel->insertRows(cr,1);
+ cartmodel->setData(cartmodel->index(cr,0),1);
+ cartmodel->setData(cartmodel->index(cr,0),price,CART_PRICEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),value,CART_VALUEROLE);
+ cartmodel->setData(cartmodel->index(cr,0),CART_VOUCHER,CART_TYPEROLE);
+ cartmodel->setData(cartmodel->index(cr,1),tr("Voucher (price: %1, value %2)").arg(cent2str(price)).arg(cent2str(value)));
+ carttable->resizeColumnsToContents();
+ }*/
+}
+
+void MOverview::cartRemoveItem()
+{
+ //get selection
+ QModelIndex idx=carttable->currentIndex();
+ if(!idx.isValid())return;
+ //remove row
+ cartmodel->removeRow(idx.row());
+}
+
+void MOverview::cartOrder()
+{
+ //sanity checks
+ if(cartmodel->rowCount()<1){
+ QMessageBox::warning(this,tr("Error"),tr("There is nothing in the order. Ignoring it."));
+ return;
+ }
+ if(!customer.isValid()){
+ QMessageBox::warning(this,tr("Error"),tr("Please chose a customer first!"));
+ return;
+ }
+ ///////////////
+ //create order
+ QDomDocument doc;
+ QDomElement root=doc.createElement("Order");
+ root.setAttribute("customer",customer.id());
+ //is there a delivery address
+ QString s=cartaddr->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement da=doc.createElement("DeliveryAddress");
+ da.appendChild(doc.createTextNode(s));
+ root.appendChild(da);
+ }
+ //is there a comment?
+ s=cartcomment->toPlainText().trimmed();
+ if(s!=""){
+ QDomElement cc=doc.createElement("Comment");
+ cc.appendChild(doc.createTextNode(s));
+ root.appendChild(cc);
+ }
+ //scan tickets & scan vouchers
+ for(int i=0;i<cartmodel->rowCount();i++){
+ QModelIndex idx=cartmodel->index(i,0);
+ int tp=cartmodel->data(idx,CART_TYPEROLE).toInt();
+ if(tp==CART_TICKET){
+ int amt=cartmodel->data(idx).toInt();
+ int evid=cartmodel->data(idx,CART_IDROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Ticket");
+ tc.setAttribute("event",evid);
+ root.appendChild(tc);
+ }
+ }else
+ if(tp==CART_VOUCHER){
+ int amt=cartmodel->data(idx).toInt();
+ int price=cartmodel->data(idx,CART_PRICEROLE).toInt();
+ int value=cartmodel->data(idx,CART_VALUEROLE).toInt();
+ for(int j=0;j<amt;j++){
+ QDomElement tc=doc.createElement("Voucher");
+ tc.setAttribute("price",price);
+ tc.setAttribute("value",value);
+ root.appendChild(tc);
+ }
+
+ }
+ }
+ //set shipping info
+ if(cartship->currentIndex()>0){
+ QDomElement si=doc.createElement("Shipping");
+ si.setAttribute("type",cartship->itemData(cartship->currentIndex()).toInt());
+ root.appendChild(si);
+ }
+ //finalize
+ doc.appendChild(root);
+ //send
+ /*TODO
+ if(req->request("checkorder",doc.toByteArray())==false){
+ QMessageBox::warning(this,tr("Error"),tr("The request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Error"),tr("A problem occurred during the order: %1").arg(qApp->translate("php::",req->responseBody())));
+ return;
+ }
+ //parse result
+ QDomDocument rdoc;
+ rdoc.setContent(req->responseBody());
+ //display order and give user chance to actually order it
+ MOrderWindow *ow=new MOrderWindow(this,req,MOrder(req,rdoc.documentElement()));
+ ow->show();
+ //empty the cart
+ initCart();*/
+}
+
+void MOverview::customerMgmt()
+{/*TODO
+ MCustomerListDialog mcl(req,this);
+ mcl.exec();*/
+}
+
+void MOverview::editShipping()
+{/*TODO
+ MShippingEditor se(req,this);
+ se.exec();
+ updateShipping();*/
+}
+
+void MOverview::tabChanged()
+{/*TODO
+ QWidget*w=tab->currentWidget();
+ if(w==entrancetab){
+ //fill combobox from eventmodel
+ int ci=entranceevent->currentIndex();
+ int cev=-1;
+ if(ci>=0)cev=entranceevent->itemData(ci).toInt();
+ ci=-1;
+ entranceevent->clear();
+ for(int i=0;i<eventmodel->rowCount();i++){
+ QString ev=eventmodel->data(eventmodel->index(i,0)).toString()+" "+
+ eventmodel->data(eventmodel->index(i,1)).toString();
+ int eid=eventmodel->data(eventmodel->index(i,0),Qt::UserRole).toInt();
+ entranceevent->addItem(ev,eid);
+ if(eid==cev)ci=i;
+ }
+ if(ci>=0)entranceevent->setCurrentIndex(ci);
+ //set focus on scanner
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");
+ }*/
+}
+
+void MOverview::entranceValidate()
+{/*TODO
+ //get event ID
+ int ci=entranceevent->currentIndex();
+ if(ci<0)return;
+ int cev=entranceevent->itemData(ci).toInt();
+ //check content
+ QString tid=entrancescan->text().trimmed();
+ entrancescan->setText("");
+ //avoid spurious events
+ if(tid=="")return;
+ //avoid double scans
+ QDateTime now=QDateTime::currentDateTime();
+ if(tid==lastbarcode && lastbcscan.addSecs(20)>=now)
+ return;
+ lastbarcode=tid;
+ lastbcscan=now;
+ //reset display
+ QPalette pal=entrancelabel->palette();
+ QPalette::ColorRole rl=QPalette::Window;
+ pal.setColor(rl,Qt::lightGray);
+ entrancelabel->setPalette(pal);
+ entrancelabel->setText(tr("searching...","entrance control"));
+ //ask the server
+ MTicket tick(req,tid);
+ //decide what to do
+ if(!tick.isValid()){
+ entrancelabel->setText(tr("Ticket \"%1\" Not Valid").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.eventID()!=cev){
+ entrancelabel->setText(tr("Ticket \"%1\" is not for this event.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.status()==MTicket::Used){
+ entrancelabel->setText(tr("Ticket \"%1\" has already been used").arg(tid));
+ pal.setColor(rl,Qt::magenta);
+ }else
+ if(tick.status()!=MTicket::Bought){
+ entrancelabel->setText(tr("Ticket \"%1\" has not been bought.").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else
+ if(tick.paymentStatus()==MTicket::PSOk){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedRefund){
+ entrancelabel->setText(tr("Ticket \"%1\" Ok; the Order has a refund").arg(tid));
+ pal.setColor(rl,Qt::green);
+ tick.markUsed();
+ }else
+ if(tick.paymentStatus()==MTicket::PSNeedPayment){
+ entrancelabel->setText(tr("Ticket \"%1\" is not paid for!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }else{
+ entrancelabel->setText(tr("Ticket \"%1\" cannot be accepted, please check the order!").arg(tid));
+ pal.setColor(rl,Qt::red);
+ }
+
+ entrancelabel->setPalette(pal);
+ entrancescan->setFocus(Qt::OtherFocusReason);
+ entrancescan->setText("");*/
+}
+
+//helper: finds out whether an order should be printed.
+static inline bool candoUpdateOrders(int omode,const MOrder&ord)
+{
+ if(omode==ORDERALL)return true;
+ if((omode&ORDERPAY)!=0 && ord.needsPayment())return true;
+ if((omode&ORDERREFUND)!=0 && ord.needsRefund())return true;
+ if((omode&ORDERUNSENT)!=0 && !ord.isSent())return true;
+ if((omode&ORDERRESERVE)!=0 && ord.isReservation())return true;
+ return false;
+}
+
+void MOverview::updateOrders()
+{/*TODO
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ int omode=ordermode->itemData(ordermode->currentIndex()).toInt();
+ if(omode==ORDERNONE)return;
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ if(!candoUpdateOrders(omode,orders[i]))continue;
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ int cid=orders[i].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ cl++;
+ }
+ ordertable->resizeColumnsToContents();*/
+}
+
+void MOverview::orderDetails()
+{/*TODO
+ //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::orderByTicket()
+{/*TODO
+ //get selected order
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Enter Ticket"),tr("Please enter the ID of one of the tickets of the order you seek:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ //request it
+ if(!req->request("orderbyticket",tid.toUtf8())){
+ QMessageBox::warning(this,tr("Warning"),tr("Unable to query server."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),qApp->translate("php::",req->responseBody()));
+ return;
+ }
+ int id=req->responseBody().trimmed().toInt(&ok);
+ if(!ok || id<0){
+ QMessageBox::warning(this,tr("Warning"),tr("Server returned an invalid order ID."));
+ return;
+ }
+ //open order window
+ MOrderWindow *om=new MOrderWindow(this,req,MOrder(req,id));
+ om->setAttribute(Qt::WA_DeleteOnClose);
+ om->show();*/
+}
+
+void MOverview::orderByEvent()
+{/*TODO
+ //display selection dialog
+ QDialog d(this);
+ d.setWindowTitle(tr("Select Event"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ QTableView*tv;
+ vl->addWidget(tv=new QTableView,10);
+ tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tv->setModel(eventmodel);
+ tv->resizeColumnsToContents();
+ vl->addLayout(hl=new QHBoxLayout,0);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Ok")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")),0);
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ //wait for user
+ if(d.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ QModelIndexList ilst=tv->selectionModel()->selectedIndexes();
+ if(ilst.size()<1){
+ qDebug("nothing selected");
+ return;
+ }
+ //get events
+ QList<int>eventids;
+ for(int i=0;i<ilst.size();i++){
+ int eid=eventmodel->data(eventmodel->index(ilst[i].row(),0),Qt::UserRole).toInt();
+ if(!eventids.contains(eid))eventids.append(eid);
+ }
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getOrdersByEvents(eventids);
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ for(int cl=0;cl<orders.size();cl++){
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[cl].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[cl].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[cl].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[cl].amountPaidString());
+ int cid=orders[cl].customerID();
+ //TODO: make this more effective:
+ for(int j=0;j<cust.size();j++)
+ if(cust[j].customerID()==cid)
+ ordermodel->setData(ordermodel->index(cl,3),cust[j].name());
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByCustomer()
+{/*TODO
+ //display selection dialog
+ MCustomerListDialog mcl(req,this,true);
+ //wait for user
+ if(mcl.exec()!=QDialog::Accepted)
+ return;
+ //get selection
+ MCustomer cst=mcl.getCustomer();
+ if(!cst.isValid()){
+ qDebug("nothing selected");
+ return;
+ }
+ qint64 custid=cst.customerID();
+ //request data and display
+ //TODO: unify this part with updateOrders
+ ordermodel->clear();
+ ordermodel->setHorizontalHeaderLabels(QStringList()<<tr("Status")<<tr("Total")<<tr("Paid")<<tr("Customer"));
+ QList<MOrder> orders=req->getAllOrders();
+ if(orders.size()==0)return;
+ QList<MCustomer> cust=req->getAllCustomers();
+ int cl=0;
+ for(int i=0;i<orders.size();i++){
+ //filter
+ if(orders[i].customerID()!=custid)continue;
+ //put into table
+ ordermodel->insertRow(cl);
+ ordermodel->setHeaderData(cl,Qt::Vertical,orders[i].orderID());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderStatusString());
+ ordermodel->setData(ordermodel->index(cl,0),orders[i].orderID(),Qt::UserRole);
+ ordermodel->setData(ordermodel->index(cl,1),orders[i].totalPriceString());
+ ordermodel->setData(ordermodel->index(cl,2),orders[i].amountPaidString());
+ ordermodel->setData(ordermodel->index(cl,3),cst.name());
+ //count up
+ cl++;
+ }
+ ordermode->setCurrentIndex(ordermode->count()-1);*/
+}
+
+void MOverview::orderByOrder()
+{/*TODO
+ //ask for OrderID
+ bool ok;
+ int oid=QInputDialog::getInteger(this,tr("Enter Order ID"),tr("Please enter the ID of the order you want to display:"),0,0,2147483647,1,&ok);
+ if(!ok)return;
+ //display
+ MOrder ord(req,oid);
+ if(!ord.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This order does not exist."));
+ return;
+ }
+ MOrderWindow *ow=new MOrderWindow(this,req,ord);
+ ow->show();*/
+}
+
+void MOverview::ticketReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Ticket"),tr("Please enter the ticket ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MTicket tick(req,tid);
+ if(!tick.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid ticket."));
+ return;
+ }
+ //check state
+ if(tick.status()!=MTicket::Bought && tick.status()!=MTicket::Reserved){
+ QMessageBox::warning(this,tr("Warning"),tr("This ticket cannot be returned, it has already been used or is in the wrong state."));
+ return;
+ }
+ //submit
+ QString r=tick.ticketReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::voucherReturn()
+{/*TODO
+ //get ticket
+ bool ok;
+ QString tid=QInputDialog::getText(this,tr("Return Voucher"),tr("Please enter the voucher ID to return:"),QLineEdit::Normal,"",&ok);
+ if(!ok || tid=="")return;
+ MVoucher vouc(req,tid);
+ if(!vouc.isValid()){
+ QMessageBox::warning(this,tr("Warning"),tr("This is not a valid voucher."));
+ return;
+ }
+ //check state
+ if(vouc.isUsed()){
+ QMessageBox::warning(this,tr("Warning"),tr("This voucher cannot be returned, it has already been used."));
+ return;
+ }
+ //submit
+ QString r=vouc.voucherReturn();
+ if(r!="")QMessageBox::warning(this,tr("Warning"),trUtf8(r.toUtf8()));*/
+}
+
+void MOverview::deductVoucher()
+{/*TODO
+ //get voucher ID and amount
+ QDialog d;
+ d.setWindowTitle(tr("Deduct from Voucher"));
+ QGridLayout *gl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Using a voucher to pay outside the system.")),0,0,1,2);
+
+ QLineEdit*vid;
+ MCentSpinBox*cent;
+ gl->addWidget(new QLabel(tr("Amount to deduct:")),1,0);
+ gl->addWidget(cent=new MCentSpinBox,1,1);
+ gl->addWidget(new QLabel(tr("Voucher ID:")),2,0);
+ gl->addWidget(vid=new QLineEdit,2,1);
+
+ gl->setRowMinimumHeight(3,15);
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,4,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ if(vid->text().trimmed()=="" || cent->value()<=0)return;
+ //query server
+ QByteArray r=vid->text().trimmed().toAscii()+"\n"+QString::number(cent->value()).toAscii();
+ if(!req->request("usevoucheroutside",r)){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ if(req->responseStatus()!=MSInterface::Ok){
+ QMessageBox::warning(this,tr("Warning"),tr("Request failed."));
+ return;
+ }
+ QStringList sl=QString::fromAscii(req->responseBody().trimmed()).split("\n");
+ int tak=-1,rem=-1;
+ if(sl.size()>0)tak=sl[0].trimmed().toInt();
+ if(sl.size()>1)rem=sl[1].trimmed().toInt();
+ QMessageBox::information(this,tr("Deducted from Voucher"),tr("Value taken from voucher: %1\nValue remaining on voucher: %2").arg(cent2str(tak)).arg(cent2str(rem)));*/
+}
+
+void MOverview::refreshData()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ if(set.value("refreshEvents",false).toBool() && req->hasRole("geteventlist"))
+ updateEvents();
+ if(set.value("refreshUsers",false).toBool() && req->hasRole("getusers"))
+ updateUsers();
+ if(set.value("refreshHosts",false).toBool() && req->hasRole("gethosts"))
+ updateHosts();
+ if(set.value("refreshShipping",false).toBool() && req->hasRole("getshipping"))
+ updateShipping();
+}
+
+void MOverview::setRefresh()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //dialog
+ QDialog d;
+ d.setWindowTitle(tr("Refresh Settings"));
+ QVBoxLayout*vl;
+ QHBoxLayout*hl;
+ d.setLayout(vl=new QVBoxLayout);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addWidget(new QLabel(tr("Refresh Rate (minutes):")),1);
+ QSpinBox*rate;
+ hl->addWidget(rate=new QSpinBox,0);
+ rate->setRange(1,999);
+ rate->setValue(set.value("refresh",300).toInt()/60);
+ QCheckBox *rev,*rus,*rho,*rsh;
+ vl->addWidget(rev=new QCheckBox(tr("refresh &event list")));
+ rev->setChecked(set.value("refreshEvents",false).toBool());
+ vl->addWidget(rus=new QCheckBox(tr("refresh &user list")));
+ rus->setChecked(set.value("refreshUsers",false).toBool());
+ vl->addWidget(rho=new QCheckBox(tr("refresh &host list")));
+ rho->setChecked(set.value("refreshHosts",false).toBool());
+ vl->addWidget(rsh=new QCheckBox(tr("refresh &shipping list")));
+ rho->setChecked(set.value("refreshShipping",false).toBool());
+ vl->addSpacing(15);
+ vl->addStretch(10);
+ vl->addLayout(hl=new QHBoxLayout);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ set.setValue("refreshEvents",rev->isChecked());
+ set.setValue("refreshUsers",rus->isChecked());
+ set.setValue("refreshHosts",rho->isChecked());
+ set.setValue("refreshShipping",rsh->isChecked());
+ set.setValue("refresh",rate->value()*60);
+ //reset timer
+ rtimer.stop();
+ rtimer.setInterval(rate->value()*60000);
+ rtimer.start();
+}
+
+void MOverview::webSettings(bool showdlg)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ //get settings
+ MSInterface::LogLevel lvl=MSInterface::LogLevel(set.value("webloglevel", MSInterface::LogOnError).toInt());
+ int timeout=set.value("webtimeout",30).toInt();
+ //dialog
+ if(showdlg){
+ QDialog d;
+ d.setWindowTitle(tr("Server Access Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ d.setLayout(gl=new QGridLayout);
+ gl->addWidget(new QLabel(tr("Request Timeout (seconds):")),0,0);
+ QSpinBox*tmout;
+ gl->addWidget(tmout=new QSpinBox,0,1);
+ tmout->setRange(10,999);
+ tmout->setValue(timeout);
+ QComboBox *log;
+ gl->addWidget(new QLabel(tr("Log Level:")),1,0);
+ gl->addWidget(log=new QComboBox,1,1);
+ log->addItem(tr("Minimal Logging"),MSInterface::LogMinimal);
+ log->addItem(tr("Log Details on Error"),MSInterface::LogOnError);
+ log->addItem(tr("Always Log Details"),MSInterface::LogDetailed);
+ switch(lvl){
+ case MSInterface::LogMinimal:log->setCurrentIndex(0);break;
+ case MSInterface::LogOnError:log->setCurrentIndex(1);break;
+ case MSInterface::LogDetailed:log->setCurrentIndex(2);break;
+ }
+ gl->setRowMinimumHeight(2,15);
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),&d,SLOT(reject()));
+ if(d.exec()!=QDialog::Accepted)return;
+ //write settings
+ lvl=MSInterface::LogLevel(log->itemData(log->currentIndex()).toInt());
+ timeout=tmout->value();
+ set.setValue("webloglevel",lvl);
+ set.setValue("webtimeout",timeout);
+ }
+ //reset webrequest
+ req->setLogLevel(lvl);
+ req->setWebTimeout(timeout*1000);
+}
+
+void MOverview::doBackup()
+{
+ baktimer.stop();
+ //sanity check
+ if(!req->hasRight(req->RBackup))return;
+ //get settings
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ //get data
+ MTBackup bc;
+ bc=MTBackup::query();
+ if(bc.stage()!=bc.Success){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup failed with error (%2): %1").arg(bc.errorString()).arg(bc.errorType()));
+ return;
+ }
+ if(bc.getbackup().isNull()||bc.getbackup().value().isEmpty()){
+ QMessageBox::warning(this,tr("Warning"),tr("Backup returned empty."));
+ return;
+ }
+ //rotate files
+ QFile(path+"."+QString::number(gens)).remove();
+ for(int i=gens-1;i>=0;i--){
+ if(i)
+ QFile(path+"."+QString::number(i)).rename(path+"."+QString::number(i+1));
+ else
+ QFile(path).rename(path+".1");
+ }
+ //store new data
+ QFile fd(path);
+ if(fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+ fd.write(bc.getbackup().value().toAscii());
+ fd.close();
+ set.setValue("backuptime",QDateTime::currentDateTime().toTime_t());
+ QMessageBox::information(this,tr("Backup"),tr("The backup was successful."));
+ int tm=set.value("backupinterval",0).toInt()*86400000;
+ if(tm)baktimer.start(tm);
+ }else
+ QMessageBox::warning(this,tr("Warning"),tr("Cannot create backup file."));
+}
+
+void MOverview::backupSettings()
+{
+ //show dialog
+ MBackupDialog d(this,profilekey);
+ d.exec();
+ //reset timer
+ int btm=QSettings().value("profiles/"+profilekey+"/backupinterval",0).toInt()*86400;
+ if(btm){
+ //adjust for last backup time
+ int iv=QDateTime::currentDateTime().toTime_t() - QSettings().value("profiles/"+profilekey+"/backuptime",0).toInt();
+ if(iv>=btm)btm=0;
+ else btm-=iv;
+ //start timer
+ baktimer.start(btm*1000);
+ }
+}
+
+void MOverview::moneylogVoucher()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("Voucher ID"),tr("Please enter voucher ID to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"voucher\n"+vid).exec();*/
+}
+
+void MOverview::moneylogUser()
+{/*TODO
+ QString vid=QInputDialog::getText(this,tr("User"),tr("Please enter login name of user to show log:"));
+ if(vid!="")
+ MMoneyLog(this,req,"user\n"+vid).exec();*/
+}
+
+
+/**********************************************/
+
+MBackupDialog::MBackupDialog(QWidget*par,QString pk)
+ :QDialog(par),profilekey(pk)
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ QString path=set.value("backupfile",req->dataDir()+"/backup").toString();
+ int gens=set.value("backupgenerations",3).toInt();
+ int tm=set.value("backupinterval",0).toInt();
+ //dialog
+ setWindowTitle(tr("Backup Settings"));
+ QGridLayout*gl;
+ QHBoxLayout*hl;
+ setLayout(gl=new QGridLayout);
+ QPushButton*p;
+ gl->addWidget(new QLabel(tr("Backup File:")),0,0);
+ gl->addWidget(lpath=new QLineEdit(path),0,1);
+ gl->addWidget(p=new QPushButton(tr("...")),0,2);
+ connect(p,SIGNAL(clicked()),this,SLOT(getpath()));
+
+ gl->addWidget(new QLabel(tr("Generations to keep:")),1,0);
+ gl->addWidget(gener=new QSpinBox,1,1,1,2);
+ gener->setRange(1,16);
+ gener->setValue(gens);
+
+ gl->addWidget(new QLabel(tr("Automatic Backup:")),2,0);
+ gl->addWidget(autob=new QCheckBox,2,1,1,2);
+ autob->setChecked(tm>0);
+
+ gl->addWidget(new QLabel(tr("Interval in days:")),3,0);
+ gl->addWidget(interv=new QSpinBox,3,1,1,2);
+ interv->setRange(1,24);
+ interv->setValue(tm>0?tm:1);
+
+ gl->setRowMinimumHeight(4,15);
+ gl->addLayout(hl=new QHBoxLayout,5,0,1,3);
+ hl->addStretch(10);
+ hl->addWidget(p=new QPushButton(tr("&OK")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ connect(p,SIGNAL(clicked()),this,SLOT(save()));
+ hl->addWidget(p=new QPushButton(tr("&Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+void MBackupDialog::getpath()
+{
+ QString path=QFileDialog::getSaveFileName(this,tr("Backup File"),lpath->text());
+ if(path!="")lpath->setText(path);
+}
+
+void MBackupDialog::save()
+{
+ QSettings set;
+ set.beginGroup("profiles/"+profilekey);
+ set.setValue("backupfile",lpath->text());
+ set.setValue("backupgenerations",gener->value());
+ set.setValue("backupinterval",autob->isChecked()?interv->value():0);
+}
+/**********************************************/
+
+MPasswordChange::MPasswordChange(QWidget*par,QString user)
+ :QDialog(par)
+{
+ oldpwd=newpwd1=newpwd2=0;
+ if(user=="")
+ setWindowTitle(tr("Change my password"));
+ else
+ setWindowTitle(tr("Reset password of user \"%1\"").arg(user));
+ QGridLayout*gl;
+ setLayout(gl=new QGridLayout);
+ if(user==""){
+ gl->addWidget(new QLabel(tr("Old Password:")),0,0);
+ gl->addWidget(oldpwd=new QLineEdit,0,1);
+ oldpwd->setEchoMode(QLineEdit::Password);
+ }
+ gl->addWidget(new QLabel(tr("New Password:")),1,0);
+ gl->addWidget(newpwd1=new QLineEdit,1,1);
+ newpwd1->setEchoMode(QLineEdit::Password);
+ gl->addWidget(new QLabel(tr("Repeat Password:")),2,0);
+ gl->addWidget(newpwd2=new QLineEdit,2,1);
+ newpwd2->setEchoMode(QLineEdit::Password);
+
+ QHBoxLayout*hl;
+ gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+ hl->addStretch(10);
+ QPushButton*p;
+ hl->addWidget(p=new QPushButton(tr("Set Password")));
+ connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+ hl->addWidget(p=new QPushButton(tr("Cancel")));
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+QString MPasswordChange::oldPassword()
+{
+ if(oldpwd)return oldpwd->text();
+ return "";
+}
+
+QString MPasswordChange::newPassword()
+{
+ if(newpwd1==0 || newpwd2==0)return "";
+ if(newpwd1->text()!=newpwd2->text())return "";
+ return newpwd1->text();
+}
+
+
+/********************************************************************************/
+
+MCartTableDelegate::MCartTableDelegate(QObject*p)
+ :QItemDelegate(p)
+{
+}
+
+QWidget *MCartTableDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &/* option */,
+ const QModelIndex & index ) const
+{
+ //base class
+ if(index.column()!=0)return 0;
+
+ QSpinBox *editor = new QSpinBox(parent);
+ editor->setRange(1,1000);
+ editor->installEventFilter(const_cast<MCartTableDelegate*>(this));
+ return editor;
+}
+
+void MCartTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0)
+ ((QSpinBox*)editor)->setValue(index.model()->data(index).toInt());
+}
+
+void MCartTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ //name field
+ int c=index.column();
+ if(c==0){
+ int newval=((QSpinBox*)editor)->value();
+ model->setData(index,newval);
+ }
+}
--- /dev/null
+//
+// C++ Interface: overview
+//
+// Description:
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2007
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef MAGICSMOKE_OVERVIEW_H
+#define MAGICSMOKE_OVERVIEW_H
+
+#include <QDateTime>
+#include <QDialog>
+#include <QItemDelegate>
+#include <QMainWindow>
+#include <QTimer>
+
+#include "customer.h"
+
+class QAction;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSpinBox;
+class QStandardItemModel;
+class QTabWidget;
+class QTableView;
+
+class MSInterface;
+
+/**Main Overview Window*/
+class MOverview:public QMainWindow
+{
+ Q_OBJECT
+ public:
+ /**construct the window with web-request/session handler and QSettings-key for current profile*/
+ MOverview(QString);
+ ~MOverview();
+ protected:
+ /**handle closing the window: close the session too*/
+ void closeEvent(QCloseEvent*);
+ private slots:
+ /**try to log in again*/
+ void relogin();
+
+ /**create a new event*/
+ void newEvent();
+ /**edit existing event*/
+ void editEvent();
+ /**update list of events*/
+ void updateEvents();
+ /**order ticket from event tab*/
+ void eventOrderTicket();
+ /**open event summary*/
+ void eventSummary();
+ /**cancel the event*/
+ void eventCancel();
+
+ /**update shipping info*/
+ void updateShipping();
+
+ /**get all orders, update list*/
+ void updateOrders();
+ /**open order detail window*/
+ void orderDetails();
+
+ /**update list of users*/
+ void updateUsers();
+ /**create new user*/
+ void newUser();
+ /**delete selected user*/
+ void deleteUser();
+ /**set users description*/
+ void editUserDescription();
+ /**set users roles*/
+ void editUserRoles();
+ /**set users hosts*/
+ void editUserHosts();
+ /**set my own password*/
+ void setMyPassword();
+ /**set a users password*/
+ void setUserPassword();
+
+ /**update list of hosts*/
+ void updateHosts();
+ /**create new host*/
+ void newHost();
+ /**create a database entry for this host*/
+ void addThisHost();
+ /**delete a host*/
+ void deleteHost();
+ /**generate a new key*/
+ void changeHostKey();
+ /**import host from file*/
+ void importHost();
+ /**export host to file*/
+ void exportHost();
+
+ /**decide what customer to use*/
+ void setCustomer();
+ /**initialize cart tab*/
+ void initCart();
+ /**add a ticket to the cart*/
+ void cartAddTicket();
+ /**add a voucher to the cart*/
+ void cartAddVoucher();
+ /**remove item from the cart*/
+ void cartRemoveItem();
+ /**check the order on the server*/
+ void cartOrder();
+
+ /**manage customers*/
+ void customerMgmt();
+
+ /**edit shipping options*/
+ void editShipping();
+
+ /**generic check which tab is active*/
+ void tabChanged();
+
+ /**react on entry in Entrance tab*/
+ void entranceValidate();
+
+ /**return a ticket*/
+ void ticketReturn();
+ /**return a voucher*/
+ void voucherReturn();
+ /**find an order by ticket*/
+ void orderByTicket();
+ /**find/select orders by event*/
+ void orderByEvent();
+ /**find/select orders by customer*/
+ void orderByCustomer();
+ /**find and display order by order ID*/
+ void orderByOrder();
+ /**deduct some money from a voucher (to pay outside the system)*/
+ void deductVoucher();
+
+ /**money log for voucher*/
+ void moneylogVoucher();
+ /**money log for user*/
+ void moneylogUser();
+
+ /**refresh data that we can refresh*/
+ void refreshData();
+ /**set refresh timeout*/
+ void setRefresh();
+
+ /**web request settings dialog; shows the dialog per default, just copies settings from registry to webrequest object if false*/
+ void webSettings(bool dlg=true);
+
+ /**do a backup now*/
+ void doBackup();
+
+ /**settings for backup*/
+ void backupSettings();
+
+ private:
+ //the profile associated with this session
+ QString profilekey;
+ //widgets
+ QTabWidget*tab;
+ QWidget*eventtab,*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
+ QTableView*eventtable,*usertable,*hosttable,*carttable,*ordertable;
+ QStandardItemModel*eventmodel,*usermodel,*hostmodel,*cartmodel,*ordermodel;
+ QPushButton*thishostbutton;
+ QLabel*cartcustomer,*entrancelabel;
+ QTextEdit *cartaddr,*cartcomment;
+ QComboBox*ordermode,*cartship,*entranceevent;
+ QLineEdit*entrancescan;
+ //event list
+ QAction*showoldevents;
+ //cart
+ MCustomer customer;
+ //barcode cache
+ QString lastbarcode;
+ QDateTime lastbcscan;
+ //refresh timers
+ QTimer rtimer,baktimer;
+};
+
+/**Helper dialog for changing passwords*/
+class MPasswordChange:public QDialog
+{
+ Q_OBJECT
+ public:
+ /**creates a password change dialog, if user is empty it is presumed to change own password*/
+ MPasswordChange(QWidget*parent,QString user=QString());
+
+ /**if own password: return old password*/
+ QString oldPassword();
+ /**returns new password, or empty if the two lines don't match*/
+ QString newPassword();
+ private:
+ QLineEdit *oldpwd,*newpwd1,*newpwd2;
+};
+
+/**Helper class for shopping cart: allow editing amount, but nothing else*/
+class MCartTableDelegate:public QItemDelegate
+{
+ public:
+ MCartTableDelegate(QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void setEditorData(QWidget *editor, const QModelIndex &index) const;
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const;
+};
+
+/**Helper class for Backup settings*/
+class MBackupDialog:public QDialog
+{
+ Q_OBJECT
+ public:
+ MBackupDialog(QWidget*,QString);
+
+ private slots:
+ void getpath();
+ void save();
+ private:
+ QLineEdit*lpath;
+ QSpinBox*interv,*gener;
+ QCheckBox*autob;
+ QString profilekey;
+};
+
+#endif
#include "moneylog.h"
#include "msinterface.h"
#include "orderwin.h"
+
#include "overview.h"
+#include "eventstab.h"
#include <QApplication>
#include <QBoxLayout>
m->addSeparator();
m->addAction(tr("&Close Session"),this,SLOT(close()));
- m=mb->addMenu(tr("&Event"));
- m->addAction(tr("&Update Event List"),this,SLOT(updateEvents()))
- ->setEnabled(req->hasRight(req->RGetAllEvents));
- m->addAction(tr("&Show/Edit details..."),this,SLOT(editEvent()))
- ->setEnabled(req->hasRight(req->RGetEvent));
- m->addAction(tr("&New Event..."),this,SLOT(newEvent()))->setEnabled(req->hasRole("createevent"));
- m->addSeparator();
- showoldevents=m->addAction(tr("Show &old Events"),this,SLOT(updateEvents()));
- showoldevents->setEnabled(req->hasRight(req->RGetAllEvents));
- showoldevents->setCheckable(true);
- showoldevents->setChecked(QSettings().value("profiles/"+pk+"/showOldEvents",false).toBool());
-
m=mb->addMenu(tr("&Customer"));
m->addAction(tr("&Show all customers"),this,SLOT(customerMgmt()));
mb->addMenu(MApplication::helpMenu());
+ //make sure webrequest knows its settings
+ webSettings(false);
+
//tabs
setCentralWidget(tab=new QTabWidget);
connect(tab,SIGNAL(currentChanged(int)),this,SLOT(tabChanged()));
//Event tab
- tab->addTab(eventtab=new QWidget,tr("Events"));
+ tab->addTab(eventtab=new MEventsTab(pk),tr("Events"));
+ mb->addMenu(eventtab->menu());
QVBoxLayout*vl;QHBoxLayout*hl;
- eventtab->setLayout(hl=new QHBoxLayout);
- hl->addWidget(eventtable=new QTableView,10);
- eventtable->setModel(eventmodel=new QStandardItemModel(this));
- eventtable->setSelectionMode(QAbstractItemView::SingleSelection);
- eventtable->setEditTriggers(QAbstractItemView::NoEditTriggers);
- hl->addSpacing(5);
- hl->addLayout(vl=new QVBoxLayout,0);
QPushButton*p;
- vl->addWidget(p=new QPushButton(tr("New Event...")),0);
- connect(p,SIGNAL(clicked()),this,SLOT(newEvent()));
- p->setEnabled(req->hasRole("createevent"));
- vl->addWidget(p=new QPushButton(tr("Details...")),0);
- connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
- p->setEnabled(req->hasRole("geteventdata"));
- vl->addSpacing(15);
- vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
- connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
- p->setEnabled(req->hasRole("createorder"));
- vl->addSpacing(15);
- vl->addWidget(p=new QPushButton(tr("Event Summary...")),0);
- connect(p,SIGNAL(clicked()),this,SLOT(eventSummary()));
- p->setEnabled(req->hasRole("eventsummary"));
- vl->addSpacing(15);
- vl->addWidget(p=new QPushButton(tr("Cancel Event...")),0);
- p->setEnabled(req->hasRole("cancelevent"));
- connect(p,SIGNAL(clicked()),this,SLOT(eventCancel()));
- vl->addStretch(10);
//Shopping Cart Tab
tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
//status bar
statusBar()->setSizeGripEnabled(true);
- //make sure webrequest knows its settings
- webSettings(false);
//fill tables
- if(req->hasRight(req->RGetAllEvents)){
- updateEvents();
- }else{
+ if(!req->hasRight(req->RGetAllEvents)){
eventtab->setEnabled(false);
tab->setTabEnabled(tab->indexOf(eventtab),false);
}
}
}
-void MOverview::updateEvents()
-{
- MTGetAllEvents gae=req->queryGetAllEvents();
- if(gae.stage()!=gae.Success){
- qDebug("Error getting all events (%s): %s",gae.errorType().toAscii().data(),gae.errorString().toAscii().data());
- return;
- }
- QList<MOEvent>evl=gae.getevents();
- eventmodel->clear();
- eventmodel->insertColumns(0,6);
- eventmodel->setHorizontalHeaderLabels(QStringList()<<tr("Start Time")<<tr("Title")<<tr("Free")<<tr("Reserved")<<tr("Sold")<<tr("Capacity"));
- QDateTime now=QDateTime::currentDateTime();
- for(int i=0,j=0;i<evl.size();i++){
- QDateTime stime=QDateTime::fromTime_t(evl[i].start());
- if(stime<now && !showoldevents->isChecked())continue;
- eventmodel->insertRow(j);
- eventmodel->setData(eventmodel->index(j,0),evl[i].id().value(),Qt::UserRole);
- eventmodel->setData(eventmodel->index(j,0),stime.toString(tr("ddd MMMM d yyyy, h:mm ap","time format")));
- eventmodel->setData(eventmodel->index(j,1),evl[i].title().value());
- eventmodel->setData(eventmodel->index(j,2),evl[i].capacity()-evl[i].amountSold()-evl[i].amountReserved());
- eventmodel->setData(eventmodel->index(j,3),evl[i].amountReserved().value());
- eventmodel->setData(eventmodel->index(j,4),evl[i].amountSold().value());
- eventmodel->setData(eventmodel->index(j,5),evl[i].capacity().value());
- j++;
- }
- eventtable->resizeColumnsToContents();
- //in case this was called from changing the check state
- QSettings().setValue("profiles/"+profilekey+"/showOldEvents",showoldevents->isChecked());
-}
-
void MOverview::closeEvent(QCloseEvent*ce)
{
//make sure session is deleted
setEnabled(true);
}
-void MOverview::newEvent()
-{
- MEventEditor ed(this);
- ed.exec();
- updateEvents();
-}
-
-void MOverview::editEvent()
-{
- int id;
- QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
- if(ilst.size()<1)return;
- QModelIndex idx=eventmodel->index(ilst[0].row(),0);
- id=eventmodel->data(idx,Qt::UserRole).toInt();
- if(id<0)return;
- MEventEditor ed(this,id);
- ed.exec();
- updateEvents();
-}
-
-void MOverview::eventSummary()
-{
- int id;
- QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
- if(ilst.size()<1)return;
- QModelIndex idx=eventmodel->index(ilst[0].row(),0);
- id=eventmodel->data(idx,Qt::UserRole).toInt();
- if(id<0)return;
- MEventSummary ed(this,id);
- ed.exec();
-}
-
-void MOverview::eventCancel()
-{
- int id;
- QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
- if(ilst.size()<1)return;
- QModelIndex idx=eventmodel->index(ilst[0].row(),0);
- id=eventmodel->data(idx,Qt::UserRole).toInt();
- if(id<0)return;
- MTGetEvent getev=MTGetEvent::query(id);
- if(!getev.hasError()){
- bool ok;
- MOEvent ev=getev.getevent();
- QString r=QInputDialog::getText(this,tr("Cancel Event"),tr("Please enter a reason to cancel event \"%1\" or abort:").arg(ev.title()),QLineEdit::Normal,"",&ok);
- if(!ok)return;
- MTCancelEvent cev=MTCancelEvent::query(id,r);
- if(!cev.hasError())
- QMessageBox::information(this,tr("Event Cancelled"),tr("The event \"%1\" has been cancelled. Please inform everybody who bought a ticket.").arg(ev.title()));
- else
- QMessageBox::warning(this,tr("Warning"),tr("Unable to cancel event \"%1\": %2.").arg(ev.title()).arg(cev.errorString()));
- }
-}
-
void MOverview::updateShipping()
{
cartship->clear();
QVBoxLayout*vl;
dlg.setLayout(vl=new QVBoxLayout);
vl->addWidget(tv=new QTableView,10);
- tv->setModel(eventmodel);
+ QStandardItemModel*eventmodel;
+ tv->setModel(eventmodel=eventtab->eventModel());
tv->setEditTriggers(QAbstractItemView::NoEditTriggers);
tv->resizeColumnsToContents();
vl->addSpacing(15);
void MOverview::eventOrderTicket()
{
//get selected event
- int id;
- QModelIndexList ilst=eventtable->selectionModel()->selectedIndexes();
- if(ilst.size()<1)return;
- QModelIndex idx=eventmodel->index(ilst[0].row(),0);
- id=eventmodel->data(idx,Qt::UserRole).toInt();
+ int id=eventtab->currentEventId();
if(id<0)return;
//activate order tab
tab->setCurrentWidget(carttab);
cartmodel->setData(cartmodel->index(cr,0),1);
cartmodel->setData(cartmodel->index(cr,0),id,CART_IDROLE);
cartmodel->setData(cartmodel->index(cr,0),CART_TICKET,CART_TYPEROLE);
- cartmodel->setData(cartmodel->index(cr,1),eventmodel->data(eventmodel->index(ilst[0].row(),1)));
- cartmodel->setData(cartmodel->index(cr,2),eventmodel->data(eventmodel->index(ilst[0].row(),0)));
+ cartmodel->setData(cartmodel->index(cr,1),eventtab->currentEventTitle());
+ cartmodel->setData(cartmodel->index(cr,2),eventtab->currentEventStart());
carttable->resizeColumnsToContents();
}
QSettings set;
set.beginGroup("profiles/"+profilekey);
if(set.value("refreshEvents",false).toBool() && req->hasRole("geteventlist"))
- updateEvents();
+ eventtab->updateEvents();
if(set.value("refreshUsers",false).toBool() && req->hasRole("getusers"))
updateUsers();
if(set.value("refreshHosts",false).toBool() && req->hasRole("gethosts"))
class MSInterface;
+class MEventsTab;
+
/**Main Overview Window*/
class MOverview:public QMainWindow
{
/**try to log in again*/
void relogin();
- /**create a new event*/
- void newEvent();
- /**edit existing event*/
- void editEvent();
- /**update list of events*/
- void updateEvents();
/**order ticket from event tab*/
void eventOrderTicket();
- /**open event summary*/
- void eventSummary();
- /**cancel the event*/
- void eventCancel();
/**update shipping info*/
void updateShipping();
QString profilekey;
//widgets
QTabWidget*tab;
- QWidget*eventtab,*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
- QTableView*eventtable,*usertable,*hosttable,*carttable,*ordertable;
- QStandardItemModel*eventmodel,*usermodel,*hostmodel,*cartmodel,*ordermodel;
+ MEventsTab*eventtab;
+ QWidget*carttab,*usertab,*hosttab,*ordertab,*entrancetab;
+ QTableView*usertable,*hosttable,*carttable,*ordertable;
+ QStandardItemModel*usermodel,*hostmodel,*cartmodel,*ordermodel;
QPushButton*thishostbutton;
QLabel*cartcustomer,*entrancelabel;
QTextEdit *cartaddr,*cartcomment;
QComboBox*ordermode,*cartship,*entranceevent;
QLineEdit*entrancescan;
- //event list
- QAction*showoldevents;
//cart
MCustomer customer;
//barcode cache