Subversion Repositories svn1

Rev

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

Rev Author Line No. Line
144 - 1
#include "qmdialogloadexternalteams.h"
380 david 2
//#include "ui_qmdialogloadexternalteams.h"
145 - 3
#include "QFile"
4
#include "QTextStream"
5
#include "mainwindow.h"
6
#include <QRegExp>
384 david 7
#include <QHBoxLayout>
8
#include <QVBoxLayout>
9
#include <QWidget>
380 david 10
#include <QHeaderView>
384 david 11
#include <QWebEngineHistory>
12
#include <QWebEngineHistoryItem>
13
#include <QWebEnginePage>
14
#include <QWebEngineView>
145 - 15
#include    "consts.h"
16
#include    "structs.h"
17
#include    "proto.h"
18
 
380 david 19
/*----------------------------------------------------------------------------
20
** FUNCTION           : QmDialogLoadExternalTeams
21
**
22
** DESCRIPTION        : Load team data from a CSV file
23
**
24
**
25
** INPUTS             : efile       - name of file
26
**                      parent      - parent widget
27
**
28
** RETURNS            :
29
**
30
----------------------------------------------------------------------------*/
31
 
145 - 32
QmDialogLoadExternalTeams::QmDialogLoadExternalTeams(const QString &efile,QWidget *parent) :
380 david 33
        QDialog(parent)
224 - 34
{
221 - 35
 
36
    //
37
    // Create Windows
38
    //
380 david 39
    createWindow();
40
    fileName->setText(efile);
41
 
42
    // Open the users file
43
 
44
    QFile file(efile);
45
    if ( ! file.open(QIODevice::ReadOnly | QIODevice::Text) )
46
    {
47
        MainWindow::showMessage("Cannot open external data file");
48
        return;
49
    }
50
    MainWindow::showMessage("Loading External Data");
51
 
52
    // Process Each line of the file
53
    QTextStream in(&file);
54
    QRegExp csv_split("\"?,\"?");
55
    while (!in.atEnd())
56
    {
57
        QString line = in.readLine();
58
        line = line.trimmed();             // Remove leading and training White Space
59
        line.remove(0xA0);                 // M$ special uglyness
60
        line.remove(0xC2);                 // M$ special uglyness
61
 
62
        bool has_RefError = hasRefError(line);
63
        QStringList parts = splitCsvData(line);
64
        insertParts( parts, has_RefError );
65
 
66
    }
67
 
68
    // Post Load fix up
69
    tableWidget->resizeColumnsToContents();
70
    reportErrors( bad_cat, bad_refs);
71
}
72
 
73
/*----------------------------------------------------------------------------
74
** FUNCTION           : QmDialogLoadExternalTeams
75
**
76
** DESCRIPTION        : Load team data from a Web Page
77
**
78
**
79
** INPUTS             : efile       - name of file (display only)
80
**                      data        - Address of the webpage data loaded in memory
81
**                      parent      - parent widget
82
**
83
** RETURNS            :
84
**
85
----------------------------------------------------------------------------*/
86
 
87
QmDialogLoadExternalTeams::QmDialogLoadExternalTeams(const QString &efile, QByteArray *data ,QWidget *parent) :
88
        QDialog(parent)
89
{
90
    // Create the basic Window
91
    createWindow();
92
    fileName->setText(efile);
93
 
94
    // Parse the data. It is an html file
95
    //
96
    MainWindow::showMessage("Parsing HTML");
97
    //qDebug("Data size: %d", data->length());
384 david 98
#if 0
380 david 99
    QWebPage page;
100
    QWebFrame * frame = page.mainFrame();
101
    frame->setContent(*data);
102
 
103
    /*
104
    **  Get the first table
105
    **      Get all rows
106
    **      Get all data items in each row
107
    */
108
    QWebElement document = frame->documentElement();
109
    QWebElement firstTable = document.findFirst("table");
110
    QWebElementCollection elements = firstTable.findAll("tr");
111
 
112
    foreach(QWebElement e, elements){
113
 
114
        //qDebug()<< "e element" <<e.tagName() << ":" << e.toPlainText();
115
        //qDebug("-----Row");
116
        bool has_RefError = hasRefError(e.toPlainText());
117
 
118
        QWebElementCollection td = e.findAll("td");
119
        QStringList parts;
120
 
121
        foreach(QWebElement e, td)
122
        {
123
            //qDebug()<< e.tagName() << ":" << e.toPlainText();
124
            parts.append(e.toPlainText());
125
        }
126
        insertParts( parts, has_RefError );
127
    }
128
 
129
    // Post Load fix up
130
    tableWidget->resizeColumnsToContents();
131
    reportErrors( bad_cat, bad_refs);
384 david 132
#endif
380 david 133
}
134
 
135
/*----------------------------------------------------------------------------
136
** FUNCTION           : createWindow
137
**
138
** DESCRIPTION        : Create the basic window
139
**                      Used in multiple places
140
**
141
**
142
** INPUTS             :
143
**
144
** RETURNS            :
145
**
146
----------------------------------------------------------------------------*/
147
 
148
void QmDialogLoadExternalTeams::createWindow(void)
149
{
150
    bad_cat = 0;
151
    bad_refs = 0;
152
 
221 - 153
    resize(550, 500);
154
    setSizeGripEnabled(true);
145 - 155
    setWindowTitle("Load External Team Data");
156
 
221 - 157
    QVBoxLayout *verticalLayout;
158
    verticalLayout = new QVBoxLayout(this);
159
    verticalLayout->setContentsMargins(0, 0, 0, 0);
160
 
223 - 161
    QVBoxLayout *verticalLayout2;
380 david 162
    verticalLayout2 = new QVBoxLayout();
223 - 163
    verticalLayout2->setContentsMargins(5, 5, 5, 5);
164
 
221 - 165
    QHBoxLayout *horizontalLayout;
166
    horizontalLayout = new QHBoxLayout();
167
 
168
    groupBox = new QGroupBox(this);
169
    groupBox->setTitle("Data");
224 - 170
    verticalLayout->addWidget(groupBox);
171
    groupBox->setLayout(verticalLayout2);
221 - 172
 
224 - 173
    tableWidget = new QTableWidget(groupBox);
174
    tableWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
175
    tableWidget->setGeometry(QRect(15, 21, 501, 421));
176
    tableWidget->setCornerButtonEnabled(false);
177
    tableWidget->verticalHeader()->setVisible(false);
178
    tableWidget->verticalHeader()->setDefaultSectionSize(20);
179
    tableWidget->verticalHeader()->setHighlightSections(true);
180
    verticalLayout2->addWidget(tableWidget);
221 - 181
 
182
    fileName = new QLineEdit(this);
183
    fileName->setObjectName(QString::fromUtf8("fileName"));
184
    fileName->setGeometry(QRect(20, 470, 331, 20));
185
    fileName->setReadOnly(true);
186
    horizontalLayout->addWidget(fileName);
187
 
188
    load = new QPushButton(this);
189
    load->setObjectName(QString::fromUtf8("load"));
190
    load->setGeometry(QRect(370, 470, 75, 23));
191
    load->setText("Load");
192
    horizontalLayout->addWidget(load);
193
 
194
    cancel = new QPushButton(this);
195
    cancel->setObjectName(QString::fromUtf8("cancel"));
196
    cancel->setGeometry(QRect(460, 470, 75, 23));
197
    cancel->setAutoDefault(false);
198
    cancel->setText("Cancel");
199
    horizontalLayout->addWidget(cancel);
200
 
201
    verticalLayout->addLayout(horizontalLayout);
202
 
149 - 203
    // Insert column headers
221 - 204
    tableWidget->setColumnCount(3 + ( 2 * config.num_legs) );
149 - 205
    QStringList labels;
206
    labels << "Team" << "Team Name" << "Cat";
207
    for (int ii = 1; ii <= config.num_legs; ii++ )
208
    {
209
        labels += QString("Leg:%1").arg(QString::number(ii));
151 david 210
        labels += QString("Age:%1").arg(QString::number(ii));
149 - 211
    }
221 - 212
    tableWidget->setHorizontalHeaderLabels(labels);
380 david 213
 
145 - 214
 
380 david 215
    // Connect up buttons
216
    connect (load, SIGNAL(clicked()), this, SLOT(loadData()));
217
    connect(cancel, SIGNAL(clicked()), this, SLOT(close()));
218
}
219
 
220
/*----------------------------------------------------------------------------
221
** FUNCTION           : insertParts
222
**
223
** DESCRIPTION        : Insert raw data into the display table
224
**
225
**
226
** INPUTS             : parts           - Ref to a list of parts
227
**                      has_RefError    - Data has Ref Error
228
**
229
** RETURNS            :
230
**
231
----------------------------------------------------------------------------*/
232
 
233
void QmDialogLoadExternalTeams::insertParts(QStringList &parts, bool has_RefError)
234
{
235
    QString first = parts.value(0);
236
    bool ok;
237
    if ( first.isEmpty() )
238
        return;
239
 
240
    int team = first.toInt(&ok);
241
    if ( ! ok || team <= 0 )
242
        return;
243
 
244
    int ii = tableWidget->rowCount();
245
    tableWidget->setRowCount(1 + ii );
246
 
247
    // Insert Team number
248
    QTableWidgetItem *item = new QTableWidgetItem(first);
249
    tableWidget->setItem(ii, 0, item );
250
    parts.removeFirst();
251
    if ( has_RefError )
145 - 252
    {
380 david 253
        item->setBackgroundColor(QColor(0,0,200,50));
254
        bad_refs++;
255
    }
145 - 256
 
380 david 257
    // Extract Team Name
258
    item = new QTableWidgetItem( parts.value(0) );
259
    tableWidget->setItem(ii, 1, item );
260
    if ( hasRefError(parts.value(0)) )
261
    {
262
        item->setBackgroundColor(QColor(0,0,200,50));
263
    }
264
    parts.removeFirst();
145 - 265
 
380 david 266
    // Extract Team Cat
267
    item = new QTableWidgetItem( parts.value(0)) ;
268
    tableWidget->setItem(ii, 2, item );
145 - 269
 
380 david 270
    if (config.lookup_class(qPrintable(parts.value(0)) ) <= 0 )
271
    {
272
        item->setBackgroundColor(QColor(200,0,0,50));
273
        bad_cat++;
274
    }
275
    if ( hasRefError(parts.value(0)) )
276
    {
277
        item->setBackgroundColor(QColor(0,0,200,50));
278
    }
279
    parts.removeFirst();
145 - 280
 
380 david 281
    int yy = 0;
282
    while ( parts.count() > 0)
283
    {
284
        // Name of competitor
285
        item = new QTableWidgetItem( parts.value(0));
286
        tableWidget->setItem(ii, 3+yy, item);
287
        if ( hasRefError(parts.value(0)) )
148 - 288
        {
380 david 289
            item->setBackgroundColor(QColor(0,0,200,50));
148 - 290
        }
291
        parts.removeFirst();
292
 
145 - 293
 
380 david 294
        // Not loading age at the moment
295
        // Reason: The CSV file is being create with a '0' for the NE teams
224 - 296
#if DO_AGE_LOAD
380 david 297
        // Posible age - if its a number
298
        int age = parts.value(0).toInt(&ok);
299
        if ( ok )
300
        {
301
            if ( age > 0 )
224 - 302
            {
380 david 303
                tableWidget->setItem(ii, 4+yy, new QTableWidgetItem( parts.value(0)));
224 - 304
            }
380 david 305
            parts.removeFirst();
306
        }
224 - 307
#endif
380 david 308
        yy += 2;
224 - 309
    }
380 david 310
 
144 - 311
}
380 david 312
/*----------------------------------------------------------------------------
313
** FUNCTION           : ~QmDialogLoadExternalTeams
314
**
315
** DESCRIPTION        : Class destructor
316
**
317
**
318
** INPUTS             :
319
**
320
** RETURNS            :
321
**
322
----------------------------------------------------------------------------*/
144 - 323
 
324
QmDialogLoadExternalTeams::~QmDialogLoadExternalTeams()
325
{
221 - 326
 
144 - 327
}
146 david 328
 
380 david 329
/*----------------------------------------------------------------------------
330
** FUNCTION           : loadData
331
**
332
** DESCRIPTION        : Store the data from the table into the database
333
**
334
**
335
** INPUTS             :
336
**
337
** RETURNS            :
338
**
339
----------------------------------------------------------------------------*/
340
 
146 david 341
void QmDialogLoadExternalTeams::loadData(void)
342
{
343
    qDebug ("LoadData");
344
    team_type team_buf;
148 - 345
    int bad_cat = 0;
380 david 346
    int bad_refs = 0;
221 - 347
    for ( int ii = 0; ii < tableWidget->rowCount(); ii++)
146 david 348
    {
221 - 349
        if ( tableWidget->isRowHidden(ii))
148 - 350
        {
351
            continue;
352
        }
353
        bool bad = false;
146 david 354
        QTableWidgetItem *item;
221 - 355
        item = tableWidget->item(ii,0);
146 david 356
        if (item)
357
        {
358
            int team = item->data(Qt::EditRole).toInt();
359
            if ( team > 0 && team <= config.max_team )
360
            {
361
                g_record( team, &team_buf );
362
 
363
                // Name
221 - 364
                item = tableWidget->item(ii,1);
146 david 365
                if (item)
366
                {
367
                    strncpy(team_buf.name , qPrintable(item->data(Qt::EditRole).toString()), sizeof(team_buf.name));
368
                }
369
 
370
                // Category
221 - 371
                item = tableWidget->item(ii,2);
146 david 372
                if (item)
373
                {
176 - 374
                    int category = config.lookup_class(qPrintable(item->data(Qt::EditRole).toString()) );
146 david 375
                    if (category)
376
                    {
377
                        team_buf.teamclass = category;
378
                    }
148 - 379
                    else
380
                    {
381
                        bad_cat++;
382
                        bad = true;
383
                    }
146 david 384
                }
385
 
386
                // Team member names and ages
387
                int member = 0;
221 - 388
                for (int yy = 3; yy < tableWidget->columnCount(); yy+= 2, member++)
146 david 389
                {
147 david 390
                    if (member > config.num_legs)
391
                    {
392
                        break;
393
                    }
221 - 394
                    item = tableWidget->item(ii,yy);
146 david 395
                    if (item)
396
                    {
397
                        strncpy(team_buf.members[member].name , qPrintable(item->data(Qt::EditRole).toString()), sizeof(team_buf.members[member].name));
380 david 398
                        if ( hasRefError(item->data(Qt::EditRole).toString()) )
399
                        {
400
                            bad = true;
401
                            bad_refs++;
402
                        }
146 david 403
                    }
221 - 404
                    item = tableWidget->item(ii,1+yy);
146 david 405
                    if (item)
406
                    {
407
                        int age = item->data(Qt::EditRole).toInt();
408
                        if (age)
409
                        {
410
                            team_buf.members[member].age = age;
411
                        }
412
                    }
413
                }
414
 
380 david 415
                team_buf.flags.valid = TRUE;
146 david 416
                put_team_record( team, &team_buf );
417
            }
148 - 418
            else
419
            {
420
                bad = true;
421
            }
146 david 422
        }
148 - 423
        else
424
        {
425
            bad = true;
426
        }
427
        if (!bad)
428
        {
221 - 429
            tableWidget->hideRow(ii);
148 - 430
        }
146 david 431
    }
148 - 432
 
433
    // Report errors
380 david 434
    reportErrors( bad_cat, bad_refs);
435
}
436
 
437
/*----------------------------------------------------------------------------
438
** FUNCTION           : reportErrors
439
**
440
** DESCRIPTION        : Report errors on the main window
441
**
442
**
443
** INPUTS             : bad_cat - count of category erors
444
**                      bad_refs - count of Reference errors
445
**
446
** RETURNS            :
447
**
448
----------------------------------------------------------------------------*/
449
 
450
void QmDialogLoadExternalTeams::reportErrors( int bad_cat, int bad_refs )
451
{
452
    if ( bad_cat && bad_refs )
148 - 453
    {
380 david 454
        MainWindow::showMessage("Invalid Categories in data and bad REFs");
455
    }
456
    else if (bad_cat)
457
    {
148 - 458
        MainWindow::showMessage("Invalid Categories in data");
459
    }
380 david 460
    else if (bad_refs)
461
    {
462
        MainWindow::showMessage("Imported data has bad REFs");
463
    }
464
 
146 david 465
}
149 - 466
 
467
/*========================================================================
468
 *
469
 *  Generate team name file
470
 *
471
 *  Purpose:
472
 *      This function is called to Generate team name file in the format
473
 *      that can be read by the load command
474
 *
475
 *      The file contains team number,Team name,Team class
476
 *      The operator is prompted to enter the name of the file
477
 *
478
 *  Parameters:
479
 *      None
480
 *
481
 *  Returns:
482
 *      Nothing
483
 *
484
 *========================================================================*/
485
void QmDialogLoadExternalTeams::storeData(const QString &efile)
486
{
487
    QFile file(efile);
488
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) )
489
    {
490
        MainWindow::showMessage("Cannot open external data file");
491
        return;
492
    }
493
    QTextStream out(&file);
494
 
495
    // Print headings
151 david 496
    out << toCsv("Team Number");
497
    out << "," << toCsv("Team Name");
498
    out << "," <<  toCsv("Class Abr");
149 - 499
 
500
    for( int j = 1; j <= config.num_legs; j++ )
501
    {
151 david 502
        out << "," << toCsv("Competitor Name");
503
        out << "," << toCsv("Age");
149 - 504
    }
505
    out << endl;
506
 
507
    /*
508
     * Put the data into the file
509
     */
170 - 510
    team_type   team_buf;
149 - 511
    for(int i = config.min_team; i <= config.max_team; i++ )
512
    {
513
        if( valid_field( i ) && g_record( i, &team_buf ) )
514
        {
515
            /*
516
            **  Basic information
517
            **      - Team number
518
            **      - Full team name
519
            */
151 david 520
            out << toCsv(team_buf.numb);
521
            out << "," << toCsv(team_buf.name);
522
            out << "," << toCsv(team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr);
149 - 523
 
524
            for(int j = 1; j <= config.num_legs; j++ )
525
            {
151 david 526
                out << "," << toCsv(team_buf.members[j-1].name);
527
                out << "," << toCsv(team_buf.members[j-1].age);
149 - 528
            }
529
            out <<endl;
530
        }
531
    }
532
}
151 david 533
 
534
QStringList QmDialogLoadExternalTeams::splitCsvData( const QString str)
535
{
536
    QStringList results;
537
 
538
    const QChar *data = str.constData();
539
    while (!data->isNull())
540
    {
541
        QString result;
542
        bool quoted = false;
543
        /*
544
        **  Extract the next record
545
        */
546
        while ( TRUE )
547
        {
548
            QChar uch = *data;
549
 
550
            /*
551
            **  End of the field
552
            */
384 david 553
            if ( uch == '\n' || uch == '\r' || uch == 0 )
151 david 554
                break;
555
 
556
            data++;
557
 
558
            /*
559
            ** Ugly character from MS CSV files
380 david 560
            ** Not too sure what the 194 is. It looks like a 0xA0 in the raw data
151 david 561
            */
380 david 562
            if ( uch == (char) 0xA0 || uch == (char)194 )
151 david 563
            {
564
                continue;
565
            }
566
 
567
            if ( !quoted && uch == ',' )
568
            {
569
                break;
570
            }
571
 
572
            /*
573
            **  An unquoted " will start scanning for a matching quote
574
            */
575
            if ( !quoted && uch == '"' )
576
            {
577
                quoted = true;
578
                continue;
579
            }
580
 
581
            /*
582
            **  A quoted " may be an embedded quote or the end of a quote
583
            */
584
            if ( quoted && uch == '"' )
585
            {
586
                if ( *data != '"' )
587
                {
588
                    quoted = FALSE;
589
                    continue;
590
                }
591
 
592
                /*
593
                **  Skip one " and pick up the next
594
                */
595
                ++data;
596
            }
597
 
598
            /*
599
            **  Save this character
600
            */
601
            result += uch;
602
        }
603
 
604
        /*
605
        **  Clean up the extracted string
606
        */
607
        results += result.trimmed();
380 david 608
    }
151 david 609
    return results;
610
}
380 david 611
/*----------------------------------------------------------------------------
612
** FUNCTION           : hasRefError
613
**
614
** DESCRIPTION        : Determine if a string contains an Excel Reference
615
**                      error: #REF!
616
**
617
**
618
** INPUTS             : data - String to test
619
**
620
** RETURNS            : True: Is an error
621
**
622
----------------------------------------------------------------------------*/
151 david 623
 
380 david 624
bool QmDialogLoadExternalTeams::hasRefError( const QString data)
625
{
626
    return data.contains("#REF!");
627
}
628
 
152 david 629
/*========================================================================
630
 *
631
 *  Generate team name file
632
 *
633
 *  Purpose:
634
 *      This function is called to Generate team name file
635
 *
636
 *      The file contains team number,Team name,Team class
637
 *      The operator is prompted to enter the name of the file
638
 *
639
 *  Parameters:
640
 *      None
641
 *
642
 *  Returns:
643
 *      Nothing
644
 *
645
 *========================================================================*/
646
 
647
void QmDialogLoadExternalTeams::storeTeamInfo(const QString &efile)
648
{
649
    QFile file(efile);
650
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) )
651
    {
652
        MainWindow::showMessage("Cannot open external team info file");
653
        return;
654
    }
655
    QTextStream out(&file);
656
 
380 david 657
    /*
152 david 658
     * Put the data into the file
659
     */
170 - 660
    team_type   team_buf;
152 david 661
    for(int i = config.min_team; i <= config.max_team; i++ )
662
    {
663
        if( valid_field( i ) && g_record( i, &team_buf ) )
664
        {
665
            /*
666
            **  Basic information
667
            **      - Team number
668
            **      - Full team name
669
            **      - Category
670
            */
671
            out.setFieldAlignment(QTextStream::AlignLeft);
672
            out.setFieldWidth(5);
673
            out << team_buf.numb;
674
            out.setFieldWidth(0);
675
            out << ",";
676
            out.setFieldWidth(MAX_TM_NAME+1);
677
            out << team_buf.name;
678
            out.setFieldWidth(0);
679
            out << ",";
680
            out << (team_buf.teamclass <= 0 ? "" : config.team_class[team_buf.teamclass - 1].abr);
681
            out <<endl;
682
        }
683
    }
684
}
685
 
151 david 686
QString QmDialogLoadExternalTeams::toCsv(const QString &str)
687
{
688
    QString result = QString(str);
689
    if ( result.contains("\"") || result.contains(",") )
690
    {
691
        result.replace("\"", "\"\"");
692
        result.prepend("\"");
693
        result.append("\"");
694
    }
695
    return result;
696
}
697
 
698
QString QmDialogLoadExternalTeams::toCsv(const int data)
699
{
700
    return QString::number(data);
701
}