Subversion Repositories svn1

Rev

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

Rev Author Line No. Line
144 - 1
#include "qmdialogloadexternalteams.h"
145 - 2
#include "QFile"
3
#include "QTextStream"
4
#include "mainwindow.h"
384 david 5
#include <QHBoxLayout>
6
#include <QVBoxLayout>
7
#include <QWidget>
380 david 8
#include <QHeaderView>
384 david 9
#include <QWebEngineHistory>
10
#include <QWebEngineHistoryItem>
11
#include <QWebEnginePage>
12
#include <QWebEngineView>
145 - 13
#include    "consts.h"
14
#include    "structs.h"
15
#include    "proto.h"
16
 
380 david 17
/*----------------------------------------------------------------------------
18
** FUNCTION           : QmDialogLoadExternalTeams
19
**
20
** DESCRIPTION        : Load team data from a CSV file
21
**
22
**
23
** INPUTS             : efile       - name of file
24
**                      parent      - parent widget
25
**
26
** RETURNS            :
27
**
28
----------------------------------------------------------------------------*/
29
 
145 - 30
QmDialogLoadExternalTeams::QmDialogLoadExternalTeams(const QString &efile,QWidget *parent) :
380 david 31
        QDialog(parent)
224 - 32
{
221 - 33
 
34
    //
35
    // Create Windows
36
    //
380 david 37
    createWindow();
38
    fileName->setText(efile);
39
 
40
    // Open the users file
41
 
42
    QFile file(efile);
43
    if ( ! file.open(QIODevice::ReadOnly | QIODevice::Text) )
44
    {
45
        MainWindow::showMessage("Cannot open external data file");
46
        return;
47
    }
48
    MainWindow::showMessage("Loading External Data");
49
 
50
    // Process Each line of the file
51
    QTextStream in(&file);
52
    while (!in.atEnd())
53
    {
54
        QString line = in.readLine();
55
        line = line.trimmed();             // Remove leading and training White Space
387 david 56
        line.remove(QChar(0xA0));          // M$ special uglyness
57
        line.remove(QChar(0xC2));                 // M$ special uglyness
380 david 58
 
59
        bool has_RefError = hasRefError(line);
60
        QStringList parts = splitCsvData(line);
61
        insertParts( parts, has_RefError );
62
 
63
    }
64
 
65
    // Post Load fix up
66
    tableWidget->resizeColumnsToContents();
67
    reportErrors( bad_cat, bad_refs);
68
}
69
 
70
/*----------------------------------------------------------------------------
71
** FUNCTION           : QmDialogLoadExternalTeams
72
**
73
** DESCRIPTION        : Load team data from a Web Page
74
**
75
**
76
** INPUTS             : efile       - name of file (display only)
77
**                      data        - Address of the webpage data loaded in memory
78
**                      parent      - parent widget
79
**
80
** RETURNS            :
81
**
82
----------------------------------------------------------------------------*/
83
 
84
QmDialogLoadExternalTeams::QmDialogLoadExternalTeams(const QString &efile, QByteArray *data ,QWidget *parent) :
85
        QDialog(parent)
86
{
390 david 87
 
88
    Q_UNUSED(data);
89
 
380 david 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
 
387 david 247
    // Reuse a brush
248
    QBrush brush = QBrush(QColor(0,0,200,50));
249
    QBrush brushRed = QBrush(QColor(200,0,0,50));
250
 
251
 
380 david 252
    // Insert Team number
253
    QTableWidgetItem *item = new QTableWidgetItem(first);
254
    tableWidget->setItem(ii, 0, item );
255
    parts.removeFirst();
256
    if ( has_RefError )
145 - 257
    {
387 david 258
        item->setBackground(brush);
380 david 259
        bad_refs++;
260
    }
145 - 261
 
380 david 262
    // Extract Team Name
263
    item = new QTableWidgetItem( parts.value(0) );
264
    tableWidget->setItem(ii, 1, item );
265
    if ( hasRefError(parts.value(0)) )
266
    {
387 david 267
        item->setBackground(brush);
380 david 268
    }
269
    parts.removeFirst();
145 - 270
 
380 david 271
    // Extract Team Cat
272
    item = new QTableWidgetItem( parts.value(0)) ;
273
    tableWidget->setItem(ii, 2, item );
145 - 274
 
380 david 275
    if (config.lookup_class(qPrintable(parts.value(0)) ) <= 0 )
276
    {
387 david 277
        item->setBackground(brushRed);
380 david 278
        bad_cat++;
279
    }
280
    if ( hasRefError(parts.value(0)) )
281
    {
387 david 282
        item->setBackground(brush);
380 david 283
    }
284
    parts.removeFirst();
145 - 285
 
380 david 286
    int yy = 0;
287
    while ( parts.count() > 0)
288
    {
289
        // Name of competitor
290
        item = new QTableWidgetItem( parts.value(0));
291
        tableWidget->setItem(ii, 3+yy, item);
292
        if ( hasRefError(parts.value(0)) )
148 - 293
        {
387 david 294
            item->setBackground(brush);
148 - 295
        }
296
        parts.removeFirst();
297
 
145 - 298
 
380 david 299
        // Not loading age at the moment
300
        // Reason: The CSV file is being create with a '0' for the NE teams
224 - 301
#if DO_AGE_LOAD
380 david 302
        // Posible age - if its a number
303
        int age = parts.value(0).toInt(&ok);
304
        if ( ok )
305
        {
306
            if ( age > 0 )
224 - 307
            {
380 david 308
                tableWidget->setItem(ii, 4+yy, new QTableWidgetItem( parts.value(0)));
224 - 309
            }
380 david 310
            parts.removeFirst();
311
        }
224 - 312
#endif
380 david 313
        yy += 2;
224 - 314
    }
380 david 315
 
144 - 316
}
380 david 317
/*----------------------------------------------------------------------------
318
** FUNCTION           : ~QmDialogLoadExternalTeams
319
**
320
** DESCRIPTION        : Class destructor
321
**
322
**
323
** INPUTS             :
324
**
325
** RETURNS            :
326
**
327
----------------------------------------------------------------------------*/
144 - 328
 
329
QmDialogLoadExternalTeams::~QmDialogLoadExternalTeams()
330
{
221 - 331
 
144 - 332
}
146 david 333
 
380 david 334
/*----------------------------------------------------------------------------
335
** FUNCTION           : loadData
336
**
337
** DESCRIPTION        : Store the data from the table into the database
338
**
339
**
340
** INPUTS             :
341
**
342
** RETURNS            :
343
**
344
----------------------------------------------------------------------------*/
345
 
146 david 346
void QmDialogLoadExternalTeams::loadData(void)
347
{
348
    qDebug ("LoadData");
349
    team_type team_buf;
148 - 350
    int bad_cat = 0;
380 david 351
    int bad_refs = 0;
221 - 352
    for ( int ii = 0; ii < tableWidget->rowCount(); ii++)
146 david 353
    {
221 - 354
        if ( tableWidget->isRowHidden(ii))
148 - 355
        {
356
            continue;
357
        }
358
        bool bad = false;
146 david 359
        QTableWidgetItem *item;
221 - 360
        item = tableWidget->item(ii,0);
146 david 361
        if (item)
362
        {
363
            int team = item->data(Qt::EditRole).toInt();
364
            if ( team > 0 && team <= config.max_team )
365
            {
366
                g_record( team, &team_buf );
367
 
368
                // Name
221 - 369
                item = tableWidget->item(ii,1);
146 david 370
                if (item)
371
                {
372
                    strncpy(team_buf.name , qPrintable(item->data(Qt::EditRole).toString()), sizeof(team_buf.name));
373
                }
374
 
375
                // Category
221 - 376
                item = tableWidget->item(ii,2);
146 david 377
                if (item)
378
                {
176 - 379
                    int category = config.lookup_class(qPrintable(item->data(Qt::EditRole).toString()) );
146 david 380
                    if (category)
381
                    {
382
                        team_buf.teamclass = category;
383
                    }
148 - 384
                    else
385
                    {
386
                        bad_cat++;
387
                        bad = true;
388
                    }
146 david 389
                }
390
 
391
                // Team member names and ages
392
                int member = 0;
221 - 393
                for (int yy = 3; yy < tableWidget->columnCount(); yy+= 2, member++)
146 david 394
                {
147 david 395
                    if (member > config.num_legs)
396
                    {
397
                        break;
398
                    }
221 - 399
                    item = tableWidget->item(ii,yy);
146 david 400
                    if (item)
401
                    {
402
                        strncpy(team_buf.members[member].name , qPrintable(item->data(Qt::EditRole).toString()), sizeof(team_buf.members[member].name));
380 david 403
                        if ( hasRefError(item->data(Qt::EditRole).toString()) )
404
                        {
405
                            bad = true;
406
                            bad_refs++;
407
                        }
146 david 408
                    }
221 - 409
                    item = tableWidget->item(ii,1+yy);
146 david 410
                    if (item)
411
                    {
412
                        int age = item->data(Qt::EditRole).toInt();
413
                        if (age)
414
                        {
415
                            team_buf.members[member].age = age;
416
                        }
417
                    }
418
                }
419
 
380 david 420
                team_buf.flags.valid = TRUE;
146 david 421
                put_team_record( team, &team_buf );
422
            }
148 - 423
            else
424
            {
425
                bad = true;
426
            }
146 david 427
        }
148 - 428
        else
429
        {
430
            bad = true;
431
        }
432
        if (!bad)
433
        {
221 - 434
            tableWidget->hideRow(ii);
148 - 435
        }
146 david 436
    }
148 - 437
 
438
    // Report errors
380 david 439
    reportErrors( bad_cat, bad_refs);
440
}
441
 
442
/*----------------------------------------------------------------------------
443
** FUNCTION           : reportErrors
444
**
445
** DESCRIPTION        : Report errors on the main window
446
**
447
**
448
** INPUTS             : bad_cat - count of category erors
449
**                      bad_refs - count of Reference errors
450
**
451
** RETURNS            :
452
**
453
----------------------------------------------------------------------------*/
454
 
455
void QmDialogLoadExternalTeams::reportErrors( int bad_cat, int bad_refs )
456
{
457
    if ( bad_cat && bad_refs )
148 - 458
    {
380 david 459
        MainWindow::showMessage("Invalid Categories in data and bad REFs");
460
    }
461
    else if (bad_cat)
462
    {
148 - 463
        MainWindow::showMessage("Invalid Categories in data");
464
    }
380 david 465
    else if (bad_refs)
466
    {
467
        MainWindow::showMessage("Imported data has bad REFs");
468
    }
469
 
146 david 470
}
149 - 471
 
472
/*========================================================================
473
 *
474
 *  Generate team name file
475
 *
476
 *  Purpose:
477
 *      This function is called to Generate team name file in the format
478
 *      that can be read by the load command
479
 *
480
 *      The file contains team number,Team name,Team class
481
 *      The operator is prompted to enter the name of the file
482
 *
483
 *  Parameters:
484
 *      None
485
 *
486
 *  Returns:
487
 *      Nothing
488
 *
489
 *========================================================================*/
490
void QmDialogLoadExternalTeams::storeData(const QString &efile)
491
{
492
    QFile file(efile);
493
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) )
494
    {
495
        MainWindow::showMessage("Cannot open external data file");
496
        return;
497
    }
498
    QTextStream out(&file);
499
 
500
    // Print headings
151 david 501
    out << toCsv("Team Number");
502
    out << "," << toCsv("Team Name");
503
    out << "," <<  toCsv("Class Abr");
149 - 504
 
505
    for( int j = 1; j <= config.num_legs; j++ )
506
    {
151 david 507
        out << "," << toCsv("Competitor Name");
508
        out << "," << toCsv("Age");
149 - 509
    }
387 david 510
    out << Qt::endl;
149 - 511
 
512
    /*
513
     * Put the data into the file
514
     */
170 - 515
    team_type   team_buf;
149 - 516
    for(int i = config.min_team; i <= config.max_team; i++ )
517
    {
518
        if( valid_field( i ) && g_record( i, &team_buf ) )
519
        {
520
            /*
521
            **  Basic information
522
            **      - Team number
523
            **      - Full team name
524
            */
151 david 525
            out << toCsv(team_buf.numb);
526
            out << "," << toCsv(team_buf.name);
527
            out << "," << toCsv(team_buf.teamclass == 0 ? "" : config.team_class[team_buf.teamclass - 1].abr);
149 - 528
 
529
            for(int j = 1; j <= config.num_legs; j++ )
530
            {
151 david 531
                out << "," << toCsv(team_buf.members[j-1].name);
532
                out << "," << toCsv(team_buf.members[j-1].age);
149 - 533
            }
387 david 534
            out <<Qt::endl;
149 - 535
        }
536
    }
537
}
151 david 538
 
539
QStringList QmDialogLoadExternalTeams::splitCsvData( const QString str)
540
{
541
    QStringList results;
542
 
543
    const QChar *data = str.constData();
544
    while (!data->isNull())
545
    {
546
        QString result;
547
        bool quoted = false;
548
        /*
549
        **  Extract the next record
550
        */
551
        while ( TRUE )
552
        {
553
            QChar uch = *data;
554
 
555
            /*
556
            **  End of the field
557
            */
384 david 558
            if ( uch == '\n' || uch == '\r' || uch == 0 )
151 david 559
                break;
560
 
561
            data++;
562
 
563
            /*
564
            ** Ugly character from MS CSV files
380 david 565
            ** Not too sure what the 194 is. It looks like a 0xA0 in the raw data
151 david 566
            */
380 david 567
            if ( uch == (char) 0xA0 || uch == (char)194 )
151 david 568
            {
569
                continue;
570
            }
571
 
572
            if ( !quoted && uch == ',' )
573
            {
574
                break;
575
            }
576
 
577
            /*
578
            **  An unquoted " will start scanning for a matching quote
579
            */
580
            if ( !quoted && uch == '"' )
581
            {
582
                quoted = true;
583
                continue;
584
            }
585
 
586
            /*
587
            **  A quoted " may be an embedded quote or the end of a quote
588
            */
589
            if ( quoted && uch == '"' )
590
            {
591
                if ( *data != '"' )
592
                {
593
                    quoted = FALSE;
594
                    continue;
595
                }
596
 
597
                /*
598
                **  Skip one " and pick up the next
599
                */
600
                ++data;
601
            }
602
 
603
            /*
604
            **  Save this character
605
            */
606
            result += uch;
607
        }
608
 
609
        /*
610
        **  Clean up the extracted string
611
        */
612
        results += result.trimmed();
380 david 613
    }
151 david 614
    return results;
615
}
380 david 616
/*----------------------------------------------------------------------------
617
** FUNCTION           : hasRefError
618
**
619
** DESCRIPTION        : Determine if a string contains an Excel Reference
620
**                      error: #REF!
621
**
622
**
623
** INPUTS             : data - String to test
624
**
625
** RETURNS            : True: Is an error
626
**
627
----------------------------------------------------------------------------*/
151 david 628
 
380 david 629
bool QmDialogLoadExternalTeams::hasRefError( const QString data)
630
{
631
    return data.contains("#REF!");
632
}
633
 
152 david 634
/*========================================================================
635
 *
636
 *  Generate team name file
637
 *
638
 *  Purpose:
639
 *      This function is called to Generate team name file
640
 *
641
 *      The file contains team number,Team name,Team class
642
 *      The operator is prompted to enter the name of the file
643
 *
644
 *  Parameters:
645
 *      None
646
 *
647
 *  Returns:
648
 *      Nothing
649
 *
650
 *========================================================================*/
651
 
652
void QmDialogLoadExternalTeams::storeTeamInfo(const QString &efile)
653
{
654
    QFile file(efile);
655
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) )
656
    {
657
        MainWindow::showMessage("Cannot open external team info file");
658
        return;
659
    }
660
    QTextStream out(&file);
661
 
380 david 662
    /*
152 david 663
     * Put the data into the file
664
     */
170 - 665
    team_type   team_buf;
152 david 666
    for(int i = config.min_team; i <= config.max_team; i++ )
667
    {
668
        if( valid_field( i ) && g_record( i, &team_buf ) )
669
        {
670
            /*
671
            **  Basic information
672
            **      - Team number
673
            **      - Full team name
674
            **      - Category
675
            */
676
            out.setFieldAlignment(QTextStream::AlignLeft);
677
            out.setFieldWidth(5);
678
            out << team_buf.numb;
679
            out.setFieldWidth(0);
680
            out << ",";
681
            out.setFieldWidth(MAX_TM_NAME+1);
682
            out << team_buf.name;
683
            out.setFieldWidth(0);
684
            out << ",";
685
            out << (team_buf.teamclass <= 0 ? "" : config.team_class[team_buf.teamclass - 1].abr);
387 david 686
            out <<Qt::endl;
152 david 687
        }
688
    }
689
}
690
 
151 david 691
QString QmDialogLoadExternalTeams::toCsv(const QString &str)
692
{
693
    QString result = QString(str);
694
    if ( result.contains("\"") || result.contains(",") )
695
    {
696
        result.replace("\"", "\"\"");
697
        result.prepend("\"");
698
        result.append("\"");
699
    }
700
    return result;
701
}
702
 
703
QString QmDialogLoadExternalTeams::toCsv(const int data)
704
{
705
    return QString::number(data);
706
}