Subversion Repositories svn1

Rev

Rev 176 | Rev 199 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "qmconfig.h"
#include "mainwindow.h"
#include <QFileDialog>
#include <QObject>
#include <QMessageBox>
#include <QFileInfo>
#include <QFile>

// Global Data
QmConfig    config;


/*
**  Local definitions
*/
char        datfile[20];                         /* Name of the data file */
char        filebase[20];                        /* Event file name base */
char        filepath[100];

void QmConfig::load(const QString &cnfFile)
{
    fileName = cnfFile;
    if ( !fileName.endsWith(".cnf",Qt::CaseInsensitive))
    {
        fileName.append(".cnf");
    }
    if (cnfFile.isEmpty())
    {
        fileName = QFileDialog::getOpenFileName(0, "Select Config File",
                                                         filepath,
                                                         "Data (*.cnf);;All (*.*)",
                                                         0,
                                                         0
                                                         );
    }

    //  No file selected
    //  Just exit
    if (fileName.isEmpty())
    {
        qDebug("No Config file selected");
        exit(1);
    }

    //
    //  Setup ffile names
    //
    QFileInfo info (fileName);
    strncpy(filebase, qPrintable(info.baseName()), 8);
    strcpy( datfile, filebase );
    strcat( datfile, ".dat" );

    strncpy(filepath, qPrintable(info.absolutePath()), sizeof(filepath)-3);
    strcat(filepath, "/");
    qDebug("FilePath:%s", filepath );

    if ( !open_read_config() )
    {
        if (QMessageBox::Cancel == QMessageBox::question ( 0,
                                                       "Config Load Error",
                                                       "Cannot load or read configuration file.\n"
                                                       "If you continue a new configuration will be created\n"
                                                       "If you cancel then the application will terminate.",
                                                       QMessageBox::Ok | QMessageBox::Cancel
                                                       ) )
        {
            qDebug("Cancel to bad config");
            exit(2);
        }
    }
}


bool QmConfig::open_read_config( void )
{
    bool result;
    // Open the file
    QFile configFile;
    configFile.setFileName(fileName);
    if ( ! configFile.open(QIODevice::ReadOnly) )
    {
        MainWindow::showMessage("Cannot open config File");
        return (false );
    }

    result = read_config(configFile);
    configFile.close();

    if ( result )
    {
        /*
         **  Post read calculations and fixups
         */
        if( datafilename[0] )
        {
            strcpy( datfile, datafilename );
            strcat( datfile, ".dat" );
        }
        nonequestrian_class = lookup_class( nonequestrian_class_abr );
    }
    return result;
}

/*========================================================================
 *
 *  Read in the configuration file
 *
 *  Purpose:
 *      This function is called to read in the configuration file
 *      NOTE: Must be maintained with the Writer function
 *
 *  Parameters:
 *      fcon        File number of the config file
 *
 *  Returns:
 *      FALSE if an error is encountered
 *
 *========================================================================*/

bool QmConfig::read_config( QFile &configFile  )
{
    int         len;                            /* Length of data read */
    int         fsize;                          /* Length of desired data */

    /*
     * Event name
     */
qDebug( "Reading: Event Name" );
    fsize = sizeof( event_name );
    len = configFile.read( event_name, fsize );
    if( len != fsize )
        return ( FALSE );

    /*
     * Leg names
     */
qDebug( "Reading: Leg Names" );
    fsize = sizeof( leg_name );
    len = configFile.read( (char *)leg_name, fsize );
    if( len != fsize )
        return ( FALSE );

    /*
     * Team definitions
     */
qDebug( "Reading: Team Defs" );
    fsize = sizeof( t_def  );
    len = configFile.read( (char *)t_def, fsize );
    if( len != fsize )
        return ( FALSE );

    /*
     * Number of legs
     */

qDebug( "Reading: Leg Nums" );
    fsize = sizeof( num_legs  );
    len = configFile.read( (char *)&num_legs, fsize );
    if( len != fsize)
        return ( FALSE );

    /*
     * Number of team splits
     */

qDebug( "Reading: Team Splits" );
    fsize = sizeof( num_teams  );
    len = configFile.read( (char *)&num_teams, fsize );
    if( len != fsize )
        return ( FALSE );

    min_team = t_def[0].start;
    max_team = t_def[num_teams - 1].end;

    /*
     * Class information
     */
qDebug( "Reading: Class Data" );
    fsize = sizeof( team_class  );
    len = configFile.read( (char *)team_class, fsize );
    if( len != fsize )
        return ( FALSE );
    fsize = sizeof( num_class  );
    len = configFile.read( (char *)&num_class, fsize);
    if( len != fsize )
        return ( FALSE );

    /*
     * Country list
     */

qDebug( "Reading: Country Data, Name" );
    fsize = sizeof( country_name  );
    len = configFile.read( (char *)country_name, fsize );
    if( len != fsize )
        return ( FALSE );

qDebug( "Reading: Country Data, Number" );
    fsize = sizeof( num_countries  );
    len = configFile.read( (char *)&num_countries, fsize );
    if( len != fsize )
        return ( FALSE );

    /*
     * Addendum file
     */

qDebug( "Reading: Addendum File" );
    fsize = sizeof( addendum );
    len = configFile.read( addendum, fsize );
    if( len != fsize )
        return ( configFile.atEnd() );

    /*
     * Name of the data file
     */

qDebug( "Reading: Name of data file" );
    fsize = sizeof( datafilename );
    len = configFile.read( datafilename, fsize );
    if( len != fsize )
        return ( configFile.atEnd() );

    /*
     **  Non-equestrian configuration information
     */
qDebug( "Reading: NonEquest" );
    fsize = sizeof( nonequestrian_class_abr );
    len = configFile.read( nonequestrian_class_abr, fsize );
    if( len != fsize )
        return ( configFile.atEnd() );

qDebug( "Reading: NonEquest-2" );
    fsize = sizeof( equestrian_leg );
    len = configFile.read( (char *)&equestrian_leg, fsize );
    if( len != fsize )
        return ( FALSE );

    /*
    **  .txt file output control. Lines per page and perf-skipping
    */
qDebug( "Reading: Output Control" );
    fsize = sizeof( lines_per_page );
    len = configFile.read( (char *)&lines_per_page, fsize );
    if( len != fsize )
        return ( configFile.atEnd() );

qDebug( "Reading: Output Control-2" );
    fsize = sizeof( perf_skip );
    len = configFile.read( (char *)&perf_skip, fsize );
    if( len != fsize )
        return ( FALSE );

qDebug( "Reading: Winners Info" );
    fsize = sizeof( class_winners );
    len = configFile.read( (char *)&class_winners, fsize );
    if( len != fsize )
        return ( FALSE );

qDebug( "Reading: Hall of Fame Info" );
    fsize = sizeof( hall_fame );
    len = configFile.read( (char *)&hall_fame, fsize );
    if( len != fsize )
        return ( FALSE );

qDebug( "Reading: Hall of Fame Numbers" );
    fsize = sizeof( hall_fame );
    len = configFile.read( (char *)&num_fame, fsize );
    if( len != fsize )
        return ( configFile.atEnd() );


    return ( TRUE );
}


/*========================================================================
 *
 *  Write out the configuration file
 *
 *  Purpose:
 *      This function is called to write the configuration file
 *      NOTE: Must be maintained with the Reader function
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      FALSE   : Error encountered
 *
 *========================================================================*/

bool QmConfig::write_config( void )
{
    if (fileName.isEmpty())
    {
        qDebug("No Config file selected");
        return(false);
    }
    /*
     **  Open as a binary file
     */
    QFile file;
    file.setFileName(fileName);
    if ( ! file.open(QIODevice::WriteOnly | QIODevice::Truncate) )
    {
        qDebug("File error: %s", qPrintable(file.errorString()));
        MainWindow::showMessage("Cannot open config file");
        return (false);
    }

     /*
     **  Write out multiple structures
     **     Event name
     **     Leg names
     **     Team definitions
     **     Number of legs
     **     Number fo team splits
     **     Class information
     **     Number of defined classes
     **     Country list
     **     Number of defined countries
     **     Legend addendum file name
     **     Data file name
     */

    file.write( (const char *) event_name, sizeof( event_name ) );
    file.write( (const char *) leg_name, sizeof( leg_name ) );
    file.write( (const char *) t_def, sizeof( t_def ) );
    file.write( (const char *) &num_legs, sizeof( num_legs ) );
    file.write( (const char *) &num_teams, sizeof( num_teams ) );
    file.write( (const char *) team_class, sizeof( team_class ) );
    file.write( (const char *) &num_class, sizeof( num_class ) );
    file.write( (const char *) country_name, sizeof( country_name ) );
    file.write( (const char *) &num_countries, sizeof( num_countries ) );
    file.write( (const char *) addendum, sizeof( addendum ) );
    file.write( (const char *) datafilename, sizeof( datafilename ) );
    file.write( (const char *) nonequestrian_class_abr, sizeof( nonequestrian_class_abr ) );
    file.write( (const char *) &equestrian_leg, sizeof( equestrian_leg ) );
    file.write( (const char *) &lines_per_page, sizeof( lines_per_page ) );
    file.write( (const char *) &perf_skip, sizeof( perf_skip ) );
    file.write( (const char *) &class_winners, sizeof( class_winners ) );
    file.write( (const char *) &hall_fame, sizeof( hall_fame ) );
    file.write( (const char *) &num_fame, sizeof( num_fame ) );

    file.close();
    return ( TRUE );
}

/*========================================================================
 *
 *  Qsort callback: Sort by team
 *
 *  Purpose:
 *      Function used by the team definition sort operation
 *      It will compare two entries of the team def structure and return an
 *      integer for gt eq lt conditions.
 *      Note : If the start is 0 the team entry does exist and is placed at the
 *      end of the sorted list.
 *
 *  Parameters:
 *      a           comparision entry
 *      b           comparision entry
 *
 *  Returns:
 *      gt, eq, lt as required
 *
 *========================================================================*/

int f_comp_int( const void *aa, const void *bb )
{
    const ty_t_def *a = (ty_t_def *)aa;
    const ty_t_def *b = (ty_t_def *)bb;

    if( a->start == 0 )
        return ( 1 );
    else if( b->start == 0 )
        return ( -1 );
    else
        return ( a->start - b->start );
}

/*========================================================================
 *
 *  Compact a string
 *
 *  Purpose:
 *      This function is called remove leading and trailing spaces from
 *      a string. Treats other non-printing characters as leading
 *      spaces. This solves a problem when importing data from a
 *      Microsoft CSV file with empty fields.
 *
 *  Parameters:
 *      str     Address of the string to compact
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/

void compact( char *str )
{
    char       *ptr;

    ptr = str;
    while( *str && ( isspace( *str ) || !isprint( *str ) ) )
        str++;
    strcpy( ptr, str );
}

/*========================================================================
 *
 *  Validate a team number
 *
 *  Purpose:
 *      This function is called to validate a team number
 *
 *  Parameters:
 *      x       Number to validate
 *
 *  Returns:
 *      TRUE    : Valid
 *      FALSE   : Not valid
 *
 *========================================================================*/

bool valid_field( int x )
{
    int         i;

    for( i = 0; i < config.num_teams; i++ )
    {
        if( x <= config.t_def[i].end && x >= config.t_def[i].start )
            return ( TRUE );
        if( x < config.t_def[i].start )
            break;                               /* Because the list is sorted */
    }
    return ( FALSE );
}

/*========================================================================
 *
 *  Get a class descriptor from existing text
 *
 *  Purpose:
 *      This function is called to Get a class descriptor
 *
 *  Parameters:
 *      text    - User text to examine
 *      config  - configuration dtaa to use
 *
 *  Returns:
 *      An integer which is the index into the  config.team_class array
 *      The integer is in the range 1 .. num_class
 *      A value fo zero indicates the text was not found.
 *
 *========================================================================*/

int QmConfig::lookup_class( const char *text )
{
    int         i;

//    if( config_ptr == NULL )
//        config_ptr = &config;

    /*
     * Attempt to locate the entered class in the list of defined classes
     */

    for( i = 0; i < num_class; i++ )
    {
        if( toupper(text[0]) == toupper(team_class[i].abr[0]) &&
            toupper(text[1]) == toupper(team_class[i].abr[1]) )
            return ( ++i );
    }
    return ( 0 );
}

#ifdef DISPLAY_STRUCTURES
/*============================================================================
**
**  Display structure information
**
**  Purpose:    Display internal structure information
**
**  Parameters: Nothing
**
**  Returns:    Nothing directly
**
**===========================================================================*/

/*
**  esize - A macro to return the size of a structure element
**  element - print element information
*/
#define esize( st, el) ( sizeof(((st *)0)->el))
#define element( st, el) \
    printf( "Offset of %-15s :%4d, Size:%d   \n", #el, offsetof( st, el), esize(st, el) );

void display_structures(void)
{
    printf( "Structure: leg_type\n" );
    element( leg_type, start    );
    element( leg_type, end      );
    element( leg_type, elapsed  );
    element( leg_type, l_place  );
    element( leg_type, le_place );
    element( leg_type, lc_place );
    element( leg_type, lec_place);
    element( leg_type, manual   );
    printf( "Sizeof %-18s :%4d\n", "leg_type", sizeof(leg_type) );


    printf( "\n" );
    printf( "Structure: team_type\n" );
    element( team_type, numb   );
    element( team_type, name   );
    element( team_type, leg    );
    element( team_type, members);
    element( team_type, class  );
    element( team_type, country);
    element( team_type, flags  );
    printf( "Sizeof %-18s :%4d\n", "team_type", sizeof(team_type) );

    printf( "\n" );
    printf( "Structure: MARA_CFG\n" );
    element( MARA_CFG, event_name      );
    element( MARA_CFG, leg_name        );
    element( MARA_CFG, t_def           );
    element( MARA_CFG, num_legs        );
    element( MARA_CFG, num_teams       );
    element( MARA_CFG, max_team        );
    element( MARA_CFG, min_team        );
    element( MARA_CFG, team_class      );
    element( MARA_CFG, num_class       );
    element( MARA_CFG, country_name    );
    element( MARA_CFG, num_countries   );
    element( MARA_CFG, addendum        );
    element( MARA_CFG, datafilename    );
    printf( "Sizeof %-18s :%4d\n", "MARA_CFG", sizeof(MARA_CFG) );
}
#endif