Subversion Repositories svn1-original

Rev

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