From c41a3bb381fc46d0afdefb7834246b1d26faa520 Mon Sep 17 00:00:00 2001 From: konrad Date: Sun, 27 Dec 2009 10:53:41 +0000 Subject: [PATCH] started to refactor main overview window: *copied files *extracted events list *more tabs to come... git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@355 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- src/mwin/acltabs.cpp | 1753 ++++++++++++++++++++++++++++++++++++++++++++++ src/mwin/acltabs.h | 235 +++++++ src/mwin/carttab.cpp | 1753 ++++++++++++++++++++++++++++++++++++++++++++++ src/mwin/carttab.h | 235 +++++++ src/mwin/entrancetab.cpp | 1753 ++++++++++++++++++++++++++++++++++++++++++++++ src/mwin/entrancetab.h | 235 +++++++ src/mwin/eventstab.cpp | 213 ++++++ src/mwin/eventstab.h | 86 +++ src/mwin/mwin.pri | 6 +- src/mwin/orderstab.cpp | 1753 ++++++++++++++++++++++++++++++++++++++++++++++ src/mwin/orderstab.h | 235 +++++++ src/mwin/overview.cpp | 151 +---- src/mwin/overview.h | 21 +- 13 files changed, 8275 insertions(+), 154 deletions(-) create mode 100644 src/mwin/acltabs.cpp create mode 100644 src/mwin/acltabs.h create mode 100644 src/mwin/carttab.cpp create mode 100644 src/mwin/carttab.h create mode 100644 src/mwin/entrancetab.cpp create mode 100644 src/mwin/entrancetab.h create mode 100644 src/mwin/eventstab.cpp create mode 100644 src/mwin/eventstab.h create mode 100644 src/mwin/orderstab.cpp create mode 100644 src/mwin/orderstab.h diff --git a/src/mwin/acltabs.cpp b/src/mwin/acltabs.cpp new file mode 100644 index 0000000..33d9424 --- /dev/null +++ b/src/mwin/acltabs.cpp @@ -0,0 +1,1753 @@ +// +// C++ Implementation: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + QListevl=gae.getevents(); + eventmodel->clear(); + eventmodel->insertColumns(0,6); + eventmodel->setHorizontalHeaderLabels(QStringList()<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(); + QListship=sh.getshipping(); + for(int i=0;iaddItem(ship[i].description(),(int)ship[i].id()); +} + +void MOverview::updateUsers() +{ + MTGetAllUsers au=req->queryGetAllUsers(); + if(au.hasError())return; + QListusl=au.getusers(); + usermodel->clear(); + usermodel->insertColumns(0,2); + usermodel->insertRows(0,usl.size()); + usermodel->setHorizontalHeaderLabels(QStringList()<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<rowCount();i++) + rplc<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(); + QListhsl=req->getAllHosts(); + hostmodel->clear(); + hostmodel->insertColumns(0,2); + hostmodel->insertRows(0,hsl.size()); + hostmodel->setHorizontalHeaderLabels(QStringList()<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()<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); + QListprc=req->getVoucherPrices(); + mdl.insertRows(0,prc.size()); + mdl.insertColumns(0,1); + for(int i=0;iaddWidget(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;irowCount();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;jdata(idx).toInt(); + int price=cartmodel->data(idx,CART_PRICEROLE).toInt(); + int value=cartmodel->data(idx,CART_VALUEROLE).toInt(); + for(int j=0;jcurrentIndex()>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;irowCount();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()<itemData(ordermode->currentIndex()).toInt(); + if(omode==ORDERNONE)return; + QList orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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;jsetData(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 + QListeventids; + for(int i=0;idata(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()< orders=req->getOrdersByEvents(eventids); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + for(int cl=0;clinsertRow(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;jsetData(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()< orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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(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); + } +} diff --git a/src/mwin/acltabs.h b/src/mwin/acltabs.h new file mode 100644 index 0000000..dfd5a43 --- /dev/null +++ b/src/mwin/acltabs.h @@ -0,0 +1,235 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef MAGICSMOKE_OVERVIEW_H +#define MAGICSMOKE_OVERVIEW_H + +#include +#include +#include +#include +#include + +#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 diff --git a/src/mwin/carttab.cpp b/src/mwin/carttab.cpp new file mode 100644 index 0000000..33d9424 --- /dev/null +++ b/src/mwin/carttab.cpp @@ -0,0 +1,1753 @@ +// +// C++ Implementation: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + QListevl=gae.getevents(); + eventmodel->clear(); + eventmodel->insertColumns(0,6); + eventmodel->setHorizontalHeaderLabels(QStringList()<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(); + QListship=sh.getshipping(); + for(int i=0;iaddItem(ship[i].description(),(int)ship[i].id()); +} + +void MOverview::updateUsers() +{ + MTGetAllUsers au=req->queryGetAllUsers(); + if(au.hasError())return; + QListusl=au.getusers(); + usermodel->clear(); + usermodel->insertColumns(0,2); + usermodel->insertRows(0,usl.size()); + usermodel->setHorizontalHeaderLabels(QStringList()<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<rowCount();i++) + rplc<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(); + QListhsl=req->getAllHosts(); + hostmodel->clear(); + hostmodel->insertColumns(0,2); + hostmodel->insertRows(0,hsl.size()); + hostmodel->setHorizontalHeaderLabels(QStringList()<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()<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); + QListprc=req->getVoucherPrices(); + mdl.insertRows(0,prc.size()); + mdl.insertColumns(0,1); + for(int i=0;iaddWidget(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;irowCount();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;jdata(idx).toInt(); + int price=cartmodel->data(idx,CART_PRICEROLE).toInt(); + int value=cartmodel->data(idx,CART_VALUEROLE).toInt(); + for(int j=0;jcurrentIndex()>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;irowCount();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()<itemData(ordermode->currentIndex()).toInt(); + if(omode==ORDERNONE)return; + QList orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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;jsetData(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 + QListeventids; + for(int i=0;idata(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()< orders=req->getOrdersByEvents(eventids); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + for(int cl=0;clinsertRow(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;jsetData(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()< orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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(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); + } +} diff --git a/src/mwin/carttab.h b/src/mwin/carttab.h new file mode 100644 index 0000000..dfd5a43 --- /dev/null +++ b/src/mwin/carttab.h @@ -0,0 +1,235 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef MAGICSMOKE_OVERVIEW_H +#define MAGICSMOKE_OVERVIEW_H + +#include +#include +#include +#include +#include + +#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 diff --git a/src/mwin/entrancetab.cpp b/src/mwin/entrancetab.cpp new file mode 100644 index 0000000..33d9424 --- /dev/null +++ b/src/mwin/entrancetab.cpp @@ -0,0 +1,1753 @@ +// +// C++ Implementation: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + QListevl=gae.getevents(); + eventmodel->clear(); + eventmodel->insertColumns(0,6); + eventmodel->setHorizontalHeaderLabels(QStringList()<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(); + QListship=sh.getshipping(); + for(int i=0;iaddItem(ship[i].description(),(int)ship[i].id()); +} + +void MOverview::updateUsers() +{ + MTGetAllUsers au=req->queryGetAllUsers(); + if(au.hasError())return; + QListusl=au.getusers(); + usermodel->clear(); + usermodel->insertColumns(0,2); + usermodel->insertRows(0,usl.size()); + usermodel->setHorizontalHeaderLabels(QStringList()<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<rowCount();i++) + rplc<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(); + QListhsl=req->getAllHosts(); + hostmodel->clear(); + hostmodel->insertColumns(0,2); + hostmodel->insertRows(0,hsl.size()); + hostmodel->setHorizontalHeaderLabels(QStringList()<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()<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); + QListprc=req->getVoucherPrices(); + mdl.insertRows(0,prc.size()); + mdl.insertColumns(0,1); + for(int i=0;iaddWidget(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;irowCount();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;jdata(idx).toInt(); + int price=cartmodel->data(idx,CART_PRICEROLE).toInt(); + int value=cartmodel->data(idx,CART_VALUEROLE).toInt(); + for(int j=0;jcurrentIndex()>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;irowCount();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()<itemData(ordermode->currentIndex()).toInt(); + if(omode==ORDERNONE)return; + QList orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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;jsetData(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 + QListeventids; + for(int i=0;idata(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()< orders=req->getOrdersByEvents(eventids); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + for(int cl=0;clinsertRow(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;jsetData(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()< orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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(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); + } +} diff --git a/src/mwin/entrancetab.h b/src/mwin/entrancetab.h new file mode 100644 index 0000000..dfd5a43 --- /dev/null +++ b/src/mwin/entrancetab.h @@ -0,0 +1,235 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef MAGICSMOKE_OVERVIEW_H +#define MAGICSMOKE_OVERVIEW_H + +#include +#include +#include +#include +#include + +#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 diff --git a/src/mwin/eventstab.cpp b/src/mwin/eventstab.cpp new file mode 100644 index 0000000..5ab6ee3 --- /dev/null +++ b/src/mwin/eventstab.cpp @@ -0,0 +1,213 @@ +// +// C++ Implementation: event list tab +// +// Description: +// +// +// Author: Konrad Rosenbaum , (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + QListevl=gae.getevents(); + eventmodel->clear(); + eventmodel->insertColumns(0,6); + eventmodel->setHorizontalHeaderLabels(QStringList()<isChecked(); + else showold=QSettings().value("profiles/"+profilekey+"/showOldEvents",false).toBool(); + for(int i=0,j=0;iinsertRow(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(); +} diff --git a/src/mwin/eventstab.h b/src/mwin/eventstab.h new file mode 100644 index 0000000..e9f1f4c --- /dev/null +++ b/src/mwin/eventstab.h @@ -0,0 +1,86 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef MAGICSMOKE_EVENTSTAB_H +#define MAGICSMOKE_EVENTSTAB_H + +#include +#include +#include +#include +#include + +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 diff --git a/src/mwin/mwin.pri b/src/mwin/mwin.pri index aaf3570..33b2481 100644 --- a/src/mwin/mwin.pri +++ b/src/mwin/mwin.pri @@ -1,7 +1,9 @@ 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 diff --git a/src/mwin/orderstab.cpp b/src/mwin/orderstab.cpp new file mode 100644 index 0000000..33d9424 --- /dev/null +++ b/src/mwin/orderstab.cpp @@ -0,0 +1,1753 @@ +// +// C++ Implementation: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + QListevl=gae.getevents(); + eventmodel->clear(); + eventmodel->insertColumns(0,6); + eventmodel->setHorizontalHeaderLabels(QStringList()<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(); + QListship=sh.getshipping(); + for(int i=0;iaddItem(ship[i].description(),(int)ship[i].id()); +} + +void MOverview::updateUsers() +{ + MTGetAllUsers au=req->queryGetAllUsers(); + if(au.hasError())return; + QListusl=au.getusers(); + usermodel->clear(); + usermodel->insertColumns(0,2); + usermodel->insertRows(0,usl.size()); + usermodel->setHorizontalHeaderLabels(QStringList()<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<rowCount();i++) + rplc<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(); + QListhsl=req->getAllHosts(); + hostmodel->clear(); + hostmodel->insertColumns(0,2); + hostmodel->insertRows(0,hsl.size()); + hostmodel->setHorizontalHeaderLabels(QStringList()<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()<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); + QListprc=req->getVoucherPrices(); + mdl.insertRows(0,prc.size()); + mdl.insertColumns(0,1); + for(int i=0;iaddWidget(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;irowCount();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;jdata(idx).toInt(); + int price=cartmodel->data(idx,CART_PRICEROLE).toInt(); + int value=cartmodel->data(idx,CART_VALUEROLE).toInt(); + for(int j=0;jcurrentIndex()>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;irowCount();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()<itemData(ordermode->currentIndex()).toInt(); + if(omode==ORDERNONE)return; + QList orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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;jsetData(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 + QListeventids; + for(int i=0;idata(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()< orders=req->getOrdersByEvents(eventids); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + for(int cl=0;clinsertRow(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;jsetData(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()< orders=req->getAllOrders(); + if(orders.size()==0)return; + QList cust=req->getAllCustomers(); + int cl=0; + for(int i=0;iinsertRow(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(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); + } +} diff --git a/src/mwin/orderstab.h b/src/mwin/orderstab.h new file mode 100644 index 0000000..dfd5a43 --- /dev/null +++ b/src/mwin/orderstab.h @@ -0,0 +1,235 @@ +// +// C++ Interface: overview +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +#ifndef MAGICSMOKE_OVERVIEW_H +#define MAGICSMOKE_OVERVIEW_H + +#include +#include +#include +#include +#include + +#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 diff --git a/src/mwin/overview.cpp b/src/mwin/overview.cpp index 33d9424..ead5eb5 100644 --- a/src/mwin/overview.cpp +++ b/src/mwin/overview.cpp @@ -19,7 +19,9 @@ #include "moneylog.h" #include "msinterface.h" #include "orderwin.h" + #include "overview.h" +#include "eventstab.h" #include #include @@ -89,18 +91,6 @@ MOverview::MOverview(QString pk) 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())); @@ -135,40 +125,18 @@ MOverview::MOverview(QString pk) 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")); @@ -339,12 +307,8 @@ MOverview::MOverview(QString pk) //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); } @@ -375,36 +339,6 @@ MOverview::MOverview(QString pk) } } -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; - } - QListevl=gae.getevents(); - eventmodel->clear(); - eventmodel->insertColumns(0,6); - eventmodel->setHorizontalHeaderLabels(QStringList()<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 @@ -427,60 +361,6 @@ void MOverview::relogin() 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(); @@ -834,7 +714,8 @@ void MOverview::cartAddTicket() 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); @@ -868,11 +749,7 @@ void MOverview::cartAddTicket() 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); @@ -882,8 +759,8 @@ void MOverview::eventOrderTicket() 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(); } @@ -1426,7 +1303,7 @@ void MOverview::refreshData() 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")) diff --git a/src/mwin/overview.h b/src/mwin/overview.h index dfd5a43..b52c4a3 100644 --- a/src/mwin/overview.h +++ b/src/mwin/overview.h @@ -34,6 +34,8 @@ class QTableView; class MSInterface; +class MEventsTab; + /**Main Overview Window*/ class MOverview:public QMainWindow { @@ -49,18 +51,8 @@ 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(); @@ -166,16 +158,15 @@ class MOverview:public QMainWindow 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 -- 1.7.2.5