#include "qmdialoguploadlegtimes.h" #include "qmdialoguploadlegtimes_ui.cpp" #include "QTableWidgetItem" #include "QFile" #include "QString" #include "QFileDialog" #include "QClipboard" #include "QRegExp" #include "mainwindow.h" #include "QTextStream" #include "timedelegate.h" #include "qmconfig.h" #include "consts.h" #include "structs.h" #include "proto.h" QmDialogUploadLegTimes::QmDialogUploadLegTimes(QWidget *parent) : QDialog(parent), ui(new Ui::QmDialogUploadLegTimes) { ui->setupUi(this); setSizeGripEnabled(true); ui->legNumber->setMaximum(config.num_legs); // Connect up buttons connect(ui->load, SIGNAL(clicked()), this, SLOT(load())); connect(ui->fromClip, SIGNAL(clicked()), this, SLOT(fromClip())); connect(ui->fromEvent, SIGNAL(clicked()), this, SLOT(fromEvent())); connect(ui->clear, SIGNAL(clicked()), this, SLOT(clear())); connect(ui->cancel,SIGNAL(clicked()), this, SLOT(close())); connect(ui->update,SIGNAL(clicked()), this, SLOT(update())); connect(ui->deltaTime, SIGNAL(timeChanged(QTime)), this, SLOT(updateDeltaDisplay())); connect(ui->hideOk, SIGNAL(clicked()), this, SLOT(updateDeltaDisplay())); connect(ui->legNumber, SIGNAL(valueChanged(int)), this, SLOT(legNumberChanged(int))); // Set up the table // First column is not a 'time' column ui->tableWidget->setColumnCount(1); ui->tableWidget->setHorizontalHeaderItem ( 0, new QTableWidgetItem ("Team")); addColumn("Delta"); addColumn("Used"); addColumn("Time"); // Wire up the table connect(ui->tableWidget,SIGNAL(itemDoubleClicked (QTableWidgetItem*)), this,SLOT(itemActivated(QTableWidgetItem*))); // Init status ui->status->setText("Load Leg File"); legNumberChanged(0); } QmDialogUploadLegTimes::~QmDialogUploadLegTimes() { delete ui; } void QmDialogUploadLegTimes::addColumn(QString hdr) { int col = ui->tableWidget->columnCount(); ui->tableWidget->insertColumn(col); // Insert header ui->tableWidget->setHorizontalHeaderItem ( col, new QTableWidgetItem (hdr)); // Insert Time Delegate ui->tableWidget->setItemDelegateForColumn(col, new timeDelegate()); } void QmDialogUploadLegTimes::clear(void) { ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); // Update Error information updateDeltaDisplay(); } void QmDialogUploadLegTimes::fromEvent(void) { team_type team_buf; /* Determine the leg to load - from other dialog */ int leg = ui->legNumber->value() ; if (leg <= 0 || leg > config.num_legs) { ui->status->setText("Must select leg number"); return; } ui->status->setText("Load existing data from leg:" + QString::number(leg)); for( int i = config.min_team; i <= config.max_team; i++ ) { if( valid_field( i ) && g_record( i, &team_buf ) ) { int secs; if ( ui->legStart->isChecked()) { secs = team_buf.leg[leg].start; } else { secs = team_buf.leg[leg].end; } QTime data = QTime().addSecs(secs); //qDebug() << "Team:"<< i << " Time:" << data.toString("hh:mm:ss"); addDataToTable(i, data, true); } } // Update Error information updateDeltaDisplay(); } void QmDialogUploadLegTimes::fromClip(void) { QClipboard *clipboard = QApplication::clipboard(); QString text = clipboard->text(); if (text.length() > 0) { QStringList list = text.split(QRegExp("[\\r\\n]")); ui->status->setText("Loading Data"); for (int i = 0; i < list.size(); ++i) { processOneLine(list.at(i)); } // Update Error information updateDeltaDisplay(); } } void QmDialogUploadLegTimes::processOneLine(QString line) { QStringList parts; line = line.trimmed(); // Remove leading and training White Space if (line.size() <= 0) return; // An array of possible imput parsers // QRegExp lineFormats[] = { QRegExp ("^(\\d+)\\s+(\\d+:\\d+:\\d+)$"), // 022 12:13:14 QRegExp ("^(\\d+)\\s*,\\s*(\\d+:\\d+:\\d+)$"), // 022,12:13:14 QRegExp ("^(\\d+)\\s+\\d+-\\d+-\\d+\\s+(\\d+:\\d+:\\d+)\\.\\d+$"), // 022 2019-08-01 12:13:14.123 QRegExp ("^\\d+,(\\d+),(\\d+:\\d+:\\d+)$"), // 001,022,12:13:14 QRegExp ("^\\d+,(\\d+),\\d+,\"(\\d+:\\d+:\\d+)\\.\\d+\"$"), // 2,22,0,"09:40:09.612" }; for( unsigned int idx = 0 ; idx <(sizeof(lineFormats)/sizeof(*lineFormats)); idx++ ) { if(lineFormats[idx].indexIn(line) == 0) { parts = lineFormats[idx].capturedTexts(); } } if ( parts.empty()) { qDebug("Funny Line regex: %s", qPrintable(line)); return; } QString first = parts.value(1); if ( parts.count() != 3) { qDebug("Funny Line parts: %s", qPrintable(line)); return; } bool ok; int team = first.toInt(&ok); if ( ! ok || team <= 0 || team > 999 ) { qDebug("Bad Team Number: %s", qPrintable(line)); return; } addDataToTable(team, QTime::fromString(parts.value(2),"hh:mm:ss"), false); } void QmDialogUploadLegTimes::addDataToTable(int team, QTime ltime, bool isYellow) { if ( team <= 0 || team > 999 ) { //qDebug("Team Number out of range: %s", qPrintable(line)); return; } if (team > ui->tableWidget->rowCount()) { ui->tableWidget->setRowCount(team); } QTableWidgetItem *item = ui->tableWidget->item(team-1,0); if (!item) { item = new QTableWidgetItem(QString::number(team)); item->setFlags(item->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled)); ui->tableWidget->setItem(team-1,0,item); item->setData(Qt::ToolTipRole,"Team Number"); item = new QTableWidgetItem(""); item->setFlags(item->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled)); ui->tableWidget->setItem(team-1,1,item); item->setData(Qt::ToolTipRole,"Max delta"); item = new QTableWidgetItem(""); item->setFlags(item->flags() & ~(Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled)); ui->tableWidget->setItem(team-1,2,item); item->setData(Qt::ToolTipRole,"Use this data"); } // Insert the time at the first available slot // Scan for max an min as we go int ii; QTableWidgetItem *titem = NULL; //QTime ltime = QTime::fromString(parts.value(2),"hh:mm:ss"); unsigned int lsecs = QTime(0,0,0).secsTo(ltime); if ( lsecs <= 0) { //qDebug("Funny Line: %s", qPrintable(line)); return; } //qDebug("Tead: %d, Secs: %d", team, lsecs ); unsigned int min_time = lsecs; unsigned int max_time = lsecs; bool empty_cell_found = false; for (ii=3 ; ii <= ui->tableWidget->columnCount() - 1; ii++) { titem = ui->tableWidget->item(team-1,ii); if (! titem) { // Empty cell found empty_cell_found = true; break; } QTime entry = titem->data(Qt::EditRole).toTime(); unsigned int secs = QTime(0,0,0).secsTo(entry); if ( secs < min_time ) min_time = secs; if (secs > max_time) max_time = secs; } // No space found for the data - add a new column if ( ! empty_cell_found ) { addColumn("Time"); ii = ui->tableWidget->columnCount() - 1; } // Insert data into cell titem = new QTableWidgetItem(); titem->setData(Qt::EditRole, ltime); titem->setFlags(titem->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled)); ui->tableWidget->setItem(team-1,ii,titem); // Color if needed if (isYellow) titem->setBackgroundColor(QColor(255,255,0,30)); //qDebug("Team: %d, %d of %d", team-1, ii, ui->tableWidget->columnCount() ); if (ii == 3) { titem = new QTableWidgetItem(); titem->setData(Qt::EditRole, ltime); ui->tableWidget->setItem(team-1,2,titem); titem->setBackgroundColor(QColor(0,255,0,30)); } int delta = max_time - min_time; if ( delta ) { ui->tableWidget->item(team-1,1)->setData(Qt::EditRole, QTime().addSecs(delta)); } } void QmDialogUploadLegTimes::load(void) { QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), appSettings->value("LegTimeUpload/LastFile",filepath).toString(), tr("Legs (*leg*);;Data (*.leg);;Text (*.txt);;Csv (*.csv);;All (*.*)"), 0, QFileDialog::ReadOnly); if ( fileName.isEmpty() ) { MainWindow::showMessage("No File Specified"); return; } appSettings->setValue("LegTimeUpload/LastFile", fileName); // Open the file QFile file(fileName); if ( ! file.open(QIODevice::ReadOnly | QIODevice::Text) ) { MainWindow::showMessage("Cannot open Leg Data file"); return; } ui->status->setText("Loading Data"); // Insert column headers //ui->tableWidget->clearContents(); //ui->tableWidget->setRowCount(0); // Process Each line of the file // Format (original) is TeamNumber Time // Format (alternate) is TeamNumber Date Time // Time has milliseconds QTextStream in(&file); while (!in.atEnd()) { processOneLine(in.readLine()); } // Update Error information updateDeltaDisplay(); } void QmDialogUploadLegTimes::updateDeltaDisplay( void ) { bool isFlagged = false; QTime maxDelta(0,0,0,0); QTime delta = ui->deltaTime->time(); //qDebug("New Delta: %s", qPrintable(ui->deltaTime->time().toString())); for ( int ii = 0; ii < ui->tableWidget->rowCount(); ii++) { bool show = true; QTableWidgetItem *item; item = ui->tableWidget->item(ii, 1); if (item) { QTime time = item->data(Qt::EditRole).toTime(); if ( time > maxDelta) { maxDelta = time; } if ( time > delta ) { item->setBackgroundColor(QColor(255,0,0,50)); isFlagged = true; } else { item->setBackgroundColor(QColor(255,255,255)); if ( ui->hideOk->isChecked()) { show = false; } } } // Hide if not a valid time and we have no time ebtry for it if ( !valid_field(ii+1) && item == NULL ) { show = false; } ui->tableWidget->setRowHidden(ii,!show); } //ui->maxDeltaTime->setText(QString::number(QTime(0,0,0).secsTo(maxDelta))); ui->maxDeltaTime->setText(maxDelta.toString("hh:mm:ss")); if (isFlagged) { ui->status->setText("Large Delta Times"); } else { } } void QmDialogUploadLegTimes::update(void) { team_type team_buf; int leg = ui->legNumber->value() ; if (leg <= 0 || leg > config.num_legs) { ui->status->setText("Must select leg number"); return; } // Insert the first time into the desired leg for ( int ii = 0; ii < ui->tableWidget->rowCount(); ii++) { QTableWidgetItem *item; item = ui->tableWidget->item(ii, 0); if (item) { int team = item->data(Qt::EditRole).toInt(); if( valid_field( team ) && g_record( team, &team_buf ) ) { item = ui->tableWidget->item(ii, 2); if (item) { QTime time = item->data(Qt::EditRole).toTime(); int secs = QTime(0,0,0).secsTo(time); if ( ui->legStart->isChecked()) { team_buf.leg[leg].start = secs; team_buf.leg[leg].manual = TRUE; } else { team_buf.leg[leg].end = secs; } set_times( &team_buf ); /* Calc start of next leg */ test_times( &team_buf, 0 ); /* Calc elapsed times etc */ put_team_record( team, &team_buf ); ui->tableWidget->hideRow(ii); } } } } } void QmDialogUploadLegTimes::itemActivated ( QTableWidgetItem * uitem ) { // Use this item for the time, but only if the item is from a 'time' column if ( uitem->column() >= 3 ) { QTableWidgetItem *titem = new QTableWidgetItem(*uitem); titem->setFlags(titem->flags()| Qt::ItemIsEditable); ui->tableWidget->setItem(uitem->row(),2,titem); titem->setBackgroundColor(QColor(0,0,255,30)); } } void QmDialogUploadLegTimes::legNumberChanged(int leg) { //qDebug() << "Leg:" << leg; ui->fromEvent->setEnabled(leg != 0); ui->update->setEnabled( leg != 0); }