Subversion Repositories svn1

Rev

Rev 387 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
153 david 1
#include "qmdialoguploadlegtimes.h"
380 david 2
#include "qmdialoguploadlegtimes_ui.cpp"
153 david 3
#include "QTableWidgetItem"
4
#include "QFile"
5
#include "QString"
6
#include "QFileDialog"
380 david 7
#include "QClipboard"
387 david 8
#include "QRegularExpression"
153 david 9
#include "mainwindow.h"
10
#include "QTextStream"
11
#include "timedelegate.h"
380 david 12
#include "qmconfig.h"
153 david 13
 
14
#include    "consts.h"
15
#include    "structs.h"
16
#include    "proto.h"
17
 
18
QmDialogUploadLegTimes::QmDialogUploadLegTimes(QWidget *parent) :
19
    QDialog(parent),
20
    ui(new Ui::QmDialogUploadLegTimes)
21
{
22
    ui->setupUi(this);
380 david 23
    setSizeGripEnabled(true);
153 david 24
    ui->legNumber->setMaximum(config.num_legs);
25
 
26
    // Connect up buttons
27
    connect(ui->load, SIGNAL(clicked()), this, SLOT(load()));
380 david 28
    connect(ui->fromClip, SIGNAL(clicked()), this, SLOT(fromClip()));
29
    connect(ui->fromEvent, SIGNAL(clicked()), this, SLOT(fromEvent()));
30
    connect(ui->clear, SIGNAL(clicked()), this, SLOT(clear()));
153 david 31
    connect(ui->cancel,SIGNAL(clicked()), this, SLOT(close()));
155 - 32
    connect(ui->update,SIGNAL(clicked()), this, SLOT(update()));
380 david 33
    connect(ui->deltaTime, SIGNAL(timeChanged(QTime)), this, SLOT(updateDeltaDisplay()));
185 - 34
    connect(ui->hideOk, SIGNAL(clicked()), this, SLOT(updateDeltaDisplay()));
380 david 35
    connect(ui->legNumber, SIGNAL(valueChanged(int)), this, SLOT(legNumberChanged(int)));
153 david 36
 
37
 
38
    // Set up the table
380 david 39
    // First column is not a 'time' column
40
    ui->tableWidget->setColumnCount(1);
41
    ui->tableWidget->setHorizontalHeaderItem ( 0, new QTableWidgetItem ("Team"));
42
    addColumn("Delta");
43
    addColumn("Used");
44
    addColumn("Time");
153 david 45
 
380 david 46
    // Wire up the table
47
    connect(ui->tableWidget,SIGNAL(itemDoubleClicked (QTableWidgetItem*)), this,SLOT(itemActivated(QTableWidgetItem*)));
153 david 48
 
380 david 49
    // Init status
50
    ui->status->setText("Load Leg File");
51
    legNumberChanged(0);
153 david 52
}
53
 
54
QmDialogUploadLegTimes::~QmDialogUploadLegTimes()
55
{
56
    delete ui;
57
}
58
 
380 david 59
void QmDialogUploadLegTimes::addColumn(QString hdr)
60
{
61
    int col = ui->tableWidget->columnCount();
62
    ui->tableWidget->insertColumn(col);
63
 
64
    // Insert header
65
    ui->tableWidget->setHorizontalHeaderItem ( col, new QTableWidgetItem (hdr));
66
 
67
    // Insert Time Delegate
68
    ui->tableWidget->setItemDelegateForColumn(col, new timeDelegate());
69
}
70
 
71
void QmDialogUploadLegTimes::clear(void)
72
{
73
    ui->tableWidget->clearContents();
74
    ui->tableWidget->setRowCount(0);
75
 
76
    // Update Error information
77
    updateDeltaDisplay();
78
}
79
 
80
void QmDialogUploadLegTimes::fromEvent(void)
81
{
82
    team_type   team_buf;
83
 
84
    /* Determine the leg to load - from other dialog */
85
    int leg = ui->legNumber->value() ;
86
    if (leg <= 0 || leg > config.num_legs)
87
    {
88
        ui->status->setText("Must select leg number");
89
        return;
90
    }
91
 
92
    ui->status->setText("Load existing data from leg:" + QString::number(leg));
93
    for( int i = config.min_team; i <= config.max_team; i++ )
94
    {
95
        if( valid_field( i ) && g_record( i, &team_buf ) )
96
        {
97
            int secs;
98
            if ( ui->legStart->isChecked()) {
99
                secs = team_buf.leg[leg].start;
100
            } else {
101
                secs = team_buf.leg[leg].end;
102
            }
103
 
384 david 104
            QTime data = QTime(0,0).addSecs(secs);
380 david 105
            //qDebug() << "Team:"<< i << " Time:" << data.toString("hh:mm:ss");
106
            addDataToTable(i, data, true);
107
        }
108
    }
109
 
110
    // Update Error information
111
    updateDeltaDisplay();
112
}
113
 
114
void QmDialogUploadLegTimes::fromClip(void)
115
{
116
    QClipboard *clipboard = QApplication::clipboard();
117
    QString text = clipboard->text();
118
    if (text.length() > 0) {
387 david 119
        QStringList list = text.split(QRegularExpression("[\\r\\n]"),Qt::SkipEmptyParts	);
380 david 120
 
121
        ui->status->setText("Loading Data");
122
        for (int i = 0; i < list.size(); ++i)
123
        {
124
            processOneLine(list.at(i));
125
        }
126
 
127
        // Update Error information
128
        updateDeltaDisplay();
129
    }
130
}
131
 
132
void QmDialogUploadLegTimes::processOneLine(QString line)
133
{
134
    QStringList parts;
135
    line = line.trimmed();             // Remove leading and training White Space
136
    if (line.size() <= 0)
137
        return;
138
 
387 david 139
    //  An array of possible input parsers
380 david 140
    //
387 david 141
    QRegularExpression lineFormats[] = {
142
        QRegularExpression ("^(\\d+)\\s+(\\d+:\\d+:\\d+)$"),                           // 022 12:13:14
143
        QRegularExpression ("^(\\d+)\\s*,\\s*(\\d+:\\d+:\\d+)$"),                      // 022,12:13:14
144
        QRegularExpression ("^(\\d+)\\s+\\d+-\\d+-\\d+\\s+(\\d+:\\d+:\\d+)\\.\\d+$"),  // 022 2019-08-01 12:13:14.123
145
        QRegularExpression ("^\\d+,(\\d+),(\\d+:\\d+:\\d+)$"),                         // 001,022,12:13:14
146
        QRegularExpression ("^\\d+,(\\d+),\\d+,\"(\\d+:\\d+:\\d+)\\.\\d+\"$"),         // 2,22,0,"09:40:09.612"
380 david 147
    };
148
 
149
    for( unsigned int idx = 0 ; idx <(sizeof(lineFormats)/sizeof(*lineFormats)); idx++ )
150
    {
387 david 151
        QRegularExpressionMatch match = lineFormats[idx].match(line);
152
        if(match.hasMatch())
380 david 153
        {
387 david 154
            parts = match.capturedTexts();
380 david 155
        }
156
    }
157
 
158
    if ( parts.empty())
159
    {
160
        qDebug("Funny Line regex: %s", qPrintable(line));
161
        return;
162
    }
163
 
164
    QString first = parts.value(1);
165
    if ( parts.count() != 3)
166
    {
167
        qDebug("Funny Line parts: %s", qPrintable(line));
168
        return;
169
    }
170
 
171
    bool ok;
172
    int team = first.toInt(&ok);
173
    if ( ! ok || team <= 0 || team > 999 )
174
    {
175
        qDebug("Bad Team Number: %s", qPrintable(line));
176
        return;
177
    }
178
 
179
    addDataToTable(team, QTime::fromString(parts.value(2),"hh:mm:ss"), false);
180
}
181
 
182
void QmDialogUploadLegTimes::addDataToTable(int team, QTime ltime, bool isYellow)
183
{
184
    if ( team <= 0 || team > 999 )
185
    {
186
        //qDebug("Team Number out of range: %s", qPrintable(line));
187
        return;
188
    }
189
 
190
    if (team > ui->tableWidget->rowCount())
191
    {
192
        ui->tableWidget->setRowCount(team);
193
    }
194
 
195
    QTableWidgetItem *item = ui->tableWidget->item(team-1,0);
196
    if (!item)
197
    {
198
        item = new QTableWidgetItem(QString::number(team));
199
        item->setFlags(item->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled));
200
        ui->tableWidget->setItem(team-1,0,item);
201
        item->setData(Qt::ToolTipRole,"Team Number");
202
 
203
        item = new QTableWidgetItem("");
204
        item->setFlags(item->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled));
205
        ui->tableWidget->setItem(team-1,1,item);
206
        item->setData(Qt::ToolTipRole,"Max delta");
207
 
208
        item = new QTableWidgetItem("");
209
        item->setFlags(item->flags() & ~(Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled));
210
        ui->tableWidget->setItem(team-1,2,item);
211
        item->setData(Qt::ToolTipRole,"Use this data");
212
    }
213
 
214
    //  Insert the time at the first available slot
215
    //  Scan for max an min as we go
216
    int ii;
217
    QTableWidgetItem *titem = NULL;
218
    //QTime ltime = QTime::fromString(parts.value(2),"hh:mm:ss");
219
    unsigned int lsecs = QTime(0,0,0).secsTo(ltime);
220
    if ( lsecs <= 0)
221
    {
222
        //qDebug("Funny Line: %s", qPrintable(line));
223
        return;
224
    }
225
    //qDebug("Tead: %d, Secs: %d", team, lsecs );
226
    unsigned int min_time = lsecs;
227
    unsigned int max_time = lsecs;
228
    bool empty_cell_found = false;
229
 
230
    for (ii=3 ; ii <= ui->tableWidget->columnCount() - 1; ii++)
231
    {
232
        titem = ui->tableWidget->item(team-1,ii);
233
        if (! titem)
234
        {
235
            // Empty cell found
236
            empty_cell_found = true;
237
            break;
238
        }
239
 
240
        QTime entry = titem->data(Qt::EditRole).toTime();
241
        unsigned int secs = QTime(0,0,0).secsTo(entry);
242
        if ( secs < min_time )
243
            min_time = secs;
244
        if (secs > max_time)
245
            max_time = secs;
246
    }
247
 
248
    // No space found for the data - add a new column
249
    if ( ! empty_cell_found )
250
    {
251
        addColumn("Time");
252
        ii = ui->tableWidget->columnCount() - 1;
253
    }
254
 
255
    // Insert data into cell
256
    titem = new QTableWidgetItem();
257
    titem->setData(Qt::EditRole, ltime);
258
    titem->setFlags(titem->flags() & ~(Qt::ItemIsEditable|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled));
259
    ui->tableWidget->setItem(team-1,ii,titem);
260
 
261
    //  Color if needed
387 david 262
    if (isYellow) {
263
        titem->setBackground( QBrush(QColor(255,255,0,30)));
264
    }
380 david 265
 
266
    //qDebug("Team: %d, %d of %d", team-1, ii, ui->tableWidget->columnCount() );
267
 
268
    if (ii == 3)
269
    {
270
        titem = new QTableWidgetItem();
271
        titem->setData(Qt::EditRole, ltime);
272
        ui->tableWidget->setItem(team-1,2,titem);
387 david 273
        titem->setBackground(QBrush(QColor(0,255,0,30)));
380 david 274
    }
275
 
276
    int delta = max_time - min_time;
277
    if ( delta )
278
    {
384 david 279
        ui->tableWidget->item(team-1,1)->setData(Qt::EditRole, QTime(0,0).addSecs(delta));
380 david 280
    }
281
}
282
 
153 david 283
void QmDialogUploadLegTimes::load(void)
284
{
285
    QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"),
389 david 286
                                                 appSettings->value("LegTimeUpload/LastFile",FilePath).toString(),
380 david 287
                                                 tr("Legs (*leg*);;Data (*.leg);;Text (*.txt);;Csv (*.csv);;All (*.*)"),
153 david 288
                                                 0,
289
                                                 QFileDialog::ReadOnly);
290
    if ( fileName.isEmpty() )
291
    {
292
        MainWindow::showMessage("No File Specified");
293
        return;
294
    }
295
 
380 david 296
    appSettings->setValue("LegTimeUpload/LastFile", fileName); 
297
 
298
 
153 david 299
    // Open the file
300
 
301
    QFile file(fileName);
302
    if ( ! file.open(QIODevice::ReadOnly | QIODevice::Text) )
303
    {
304
        MainWindow::showMessage("Cannot open Leg Data file");
305
        return;
306
    }
155 - 307
    ui->status->setText("Loading Data");
153 david 308
    // Insert column headers
380 david 309
    //ui->tableWidget->clearContents();
310
    //ui->tableWidget->setRowCount(0);
153 david 311
 
312
 
313
    // Process Each line of the file
380 david 314
    //  Format (original) is TeamNumber Time
315
    //  Format (alternate) is TeamNumber Date Time
316
    //                                       Time has milliseconds
153 david 317
    QTextStream in(&file);
318
    while (!in.atEnd())
319
    {
380 david 320
        processOneLine(in.readLine());
153 david 321
    }
322
 
155 - 323
    // Update Error information
185 - 324
    updateDeltaDisplay();
155 - 325
 
153 david 326
}
155 - 327
 
185 - 328
void QmDialogUploadLegTimes::updateDeltaDisplay( void )
155 - 329
{
330
    bool isFlagged = false;
185 - 331
    QTime maxDelta(0,0,0,0);
380 david 332
    QTime delta = ui->deltaTime->time();
333
    //qDebug("New Delta: %s", qPrintable(ui->deltaTime->time().toString()));
155 - 334
    for ( int ii = 0; ii < ui->tableWidget->rowCount(); ii++)
335
    {
185 - 336
        bool show = true;
155 - 337
        QTableWidgetItem *item;
338
        item = ui->tableWidget->item(ii, 1);
339
        if (item)
340
        {
341
            QTime time = item->data(Qt::EditRole).toTime();
185 - 342
            if ( time > maxDelta)
343
            {
344
                maxDelta = time;
345
            }
155 - 346
            if ( time > delta )
347
            {
387 david 348
                item->setBackground(QBrush(QColor(255,0,0,50)));
155 - 349
                isFlagged = true;
350
            }
351
            else
352
            {
387 david 353
                item->setBackground(QBrush(QColor(255,255,255)));
185 - 354
                if ( ui->hideOk->isChecked())
355
                {
356
                    show = false;
357
                }
155 - 358
            }
359
        }
185 - 360
 
361
        // Hide if not a valid time and we have no time ebtry for it
362
        if ( !valid_field(ii+1) && item == NULL )
363
        {
364
            show = false;
365
        }
366
        ui->tableWidget->setRowHidden(ii,!show);
367
 
155 - 368
    }
185 - 369
    //ui->maxDeltaTime->setText(QString::number(QTime(0,0,0).secsTo(maxDelta)));
370
    ui->maxDeltaTime->setText(maxDelta.toString("hh:mm:ss"));
155 - 371
    if (isFlagged)
372
    {
373
        ui->status->setText("Large Delta Times");
374
    }
375
    else
376
    {
187 - 377
 
155 - 378
    }
379
}
380
 
381
void QmDialogUploadLegTimes::update(void)
382
{
170 - 383
    team_type   team_buf;
155 - 384
    int leg = ui->legNumber->value() ;
385
    if (leg <= 0 || leg > config.num_legs)
386
    {
387
        ui->status->setText("Must select leg number");
388
        return;
389
    }
390
 
391
    // Insert the first time into the desired leg
392
    for ( int ii = 0; ii < ui->tableWidget->rowCount(); ii++)
393
    {
394
        QTableWidgetItem *item;
395
        item = ui->tableWidget->item(ii, 0);
396
        if (item)
397
        {
398
            int team = item->data(Qt::EditRole).toInt();
399
            if( valid_field( team ) && g_record( team, &team_buf ) )
400
            {
401
                item = ui->tableWidget->item(ii, 2);
402
                if (item)
403
                {
404
                    QTime time = item->data(Qt::EditRole).toTime();
405
                    int secs = QTime(0,0,0).secsTo(time);
406
 
407
                    if ( ui->legStart->isChecked())
408
                    {
409
                        team_buf.leg[leg].start = secs;
410
                        team_buf.leg[leg].manual = TRUE;
411
                    }
412
                    else
413
                    {
414
                        team_buf.leg[leg].end = secs;
415
                    }
416
                    set_times( &team_buf );                 /* Calc start of next leg */
417
                    test_times( &team_buf, 0 );             /* Calc elapsed times etc */
418
                    put_team_record( team, &team_buf );
419
                    ui->tableWidget->hideRow(ii);
420
                }
421
            }
422
        }
423
     }
424
}
187 - 425
 
426
void QmDialogUploadLegTimes::itemActivated ( QTableWidgetItem * uitem )
427
{
380 david 428
    // Use this item for the time, but only if the item is from a 'time' column
429
    if ( uitem->column() >= 3 )
430
    {
431
        QTableWidgetItem *titem = new QTableWidgetItem(*uitem);
432
        titem->setFlags(titem->flags()| Qt::ItemIsEditable);
433
        ui->tableWidget->setItem(uitem->row(),2,titem);
387 david 434
        titem->setBackground(QBrush(QColor(0,0,255,30)));
380 david 435
    }
436
}
187 - 437
 
380 david 438
void QmDialogUploadLegTimes::legNumberChanged(int leg)
439
{
440
    //qDebug() << "Leg:" << leg;
441
    ui->fromEvent->setEnabled(leg != 0);
442
    ui->update->setEnabled( leg != 0);
187 - 443
}