Subversion Repositories svn1-original

Rev

Details | Last modification | View Log | RSS feed

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