Subversion Repositories svn1-original

Rev

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