예제 #1
0
// Determine the format that will be used when interpreting a value to write,
// or when presenting a value for which default formatting has been requested.
void QEStringFormatting::determineDbFormat( const QVariant &value )
{
    // Assume default formatting, and only a single value
    dbFormat = FORMAT_DEFAULT;
    dbFormatArray = false;

    // Get the value type
    QVariant::Type t = value.type();

    // If the value is a list, get the type of the first element in the list
    if( t == QVariant::List )
    {
        // Note that whatever the format, we have an array of them
        dbFormatArray = true;

        // Get the list
        const QVariantList valueArray = value.toList();

        // If the list has anything in it, get the type of the first
        if( valueArray.count() )
        {
            t = valueArray[0].type();
        }
        else
        {
            formatFailure( QString( "Bug in QEStringFormatting::determineDefaultFormatting(). Empty array" ) );
            return;
        }
    }

    // Determine the formatting type from the variant type
    switch( t )
    {
        case QVariant::Double:
            dbFormat = FORMAT_FLOATING;
            break;

        case QVariant::LongLong:
        case QVariant::Int:
            dbFormat = FORMAT_INTEGER;
            break;

        case QVariant::ULongLong:
        case QVariant::UInt:
            dbFormat = FORMAT_UNSIGNEDINTEGER;
            break;

        case QVariant::String:
            dbFormat = FORMAT_STRING;
            break;

        default:
            formatFailure( QString( "Bug in QEStringFormatting::determineDbFormatting(). The QVariant type was not expected" ) );
            break;
        }
}
예제 #2
0
/*!
    Generate an integer given a value, using formatting defined within this class.
*/
long QCaIntegerFormatting::formatInteger( const QVariant &value ) {
    // Determine the format from the variant type.
    // Only the types used to store ca data are used. any other type is considered a failure.
    switch( value.type() ) {
        case QVariant::Double :
        {
            return formatFromFloating( value );
        }
        case QVariant::LongLong :
        {
            return value.toLongLong(); // No conversion requried. Stored in variant as required type
        }
        case QVariant::ULongLong :
        {
            return formatFromUnsignedInteger( value );
        }
        case QVariant::String :
        {
            return formatFromString( value );
        }
        default :
        {
            return formatFailure( QString( "Bug in QCaIntegerFormatting::formatInteger(). The QVariant type was not expected" ) );
        }
    }
}
예제 #3
0
/*
    Format a variant value as an integer representation of a string.
    This method was written to convert a QVariant of type String, but should cope with a variant of any type.
    Convert the variant value to an unsigned long. It may or may not be a ulonglong type variant. If it is - good,
    there will be no conversion problems.
*/
long QEIntegerFormatting::formatFromString( const QVariant &value ) {
    // Extract the value as a long using whatever conversion the QVariant uses.
    // If that fails, try extracting the value as a double using whatever conversion the QVariant uses, then cast it as a long.
    //
    // Note, this will not pick up if the QVariant type is not one of the types used to represent CA data.
    // This is OK as it is not absolutely nessesary to do this sort of check at this point. Also the code is more robust as it will
    // work if the range of QVariant types used expands.
    // Note, this does not give us the freedom to specify what conversions should fail or succeed. For example, does QVariant::toLongLong()
    // work if the value it holds is the string 1.0001 and should it?
    // If QVariant::toLongLong() does not do exactly what is required, a switch statement for each of the types used to hold CA data
    // will need to be added and the conversions done  manually or using QVariant::toLongLong() as required.
    bool convertOk;
    long lValue = value.toLongLong( &convertOk );

    if( convertOk )
        return lValue;

    double dValue = value.toDouble( &convertOk );
    if( convertOk )
    {
        lValue = (long)dValue;
        return lValue;
    }

    return formatFailure( QString( "Warning from QEIntegerFormatting::formatFromString(). A variant could not be converted to a string." ) );

}
예제 #4
0
/*
    Format a variant value as a string representation of an unsigned integer.
    This method was written to convert a QVariant of type ULongLong, but should cope with a variant of any type.
    First convert the variant value to an unsigned long. It may or may not be a ulonglong type variant. If it is - good,
    there will be no conversion problems.
    Then format it as a string using the formatting information stored in this class.
*/
void QEStringFormatting::formatFromUnsignedInteger( const QVariant &value ) {
    // Extract the value as an unsigned long using whatever conversion the QVariant uses.
    //
    // Note, this will not pick up if the QVariant type is not one of the types used to represent CA data.
    // This is OK as it is not absolutely nessesary to do this sort of check at this point. Also the code is more robust as it will
    // work if the range of QVariant types used expands.
    // Note, this does not give us the freedom to specify what conversions should fail or succeed. For example, does QVariant::toULongLong()
    // work if the value it holds is the string 1.000 and should it?
    // If QVariant::toULongLong() does not do exactly what is required, a switch statement for each of the types used to hold CA data
    // will need to be added and the conversions done  manually or using QVariant::toULongLong() as required.



    // Use QString conversions is variant is a string.
    // (QVariant toLongLong can't convert strings like "2.000"!)
    bool convertOk;
    unsigned long ulValue;
    if( value.type() == QVariant::String )
    {
        QString str = value.toString();
        double dd = str.toDouble( &convertOk );
        ulValue = dd;
    }

    // Use QVariant conversions otherwise
    else
    {
        ulValue = value.toULongLong( &convertOk );
    }

    if( !convertOk )
    {
        formatFailure( QString( "Warning from QEStringFormatting::formatFromUnsignedInteger(). A variant could not be converted to an unsigned long." ) );
        return;
    }

    // Generate the text
    stream << ulValue;

    // Add sperators if needs be
    outStr = insertSeparators( outStr );
}
예제 #5
0
/*
    Format a variant value as a string representation of a floating point
    number.
    First convert the variant value to a double. It may or may not be a
    floating point type variant. If it is - good,
    there will be no conversion problems.
    Then format it as a string using the formatting information stored in this
    class.
*/
void QEStringFormatting::formatFromFloating( const QVariant &value ) {
    // Extract the value as a double using whatever conversion the QVariant uses.
    //
    // Note, this will not pick up if the QVariant type is not one of the types used to represent CA data.
    // This is OK as it is not absolutely nessesary to do this sort of check at this point. Also the code is more robust as it will
    // work if the range of QVariant types used expands.
    // Note, this does not give us the freedom to specify what conversions should fail or succeed. For example, does QVariant::toDouble()
    // work if the value it holds is the string 1.234 10^6, or does it work for both - 1.234 and -1.234, and should it?
    // If QVariant::toDouble() does not do exactly what is required, a switch statement for each of the types used to hold CA data
    // will need to be added and the conversions done  manually or using QVariant::toDouble() as required.
    bool convertOk;
    double dValue = value.toDouble( &convertOk );

    if( !convertOk ) {
        formatFailure( QString( "Warning from QEStringFormatting::formatFromFloating(). A variant could not be converted to a long." ) );
        return;
    }

    // NOTE: Smart notation (NOTATION_AUTOMATIC) does not honor real number precision.
    // So select FixedNotation or ScientificNotation as appropriate.
    //
    QTextStream::RealNumberNotation rnn = stream.realNumberNotation();
    if( rnn == QTextStream::SmartNotation ){
       int prec;
       double low_fixed_limit;
       double high_fixed_limit;
       double absDbValue;

       // Extact precision being used.
       prec = stream.realNumberPrecision ();
       prec = LIMIT( prec, 0, 15 );

       // Example, if prec = 3, when low limit is 0.01
       low_fixed_limit = EXP10( 1 - prec );

       high_fixed_limit = 1.0E+05;

       // Work with absoloute value
       absDbValue = ABS( dValue );

       if( absDbValue == 0.0 || ( absDbValue >= low_fixed_limit && absDbValue < high_fixed_limit )){
          stream.setRealNumberNotation( QTextStream::FixedNotation );
       } else {
          stream.setRealNumberNotation( QTextStream::ScientificNotation );
       }
    }

    // Generate the text
    stream << dValue;

    stream.setRealNumberNotation( rnn );  // reset

    // Remove leading zero if required
    if( !leadingZero ) {
        if( outStr.left(2) == "0." )
            outStr = outStr.right( outStr.length()-1);
    }

    // Remove trailing zeros if required, but don't leave a naked decimal point, i.e. 4.0000 becomes 4.0 (as opposed to 4.)
    // Also need to be careful to ensure 1.23000e+100 becomes 1.23e+100 (as opposed to 1.23000e+1)
    if( !trailingZeros ) {
        int dp = outStr.indexOf( ".", 0 );
        if( dp >= 0 ){
            int ep = outStr.indexOf( "e", dp );           // find exponent if it exists
            if( ep < 0 ) ep = outStr.indexOf( "E", dp );  // allow for either case
            if( ep < 0 ) ep = outStr.length ();           // otherwise start at end of string
            int sp = ep;
            while( ( sp > dp + 2 ) && ( outStr[sp - 1] == '0' ) ){
                sp--;
            }
            if( sp < ep ){
               outStr.replace( sp, ep - sp, "" );
            }
        }
    }

    // Add sperators if needs be
    outStr = insertSeparators( outStr );
}
예제 #6
0
/*
    Generate a string given an element value, using formatting defined within this class.
*/
QString QEStringFormatting::formatElementString( const QVariant& value ) {
    // Examine the value and note the matching format
    determineDbFormat( value );

    // Initialise
    bool errorMessage = false;      // Set if an error message is the result
    outStr.clear();

    // Set the precision
    if( useDbPrecision )
        stream.setRealNumberPrecision( dbPrecision );
    else
        stream.setRealNumberPrecision( precision );

    // Format the value as requested
    switch( format )
    {
        // Determine the format from the variant type.
        // Only the types used to store ca data are used. any other type is
        // considered a failure.
        case FORMAT_DEFAULT :
        {
            bool haveEnumeratedString = false;  // Successfully converted the value to an enumerated string
            // If a list of enumerated strings is available, attempt to get an enumerated string
            if( dbEnumerations.size() )
            {
                // Ensure the input value can be used as an index into the list of enumerated strings
                bool convertOk;
                long lValue = value.toLongLong( &convertOk );
                if( convertOk && lValue >= 0 )
                {
                    // Get the appropriate enumerated string
                    if( lValue < dbEnumerations.size() )
                    {
                        outStr = dbEnumerations[lValue];
                        haveEnumeratedString = true;
                    }
                    // NOTE: STAT field hard-coded values now set up in QCaObject.cpp - extra values appended to dbEnumerations.
                }
            }

            // If no list of enumerated strings was available, or a string could not be selected,
            // convert the value based on it's type.
            if( !haveEnumeratedString )
            {
                switch( dbFormat )
                {
                case FORMAT_FLOATING:
                    formatFromFloating( value );
                    break;

                case FORMAT_INTEGER:
                    formatFromInteger( value );
                    break;

                case FORMAT_UNSIGNEDINTEGER:
                    formatFromUnsignedInteger( value );
                    break;

                case FORMAT_STRING:
                    formatFromString( value );
                    break;

                default:
                    formatFailure( QString( "Bug in QEStringFormatting::formatString(). The QVariant type was not expected" ) );
                    errorMessage = true;
                    break;
                }
            }
            break;
        }

        // Format as requested, ignoring the database type
        case FORMAT_FLOATING:
            formatFromFloating( value );
            break;

         case FORMAT_INTEGER:
            formatFromInteger( value );
            break;

        case FORMAT_UNSIGNEDINTEGER:
            formatFromUnsignedInteger( value );
            break;

        case FORMAT_LOCAL_ENUMERATE:
            formatFromEnumeration( value );
            break;

        case FORMAT_TIME:
            formatFromTime( value );
            break;

        case FORMAT_STRING:
            formatFromString( value );
            break;

        // Don't know how to format.
        // This is a code error. All cases in QEStringFormatting::formats should be catered for
        default:
            formatFailure( QString( "Bug in QEStringFormatting::format(). The format type was not expected" ) );
            errorMessage = true;
            break;
    }

    return outStr;
}