Subversion Repositories svn1

Rev

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