Rev 327 | 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>#include <QCoreApplication>#include <QSettings>//#define DISPLAY_STRUCTURES// Global DataQmConfig config;// Application Config// Only use this to store user setting// Thinks like :// Last path for loaded file// Last entered uploaded leg// Swim Start: Leg Set up Delta and baseQSettings *appSettings = NULL;/*** Local definitions*/char datfile[20]; /* Name of the data file */char filebase[20]; /* Event file name base */char filepath[300];/*----------------------------------------------------------------------------** FUNCTION : QmConfig**** DESCRIPTION : Constructor****** INPUTS :**----------------------------------------------------------------------------*/QmConfig::QmConfig(void){/*** Init appSettings - once !*///qDebug("Create a QmConfig");if (!appSettings){appSettings = new QSettings(getAddendemFile("mara.ini", true), QSettings::IniFormat);}}/*----------------------------------------------------------------------------** FUNCTION : ~QmConfig**** DESCRIPTION : Destructor****----------------------------------------------------------------------------*/QmConfig::~QmConfig(){/*** This will force the items to be flushed*/if (appSettings){delete(appSettings);appSettings = NULL;}}void QmConfig::load(const QString &cnfFile){#ifdef DISPLAY_STRUCTURESdisplay_structures();#endiffileName = 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 exitif (fileName.isEmpty()){qDebug("No Config file selected");exit(1);}//// Setup file 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 fileQFile 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 );class_ne_winners_by_class = false;for( int i = 0; i < MAX_CLASS; i++ ){if(class_ne_winners[i]){class_ne_winners_by_class = true;break;}}}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( num_fame );len = configFile.read( (char *)&num_fame, fsize );if( len != fsize )return ( configFile.atEnd() );//qDebug( "Reading: NE Winners Info" );fsize = sizeof( class_ne_winners );len = configFile.read( (char *)&class_ne_winners, fsize );if( len != fsize )return ( configFile.atEnd() );//qDebug( "Reading: Web Import Url" );fsize = sizeof( webUrl );len = configFile.read( (char *)&webUrl, fsize );if( len != fsize )return ( configFile.atEnd() );return ( TRUE );}/*----------------------------------------------------------------------------** FUNCTION : getAddendemFile**** DESCRIPTION : Returns the full path the the addemdum file** The function will look for the file in a number of** locations****** INPUTS : name - Name of the addenum file** create - True. Allow file to be created**** RETURNS : NULL - No addendum name, or file not found** If create' is true then the preferred** location will be returned.**----------------------------------------------------------------------------*/const QString QmConfig::getAddendemFile(const QString &name, bool create ){if (name.isEmpty())return NULL;QFile file;QString addendumFileName;addendumFileName = filepath;addendumFileName.append(name);QString addendumFileNamePreferred(addendumFileName);file.setFileName(addendumFileName);//qDebug("Try:%s", qPrintable(addendumFileName));if ( !file.exists()){addendumFileName = QCoreApplication::applicationDirPath ();addendumFileName.append("/");addendumFileName.append(name);file.setFileName(addendumFileName);//qDebug("Try:%s", qPrintable(addendumFileName));if ( !file.exists()){addendumFileName = QDir::currentPath ();addendumFileName.append("/");addendumFileName.append(name);file.setFileName(addendumFileName);//qDebug("Try:%s", qPrintable(addendumFileName));if ( !file.exists()){//qDebug("Addeddum File not found");if (create){addendumFileName = addendumFileNamePreferred;}else{return NULL;}}}}return addendumFileName;}/*========================================================================** 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 write 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.write( (const char *) &class_ne_winners, sizeof( class_ne_winners ) );file.write( (const char *) &webUrl, sizeof( webUrl ) );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 );elsereturn ( 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", #el, offsetof( st, el), esize(st, el) );#define element2( st, el) \printf( "Size of %-15s :%4d", #el, esize(st, el) );void display_structures(void){printf( "Structure: leg_type" );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", "leg_type", sizeof(leg_type) );printf( "" );printf( "Structure: team_type" );element( team_type, numb );element( team_type, name );element( team_type, leg );element( team_type, members);element( team_type, teamclass );element( team_type, country);element( team_type, flags );printf( "Sizeof %-18s :%4d", "team_type", sizeof(team_type) );#if 1printf( "" );printf( "Structure: MARA_CFG" );element2( QmConfig, event_name );element2( QmConfig, leg_name );element2( QmConfig, t_def );element2( QmConfig, num_legs );element2( QmConfig, num_teams );element2( QmConfig, max_team );element2( QmConfig, min_team );element2( QmConfig, team_class );element2( QmConfig, num_class );element2( QmConfig, country_name );element2( QmConfig, num_countries );element2( QmConfig, addendum );element2( QmConfig, datafilename );printf( "Sizeof %-18s :%4d", "QmConfig", sizeof(QmConfig) );#endif}#endif