Subversion Repositories svn1

Rev

Rev 172 | Rev 175 | 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
MARA_CFG    config;
QString     fileName;

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

QmConfig::QmConfig(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
    configFile.setFileName(fileName);
    if ( ! configFile.open(QIODevice::ReadOnly) )
    {
        MainWindow::showMessage("Cannot open config File");
        return (false );
    }

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

    if ( result )
    {
        /*
         **  Post read calculations and fixups
         */
        if( config.datafilename[0] )
        {
            strcpy( datfile, config.datafilename );
            strcat( datfile, ".dat" );
        }
        config.nonequestrian_class = lookup_class( config.nonequestrian_class_abr, &config );
    }
    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( void )
{
    int         len;                            /* Length of data read */
    int         fsize;                          /* Length of desired data */

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

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

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

    /*
     * Number of legs
     */

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

    /*
     * Number of team splits
     */

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

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

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

    /*
     * Country list
     */

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

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

    /*
     * Addendum file
     */

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

    /*
     * Name of the data file
     */

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

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

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

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

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

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

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

qDebug( "Reading: Hall of Fame Numbers" );
    fsize = sizeof( config.hall_fame );
    len = configFile.read( (char *)&config.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 config.addendum file name
     **     Data file name
     */

    file.write( (const char *) config.event_name, sizeof( config.event_name ) );
    file.write( (const char *) config.leg_name, sizeof( config.leg_name ) );
    file.write( (const char *) config.t_def, sizeof( config.t_def ) );
    file.write( (const char *) &config.num_legs, sizeof( config.num_legs ) );
    file.write( (const char *) &config.num_teams, sizeof( config.num_teams ) );
    file.write( (const char *) config.team_class, sizeof( config.team_class ) );
    file.write( (const char *) &config.num_class, sizeof( config.num_class ) );
    file.write( (const char *) config.country_name, sizeof( config.country_name ) );
    file.write( (const char *) &config.num_countries, sizeof( config.num_countries ) );
    file.write( (const char *) config.addendum, sizeof( config.addendum ) );
    file.write( (const char *) config.datafilename, sizeof( config.datafilename ) );
    file.write( (const char *) config.nonequestrian_class_abr, sizeof( config.nonequestrian_class_abr ) );
    file.write( (const char *) &config.equestrian_leg, sizeof( config.equestrian_leg ) );
    file.write( (const char *) &config.lines_per_page, sizeof( config.lines_per_page ) );
    file.write( (const char *) &config.perf_skip, sizeof( config.perf_skip ) );
    file.write( (const char *) &config.class_winners, sizeof( config.class_winners ) );
    file.write( (const char *) &config.hall_fame, sizeof( config.hall_fame ) );
    file.write( (const char *) &config.num_fame, sizeof( config.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 lookup_class( const char *text, MARA_CFG * config_ptr )
{
    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 < config_ptr->num_class; i++ )
    {
        if( toupper(text[0]) == toupper(config_ptr->team_class[i].abr[0]) &&
            toupper(text[1]) == toupper(config_ptr->team_class[i].abr[1]) )
            return ( ++i );
    }
    return ( 0 );
}