#include "qmconfclass.h" #include "qmconfig.h" #include "ui_qmconfclass.h" #include "consts.h" #include "structs.h" #include "proto.h" #include "mainwindow.h" #include "QTableWidgetItem" #include "spinboxdelegate.h" #include "timedelegate.h" #include "textdelegate.h" #include #define COL_ABR 0 #define COL_CLASS 1 #define COL_TIME 2 #define COL_WINNERS 3 #define COL_NE 4 #define COL_NE_WINNERS 5 #define COL_ST_TOTAL 6 #define COL_ST_VALID 7 #define COL_ST_DISQ 8 #define COL_ST_NONEQ 9 #define COL_ST_VET 10 #define COL_COUNT 11 QmConfClass::QmConfClass(QWidget *parent) : QWidget(parent), ui(new Ui::QmConfClass) { ui->setupUi(this); populating = false; connect(ui->pushButtonSave, SIGNAL(clicked(bool)), this, SLOT(save()) ); connect(ui->pushButtonRestore, SIGNAL(clicked(bool)), this, SLOT(cancel()) ); QStringList labels; labels << "Abr" << "Full Name" << "Start Time" << "Winners" << "NE" << "NE Winners"; ui->tableWidget->setRowCount(config.num_class + 1); ui->tableWidget->setColumnCount(COL_COUNT); ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ctxMenu(const QPoint &))); connect(ui->tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int,int))); /* ** Setup delegated for specialised editing */ ui->tableWidget->setItemDelegateForColumn(COL_ABR, new textDelegate(2)); ui->tableWidget->setItemDelegateForColumn(COL_CLASS, new textDelegate(LEN_CLASS_NAME)); ui->tableWidget->setItemDelegateForColumn(COL_TIME, new timeDelegate()); ui->tableWidget->setItemDelegateForColumn(COL_WINNERS, new SpinBoxDelegate(0,50)); ui->tableWidget->setItemDelegateForColumn(COL_NE_WINNERS, new SpinBoxDelegate(0,50)); populate(); // Wire in the status button connect(ui->statusButton, SIGNAL(clicked()), this, SLOT(updateStatus())); statusShown = false; ui->tableWidget->setColumnHidden(COL_ST_TOTAL, true); ui->tableWidget->setColumnHidden(COL_ST_VALID, true); ui->tableWidget->setColumnHidden(COL_ST_DISQ, true); ui->tableWidget->setColumnHidden(COL_ST_NONEQ, true); ui->tableWidget->setColumnHidden(COL_ST_VET, true); labels << "Total" << "Valid" <<"Disqual" << "NonEq" << "VetCheck"; ui->tableWidget->setHorizontalHeaderLabels(labels); ui->tableWidget->resizeColumnsToContents(); } void QmConfClass::populate(void) { populating = true; ui->tableWidget->setRowCount(config.num_class + 1); for ( int ii = 0; ii < MAX_CLASS; ii++) { ui->tableWidget->setItem(ii, COL_ABR, new QTableWidgetItem(config.team_class[ii].abr) ); ui->tableWidget->setItem(ii, COL_CLASS, new QTableWidgetItem(config.team_class[ii].full_name )); if ( *config.team_class[ii].abr ) { QTableWidgetItem *item; item = new QTableWidgetItem(); item->setData(Qt::EditRole,QTime().addSecs(config.team_class[ii].start) ); ui->tableWidget->setItem(ii, COL_TIME, item); item = new QTableWidgetItem(); item->setData(Qt::EditRole,config.class_winners[ii] ); ui->tableWidget->setItem(ii, COL_WINNERS, item); item = new QTableWidgetItem(); item->setCheckState(config.nonequestrian_class == 1 + ii ? Qt::Checked : Qt::Unchecked); ui->tableWidget->setItem(ii, COL_NE, item); item = new QTableWidgetItem(); item->setData(Qt::EditRole,config.class_ne_winners[ii] ); ui->tableWidget->setItem(ii, COL_NE_WINNERS, item); } } updateChanged(false); populating = false; } void QmConfClass::save(void) { /* ** Copy original data */ QmConfig newcfg(config); /* ** Extract the data from the Widgets */ for ( int ii = 0; ii < MAX_CLASS; ii++) { QTableWidgetItem *item = ui->tableWidget->item ( ii, COL_ABR ); if ( item ) { strncpy(newcfg.team_class[ii].abr, qPrintable(item->text()), sizeof(newcfg.team_class[ii].abr)-1); } else { *newcfg.team_class[ii].abr = 0; } item = ui->tableWidget->item ( ii, COL_CLASS ); if ( item ) { strncpy(newcfg.team_class[ii].full_name, qPrintable(item->text()), sizeof(newcfg.team_class[ii].full_name)-1); } else { *newcfg.team_class[ii].full_name = 0; } item = ui->tableWidget->item( ii, COL_TIME ); if ( item ) { QVariant data = item->data(Qt::EditRole); if (data.isValid()) { newcfg.team_class[ii].start = QTime(0,0,0).secsTo(item->data(Qt::EditRole).toTime()); } else { newcfg.team_class[ii].start = -1; } } else { newcfg.team_class[ii].start = -1; } item = ui->tableWidget->item( ii, COL_WINNERS ); if ( item ) { newcfg.class_winners[ii] = item->data(Qt::EditRole).toInt(); } else { newcfg.class_winners[ii] = 0; } item = ui->tableWidget->item( ii, COL_NE ); if ( item ) { if ( item->checkState() == Qt::Checked) { newcfg.nonequestrian_class = ii; strncpy(newcfg.nonequestrian_class_abr, newcfg.team_class[ii].abr, sizeof(newcfg.team_class[ii].abr)-1); } } item = ui->tableWidget->item( ii, COL_NE_WINNERS ); if ( item ) { newcfg.class_ne_winners[ii] = item->data(Qt::EditRole).toInt(); } else { newcfg.class_ne_winners[ii] = 0; } } // Validate the data try { MainWindow::showMessage( "Saving Config"); /* ** Now do the Class definitions */ for( int i = 0; i < MAX_CLASS; i++ ) { compact( newcfg.team_class[i].abr ); compact( newcfg.team_class[i].full_name ); } for( int i = 0; i < MAX_CLASS; i++ ) { if( ( newcfg.team_class[i].abr[0] == '\0' ) != ( newcfg.team_class[i].full_name[0] == '\0' ) ) { throw( "Configuration error. Class without description" ); } if( newcfg.team_class[i].abr[0] != '\0' && newcfg.team_class[i].start < 0L ) { throw( "Configuration error. Bad start time on class" ); } } newcfg.num_class = 0; for( int i = 0; i < MAX_CLASS; i++ ) if( newcfg.team_class[i].full_name[0] ) newcfg.num_class++; for( int i = newcfg.num_class; i < MAX_CLASS; i++ ) if( newcfg.team_class[i].full_name[0] ) { throw( "Configuration error: Missing Class name. Gaps not allowed" ); } if( newcfg.num_class == 0 ) { throw( "Error: No categories defined" ); } newcfg.nonequestrian_class = newcfg.lookup_class( newcfg.nonequestrian_class_abr ); if( newcfg.equestrian_leg && newcfg.nonequestrian_class == 0 ) MainWindow::showMessage( "WARNING: Non-equestrian class not found" ); /* ** Sanity test of the data */ for( int i = 0; i < MAX_CLASS; i++ ) { if( newcfg.team_class[i].abr[0] != '\0' && newcfg.class_winners[i] == 0 ) { MainWindow::showMessage( QString("Warning: Class without winners:") + newcfg.team_class[i].abr ); } } /* ** Cannot mix winners for NE class and NE Winners for each class */ if (newcfg.nonequestrian_class) { newcfg.class_ne_winners_by_class = false; for( int i = 0; i < MAX_CLASS; i++ ) { if ( newcfg.class_ne_winners[i]) { newcfg.class_ne_winners_by_class = true; break; } } if (newcfg.class_winners[newcfg.nonequestrian_class - 1] && newcfg.class_ne_winners_by_class ) { MainWindow::showMessage( QString("Should not mix NE winners by each class and by NE Class")); //throw( "Error: Cannot mix NE winners by each class and by NE Class" ); } } config = newcfg; config.write_config(); updateChanged(false); } catch (const char * str ) { MainWindow::showMessage(str); } } void QmConfClass::cancel(void) { populate(); } QmConfClass::~QmConfClass() { delete ui; } void QmConfClass::ctxMenu(const QPoint & pos) { qDebug("Context Menu"); QMenu *menu = new QMenu; QTableWidgetItem *item = ui->tableWidget->itemAt(pos); menu->addAction(tr("New Category"), this, SLOT(ctxMenuAddRow())); if (item) { menu->addAction(tr("Delete Category"), this, SLOT(ctxMenuDeleteRow())); } menu->exec(ui->tableWidget->mapToGlobal(pos)); } void QmConfClass::ctxMenuDeleteRow(void) { //qDebug ("DELETE ROW: %d", ui->tableWidget->currentRow () ); ui->tableWidget->removeRow(ui->tableWidget->currentRow ()); updateChanged(true); } void QmConfClass::ctxMenuAddRow(void) { ui->tableWidget->setRowCount( 1+ ui->tableWidget->rowCount()); } void QmConfClass::updateStatus(void) { populating = true; if (!statusShown) { ui->tableWidget->setColumnHidden(COL_ST_TOTAL, false); ui->tableWidget->setColumnHidden(COL_ST_VALID, false); ui->tableWidget->setColumnHidden(COL_ST_DISQ, false); ui->tableWidget->setColumnHidden(COL_ST_NONEQ, false); ui->tableWidget->setColumnHidden(COL_ST_VET, false); statusShown = true; } if( load_report_data() ) { t_class_summary data; calc_class_summary( & data ); // Insert summary data int ii; for (ii = 0; ii < config.num_class; ii++) { QTableWidgetItem *item; item = new QTableWidgetItem(QString::number(data.teamclass[ii+1].total)); item->setFlags(Qt::NoItemFlags); ui->tableWidget->setItem(ii,COL_ST_TOTAL, item ); item = new QTableWidgetItem(QString::number(data.teamclass[ii+1].valid)); item->setFlags(Qt::NoItemFlags); ui->tableWidget->setItem(ii,COL_ST_VALID, item ); item = new QTableWidgetItem(QString::number(data.teamclass[ii+1].disqualified)) ; item->setFlags(Qt::NoItemFlags); ui->tableWidget->setItem(ii,COL_ST_DISQ, item); item = new QTableWidgetItem(QString::number(data.teamclass[ii+1].non_equestrian)); item->setFlags(Qt::NoItemFlags); ui->tableWidget->setItem(ii,COL_ST_NONEQ, item); item = new QTableWidgetItem(QString::number(data.teamclass[ii+1].vet_check)); item->setFlags(Qt::NoItemFlags); ui->tableWidget->setItem(ii,COL_ST_VET, item); } ui->tableWidget->resizeColumnsToContents(); ui->tableWidget->resizeRowsToContents(); } populating = false; } void QmConfClass::cellChanged(int row,int col) { if ( populating ) return; updateChanged(true); populating = true; //qDebug("Cell changed: %d, %d", row, col); if (col == COL_NE) { for (int ii = 0; ii < ui->tableWidget->rowCount(); ii++) { QTableWidgetItem *item = ui->tableWidget->item(ii, COL_NE); if (item) { item->setCheckState(ii == row ? Qt::Checked : Qt::Unchecked); } } } populating = false; } void QmConfClass::updateChanged(bool newDirty) { if (newDirty != dirty) { dirty = newDirty; if (dirty) { ui->pushButtonSave->setEnabled(true); ui->pushButtonSave->setStyleSheet("background-color: rgb(255, 0, 0);"); } else { ui->pushButtonSave->setEnabled(false); ui->pushButtonSave->setStyleSheet(""); } } } void QmConfClass::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } }