Subversion Repositories svn1-original

Rev

Rev 213 | Rev 222 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
176 - 1
#include "qmconfig.h"
2
#include "mainwindow.h"
3
#include <QFileDialog>
4
#include <QObject>
5
#include <QMessageBox>
178 - 6
#include <QFileInfo>
7
#include <QFile>
203 david 8
#include <QCoreApplication>
176 - 9
 
214 - 10
//#define DISPLAY_STRUCTURES
212 - 11
 
176 - 12
// Global Data
180 - 13
QmConfig    config;
176 - 14
 
180 - 15
 
178 - 16
/*
17
**  Local definitions
18
*/
19
char        datfile[20];                         /* Name of the data file */
20
char        filebase[20];                        /* Event file name base */
202 - 21
char        filepath[300];
203 david 22
char        addendumFilepath[300];
176 - 23
 
203 david 24
 
180 - 25
void QmConfig::load(const QString &cnfFile)
176 - 26
{
212 - 27
#ifdef DISPLAY_STRUCTURES
28
    display_structures();
29
#endif
176 - 30
    fileName = cnfFile;
203 david 31
 
176 - 32
    if ( !fileName.endsWith(".cnf",Qt::CaseInsensitive))
33
    {
34
        fileName.append(".cnf");
35
    }
36
    if (cnfFile.isEmpty())
37
    {
38
        fileName = QFileDialog::getOpenFileName(0, "Select Config File",
178 - 39
                                                         filepath,
176 - 40
                                                         "Data (*.cnf);;All (*.*)",
41
                                                         0,
42
 
43
                                                         );
44
    }
45
 
46
    //  No file selected
47
    //  Just exit
48
    if (fileName.isEmpty())
49
    {
178 - 50
        qDebug("No Config file selected");
176 - 51
        exit(1);
52
    }
53
 
178 - 54
    //
55
    //  Setup ffile names
56
    //
57
    QFileInfo info (fileName);
58
    strncpy(filebase, qPrintable(info.baseName()), 8);
59
    strcpy( datfile, filebase );
60
    strcat( datfile, ".dat" );
61
 
62
    strncpy(filepath, qPrintable(info.absolutePath()), sizeof(filepath)-3);
63
    strcat(filepath, "/");
64
    qDebug("FilePath:%s", filepath );
65
 
176 - 66
    if ( !open_read_config() )
67
    {
68
        if (QMessageBox::Cancel == QMessageBox::question ( 0,
69
                                                       "Config Load Error",
70
                                                       "Cannot load or read configuration file.\n"
71
                                                       "If you continue a new configuration will be created\n"
72
                                                       "If you cancel then the application will terminate.",
73
                                                       QMessageBox::Ok | QMessageBox::Cancel
74
                                                       ) )
75
        {
178 - 76
            qDebug("Cancel to bad config");
176 - 77
            exit(2);
78
        }
79
    }
80
}
81
 
82
 
83
bool QmConfig::open_read_config( void )
84
{
85
    bool result;
86
    // Open the file
180 - 87
    QFile configFile;
176 - 88
    configFile.setFileName(fileName);
89
    if ( ! configFile.open(QIODevice::ReadOnly) )
90
    {
91
        MainWindow::showMessage("Cannot open config File");
92
        return (false );
93
    }
94
 
180 - 95
    result = read_config(configFile);
176 - 96
    configFile.close();
97
 
98
    if ( result )
99
    {
100
        /*
101
         **  Post read calculations and fixups
102
         */
180 - 103
        if( datafilename[0] )
176 - 104
        {
180 - 105
            strcpy( datfile, datafilename );
176 - 106
            strcat( datfile, ".dat" );
107
        }
180 - 108
        nonequestrian_class = lookup_class( nonequestrian_class_abr );
176 - 109
    }
110
    return result;
111
}
112
 
113
/*========================================================================
114
 *
115
 *  Read in the configuration file
116
 *
117
 *  Purpose:
118
 *      This function is called to read in the configuration file
119
 *      NOTE: Must be maintained with the Writer function
120
 *
121
 *  Parameters:
122
 *      fcon        File number of the config file
123
 *
124
 *  Returns:
125
 *      FALSE if an error is encountered
126
 *
127
 *========================================================================*/
128
 
180 - 129
bool QmConfig::read_config( QFile &configFile  )
176 - 130
{
131
    int         len;                            /* Length of data read */
132
    int         fsize;                          /* Length of desired data */
133
 
134
    /*
135
     * Event name
136
     */
214 - 137
//qDebug( "Reading: Event Name" );
180 - 138
    fsize = sizeof( event_name );
139
    len = configFile.read( event_name, fsize );
176 - 140
    if( len != fsize )
141
        return ( FALSE );
142
 
143
    /*
144
     * Leg names
145
     */
214 - 146
//qDebug( "Reading: Leg Names" );
180 - 147
    fsize = sizeof( leg_name );
148
    len = configFile.read( (char *)leg_name, fsize );
176 - 149
    if( len != fsize )
150
        return ( FALSE );
151
 
152
    /*
153
     * Team definitions
154
     */
214 - 155
//qDebug( "Reading: Team Defs" );
180 - 156
    fsize = sizeof( t_def  );
157
    len = configFile.read( (char *)t_def, fsize );
176 - 158
    if( len != fsize )
159
        return ( FALSE );
160
 
161
    /*
162
     * Number of legs
163
     */
164
 
214 - 165
//qDebug( "Reading: Leg Nums" );
180 - 166
    fsize = sizeof( num_legs  );
167
    len = configFile.read( (char *)&num_legs, fsize );
176 - 168
    if( len != fsize)
169
        return ( FALSE );
170
 
171
    /*
172
     * Number of team splits
173
     */
174
 
214 - 175
//qDebug( "Reading: Team Splits" );
180 - 176
    fsize = sizeof( num_teams  );
177
    len = configFile.read( (char *)&num_teams, fsize );
176 - 178
    if( len != fsize )
179
        return ( FALSE );
180
 
180 - 181
    min_team = t_def[0].start;
182
    max_team = t_def[num_teams - 1].end;
176 - 183
 
184
    /*
185
     * Class information
186
     */
214 - 187
//qDebug( "Reading: Class Data" );
180 - 188
    fsize = sizeof( team_class  );
189
    len = configFile.read( (char *)team_class, fsize );
176 - 190
    if( len != fsize )
191
        return ( FALSE );
180 - 192
    fsize = sizeof( num_class  );
193
    len = configFile.read( (char *)&num_class, fsize);
176 - 194
    if( len != fsize )
195
        return ( FALSE );
196
 
197
    /*
198
     * Country list
199
     */
200
 
214 - 201
//qDebug( "Reading: Country Data, Name" );
180 - 202
    fsize = sizeof( country_name  );
203
    len = configFile.read( (char *)country_name, fsize );
176 - 204
    if( len != fsize )
205
        return ( FALSE );
206
 
214 - 207
//qDebug( "Reading: Country Data, Number" );
180 - 208
    fsize = sizeof( num_countries  );
209
    len = configFile.read( (char *)&num_countries, fsize );
176 - 210
    if( len != fsize )
211
        return ( FALSE );
212
 
213
    /*
214
     * Addendum file
215
     */
216
 
214 - 217
//qDebug( "Reading: Addendum File" );
180 - 218
    fsize = sizeof( addendum );
219
    len = configFile.read( addendum, fsize );
176 - 220
    if( len != fsize )
221
        return ( configFile.atEnd() );
222
 
223
    /*
224
     * Name of the data file
225
     */
226
 
214 - 227
//qDebug( "Reading: Name of data file" );
180 - 228
    fsize = sizeof( datafilename );
229
    len = configFile.read( datafilename, fsize );
176 - 230
    if( len != fsize )
231
        return ( configFile.atEnd() );
232
 
233
    /*
234
     **  Non-equestrian configuration information
235
     */
214 - 236
//qDebug( "Reading: NonEquest" );
180 - 237
    fsize = sizeof( nonequestrian_class_abr );
238
    len = configFile.read( nonequestrian_class_abr, fsize );
176 - 239
    if( len != fsize )
240
        return ( configFile.atEnd() );
241
 
214 - 242
//qDebug( "Reading: NonEquest-2" );
180 - 243
    fsize = sizeof( equestrian_leg );
244
    len = configFile.read( (char *)&equestrian_leg, fsize );
176 - 245
    if( len != fsize )
246
        return ( FALSE );
247
 
248
    /*
249
    **  .txt file output control. Lines per page and perf-skipping
250
    */
214 - 251
//qDebug( "Reading: Output Control" );
180 - 252
    fsize = sizeof( lines_per_page );
253
    len = configFile.read( (char *)&lines_per_page, fsize );
176 - 254
    if( len != fsize )
255
        return ( configFile.atEnd() );
256
 
214 - 257
//qDebug( "Reading: Output Control-2" );
180 - 258
    fsize = sizeof( perf_skip );
259
    len = configFile.read( (char *)&perf_skip, fsize );
176 - 260
    if( len != fsize )
261
        return ( FALSE );
262
 
214 - 263
//qDebug( "Reading: Winners Info" );
180 - 264
    fsize = sizeof( class_winners );
265
    len = configFile.read( (char *)&class_winners, fsize );
176 - 266
    if( len != fsize )
267
        return ( FALSE );
268
 
214 - 269
//qDebug( "Reading: Hall of Fame Info" );
180 - 270
    fsize = sizeof( hall_fame );
271
    len = configFile.read( (char *)&hall_fame, fsize );
176 - 272
    if( len != fsize )
273
        return ( FALSE );
274
 
214 - 275
//qDebug( "Reading: Hall of Fame Numbers" );
212 - 276
    fsize = sizeof( num_fame );
180 - 277
    len = configFile.read( (char *)&num_fame, fsize );
176 - 278
    if( len != fsize )
279
        return ( configFile.atEnd() );
280
 
281
 
282
    return ( TRUE );
283
}
284
 
203 david 285
/*----------------------------------------------------------------------------
286
** FUNCTION           : getAddendemFile
287
**
288
** DESCRIPTION        : Returns the full path the the addemdum file
289
**                      The functionwill lookfor the file in a number of
290
**                      locations
291
**
292
**
293
** INPUTS             : name    - Name of the addenum file
294
**                      create  - True. Allow file to be created
295
**
296
** RETURNS            : NULL    - No addendum name, or file not found
297
**                                If create' is true then the preferred
298
**                                location will be returned.
299
**
300
----------------------------------------------------------------------------*/
176 - 301
 
203 david 302
 
303
const char *QmConfig::getAddendemFile(const QString &name, bool create )
304
{
305
    if (name.isEmpty())
306
        return NULL;
307
 
308
    QFile file;
309
    QString addendumFileName;
310
    addendumFileName = filepath;
311
    addendumFileName.append(name);
312
    QString addendumFileNamePreferred(addendumFileName);
313
    file.setFileName(addendumFileName);
204 david 314
    //qDebug("Try:%s", qPrintable(addendumFileName));
203 david 315
    if ( !file.exists())
316
    {
317
        addendumFileName = QCoreApplication::applicationDirPath ();
318
        addendumFileName.append("/");
319
        addendumFileName.append(name);
320
        file.setFileName(addendumFileName);
204 david 321
        //qDebug("Try:%s", qPrintable(addendumFileName));
203 david 322
        if ( !file.exists())
323
        {
324
             addendumFileName = QDir::currentPath ();
325
             addendumFileName.append("/");
326
             addendumFileName.append(name);
327
             file.setFileName(addendumFileName);
204 david 328
             //qDebug("Try:%s", qPrintable(addendumFileName));
203 david 329
             if ( !file.exists())
330
             {
204 david 331
                 //qDebug("Addeddum File not found");
203 david 332
                 if (create)
333
                 {
334
                     addendumFileName = addendumFileNamePreferred;
335
                 }
336
                 else
337
                 {
338
                     return NULL;
339
                 }
340
             }
341
        }
342
    }
343
    strncpy(addendumFilepath, qPrintable(addendumFileName), sizeof(addendumFilepath));
344
    return addendumFilepath;
345
}
346
 
347
 
176 - 348
/*========================================================================
349
 *
350
 *  Write out the configuration file
351
 *
352
 *  Purpose:
353
 *      This function is called to write the configuration file
354
 *      NOTE: Must be maintained with the Reader function
355
 *
356
 *  Parameters:
357
 *      None
358
 *
359
 *  Returns:
360
 *      FALSE   : Error encountered
361
 *
362
 *========================================================================*/
363
 
364
bool QmConfig::write_config( void )
365
{
178 - 366
    if (fileName.isEmpty())
367
    {
368
        qDebug("No Config file selected");
369
        return(false);
370
    }
176 - 371
    /*
372
     **  Open as a binary file
373
     */
178 - 374
    QFile file;
375
    file.setFileName(fileName);
176 - 376
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate) )
377
    {
178 - 378
        qDebug("File error: %s", qPrintable(file.errorString()));
379
        MainWindow::showMessage("Cannot open config file");
176 - 380
        return (false);
381
    }
382
 
383
     /*
384
     **  Write out multiple structures
385
     **     Event name
386
     **     Leg names
387
     **     Team definitions
388
     **     Number of legs
389
     **     Number fo team splits
390
     **     Class information
391
     **     Number of defined classes
392
     **     Country list
393
     **     Number of defined countries
180 - 394
     **     Legend addendum file name
176 - 395
     **     Data file name
396
     */
397
 
180 - 398
    file.write( (const char *) event_name, sizeof( event_name ) );
399
    file.write( (const char *) leg_name, sizeof( leg_name ) );
400
    file.write( (const char *) t_def, sizeof( t_def ) );
401
    file.write( (const char *) &num_legs, sizeof( num_legs ) );
402
    file.write( (const char *) &num_teams, sizeof( num_teams ) );
403
    file.write( (const char *) team_class, sizeof( team_class ) );
404
    file.write( (const char *) &num_class, sizeof( num_class ) );
405
    file.write( (const char *) country_name, sizeof( country_name ) );
406
    file.write( (const char *) &num_countries, sizeof( num_countries ) );
407
    file.write( (const char *) addendum, sizeof( addendum ) );
408
    file.write( (const char *) datafilename, sizeof( datafilename ) );
409
    file.write( (const char *) nonequestrian_class_abr, sizeof( nonequestrian_class_abr ) );
410
    file.write( (const char *) &equestrian_leg, sizeof( equestrian_leg ) );
411
    file.write( (const char *) &lines_per_page, sizeof( lines_per_page ) );
412
    file.write( (const char *) &perf_skip, sizeof( perf_skip ) );
413
    file.write( (const char *) &class_winners, sizeof( class_winners ) );
414
    file.write( (const char *) &hall_fame, sizeof( hall_fame ) );
415
    file.write( (const char *) &num_fame, sizeof( num_fame ) );
176 - 416
 
417
    file.close();
418
    return ( TRUE );
419
}
178 - 420
 
421
/*========================================================================
422
 *
423
 *  Qsort callback: Sort by team
424
 *
425
 *  Purpose:
426
 *      Function used by the team definition sort operation
427
 *      It will compare two entries of the team def structure and return an
428
 *      integer for gt eq lt conditions.
429
 *      Note : If the start is 0 the team entry does exist and is placed at the
430
 *      end of the sorted list.
431
 *
432
 *  Parameters:
433
 *      a           comparision entry
434
 *      b           comparision entry
435
 *
436
 *  Returns:
437
 *      gt, eq, lt as required
438
 *
439
 *========================================================================*/
440
 
441
int f_comp_int( const void *aa, const void *bb )
442
{
443
    const ty_t_def *a = (ty_t_def *)aa;
444
    const ty_t_def *b = (ty_t_def *)bb;
445
 
446
    if( a->start == 0 )
447
        return ( 1 );
448
    else if( b->start == 0 )
449
        return ( -1 );
450
    else
451
        return ( a->start - b->start );
452
}
453
 
454
/*========================================================================
455
 *
456
 *  Compact a string
457
 *
458
 *  Purpose:
459
 *      This function is called remove leading and trailing spaces from
460
 *      a string. Treats other non-printing characters as leading
461
 *      spaces. This solves a problem when importing data from a
462
 *      Microsoft CSV file with empty fields.
463
 *
464
 *  Parameters:
465
 *      str     Address of the string to compact
466
 *
467
 *  Returns:
468
 *      Nothing
469
 *
470
 *========================================================================*/
471
 
472
void compact( char *str )
473
{
474
    char       *ptr;
475
 
476
    ptr = str;
477
    while( *str && ( isspace( *str ) || !isprint( *str ) ) )
478
        str++;
479
    strcpy( ptr, str );
480
}
481
 
482
/*========================================================================
483
 *
484
 *  Validate a team number
485
 *
486
 *  Purpose:
487
 *      This function is called to validate a team number
488
 *
489
 *  Parameters:
490
 *      x       Number to validate
491
 *
492
 *  Returns:
493
 *      TRUE    : Valid
494
 *      FALSE   : Not valid
495
 *
496
 *========================================================================*/
497
 
498
bool valid_field( int x )
499
{
500
    int         i;
501
 
502
    for( i = 0; i < config.num_teams; i++ )
503
    {
504
        if( x <= config.t_def[i].end && x >= config.t_def[i].start )
505
            return ( TRUE );
506
        if( x < config.t_def[i].start )
507
            break;                               /* Because the list is sorted */
508
    }
509
    return ( FALSE );
510
}
511
 
512
/*========================================================================
513
 *
514
 *  Get a class descriptor from existing text
515
 *
516
 *  Purpose:
517
 *      This function is called to Get a class descriptor
518
 *
519
 *  Parameters:
520
 *      text    - User text to examine
521
 *      config  - configuration dtaa to use
522
 *
523
 *  Returns:
524
 *      An integer which is the index into the  config.team_class array
525
 *      The integer is in the range 1 .. num_class
526
 *      A value fo zero indicates the text was not found.
527
 *
528
 *========================================================================*/
529
 
180 - 530
int QmConfig::lookup_class( const char *text )
178 - 531
{
532
    int         i;
533
 
180 - 534
//    if( config_ptr == NULL )
535
//        config_ptr = &config;
178 - 536
 
537
    /*
538
     * Attempt to locate the entered class in the list of defined classes
539
     */
540
 
180 - 541
    for( i = 0; i < num_class; i++ )
178 - 542
    {
180 - 543
        if( toupper(text[0]) == toupper(team_class[i].abr[0]) &&
544
            toupper(text[1]) == toupper(team_class[i].abr[1]) )
178 - 545
            return ( ++i );
546
    }
547
    return ( 0 );
548
}
181 - 549
 
550
#ifdef DISPLAY_STRUCTURES
551
/*============================================================================
552
**
553
**  Display structure information
554
**
555
**  Purpose:    Display internal structure information
556
**
557
**  Parameters: Nothing
558
**
559
**  Returns:    Nothing directly
560
**
561
**===========================================================================*/
562
 
563
/*
564
**  esize - A macro to return the size of a structure element
565
**  element - print element information
566
*/
567
#define esize( st, el) ( sizeof(((st *)0)->el))
568
#define element( st, el) \
212 - 569
    printf( "Offset of %-15s :%4d, Size:%d", #el, offsetof( st, el), esize(st, el) );
213 - 570
#define element2( st, el) \
571
    printf( "Size of %-15s :%4d", #el, esize(st, el) );
181 - 572
 
573
void display_structures(void)
574
{
212 - 575
    printf( "Structure: leg_type" );
181 - 576
    element( leg_type, start    );
577
    element( leg_type, end      );
578
    element( leg_type, elapsed  );
579
    element( leg_type, l_place  );
580
    element( leg_type, le_place );
581
    element( leg_type, lc_place );
582
    element( leg_type, lec_place);
583
    element( leg_type, manual   );
212 - 584
    printf( "Sizeof %-18s :%4d", "leg_type", sizeof(leg_type) );
181 - 585
 
586
 
212 - 587
    printf( "" );
588
    printf( "Structure: team_type" );
181 - 589
    element( team_type, numb   );
590
    element( team_type, name   );
591
    element( team_type, leg    );
592
    element( team_type, members);
212 - 593
    element( team_type, teamclass  );
181 - 594
    element( team_type, country);
595
    element( team_type, flags  );
212 - 596
    printf( "Sizeof %-18s :%4d", "team_type", sizeof(team_type) );
181 - 597
 
213 - 598
#if 1
212 - 599
    printf( "" );
600
    printf( "Structure: MARA_CFG" );
213 - 601
    element2( QmConfig, event_name      );
602
    element2( QmConfig, leg_name        );
603
    element2( QmConfig, t_def           );
604
    element2( QmConfig, num_legs        );
605
    element2( QmConfig, num_teams       );
606
    element2( QmConfig, max_team        );
607
    element2( QmConfig, min_team        );
608
    element2( QmConfig, team_class      );
609
    element2( QmConfig, num_class       );
610
    element2( QmConfig, country_name    );
611
    element2( QmConfig, num_countries   );
612
    element2( QmConfig, addendum        );
613
    element2( QmConfig, datafilename    );
614
    printf( "Sizeof %-18s :%4d", "QmConfig", sizeof(QmConfig) );
212 - 615
#endif
181 - 616
}
617
#endif