Subversion Repositories svn1-original

Rev

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