[TD] fix unit mismatch bug
- also make global decimal option italic since it only affects new dimensions - also fix a typo in UnitsApi.h
This commit is contained in:
@@ -581,6 +581,32 @@ bool DrawViewDimension::isMultiValueSchema(void) const
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string DrawViewDimension::getBaseLengthUnit(Base::UnitSystem system)
|
||||
{
|
||||
switch (system) {
|
||||
case Base::UnitSystem::SI1:
|
||||
return "mm";
|
||||
case Base::UnitSystem::SI2:
|
||||
return "m";
|
||||
case Base::UnitSystem::Imperial1:
|
||||
return "in";
|
||||
case Base::UnitSystem::ImperialDecimal:
|
||||
return "in";
|
||||
case Base::UnitSystem::Centimeters:
|
||||
return "cm";
|
||||
case Base::UnitSystem::ImperialBuilding:
|
||||
return "ft";
|
||||
case Base::UnitSystem::MmMin:
|
||||
return "mm";
|
||||
case Base::UnitSystem::ImperialCivil:
|
||||
return "ft";
|
||||
case Base::UnitSystem::FemMilliMeterNewton:
|
||||
return "mm";
|
||||
default:
|
||||
return "Unknown schema";
|
||||
}
|
||||
}
|
||||
|
||||
std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int partial)
|
||||
{
|
||||
std::string result;
|
||||
@@ -588,8 +614,8 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
|
||||
QString qUserStringUnits;
|
||||
QString formattedValue;
|
||||
|
||||
bool angularMeasure = false;
|
||||
|
||||
Base::Quantity asQuantity;
|
||||
asQuantity.setValue(value);
|
||||
if ( (Type.isValue("Angle")) ||
|
||||
@@ -600,7 +626,7 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
asQuantity.setUnit(Base::Unit::Length);
|
||||
}
|
||||
|
||||
QString qUserString = asQuantity.getUserString(); // this handles mm to inch/km/parsec etc
|
||||
QString qUserString = asQuantity.getUserString(); // this handles mm to inch/km/parsec etc
|
||||
// and decimal positions but won't give more than
|
||||
// Global_Decimals precision
|
||||
// really should be able to ask units for value
|
||||
@@ -610,6 +636,9 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
//if it is multi-unit schema, don't even try to use Alt Decimals
|
||||
Base::UnitSystem unitSystem = Base::UnitsApi::getSchema();
|
||||
|
||||
// we need to know what length unit is used by the scheme
|
||||
std::string BaseLengthUnit = getBaseLengthUnit(unitSystem);
|
||||
|
||||
//get formatSpec prefix/suffix/specifier
|
||||
QStringList qsl = getPrefixSuffixSpec(qFormatSpec);
|
||||
QString formatPrefix = qsl[0]; //FormatSpec prefix
|
||||
@@ -619,24 +648,14 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
//handle multi value schemes (yd/ft/in, dms, etc)
|
||||
std::string genPrefix = getPrefix(); //general prefix - diameter, radius, etc
|
||||
QString qMultiValueStr;
|
||||
QString qGenPrefix = QString::fromUtf8(genPrefix.data(),genPrefix.size());
|
||||
if ( (unitSystem == Base::UnitSystem::ImperialBuilding) &&
|
||||
!angularMeasure ) {
|
||||
multiValueSchema = true;
|
||||
qMultiValueStr = qUserString;
|
||||
if (!genPrefix.empty()) {
|
||||
//qUserString from Quantity includes units - prefix + R + nnn ft + suffix
|
||||
qMultiValueStr = formatPrefix + qGenPrefix + qUserString + formatSuffix;
|
||||
}
|
||||
formattedValue = qMultiValueStr;
|
||||
} else if ((unitSystem == Base::UnitSystem::ImperialCivil) &&
|
||||
angularMeasure) {
|
||||
QString qGenPrefix = QString::fromUtf8(genPrefix.data(), genPrefix.size());
|
||||
if ((unitSystem == Base::UnitSystem::ImperialCivil) && angularMeasure) {
|
||||
QString dispMinute = QString::fromUtf8("\'");
|
||||
QString dispSecond = QString::fromUtf8("\"");
|
||||
QString schemeMinute = QString::fromUtf8("M");
|
||||
QString schemeSecond = QString::fromUtf8("S");
|
||||
QString displaySub = qUserString.replace(schemeMinute,dispMinute);
|
||||
displaySub = displaySub.replace(schemeSecond,dispSecond);
|
||||
QString displaySub = qUserString.replace(schemeMinute, dispMinute);
|
||||
displaySub = displaySub.replace(schemeSecond, dispSecond);
|
||||
multiValueSchema = true;
|
||||
qMultiValueStr = displaySub;
|
||||
if (!genPrefix.empty()) {
|
||||
@@ -645,85 +664,119 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
}
|
||||
formattedValue = qMultiValueStr;
|
||||
} else {
|
||||
//handle single value schemes
|
||||
if (formatSpecifier.isEmpty()) {
|
||||
Base::Console().Warning("Warning - no numeric format in formatSpec %s - %s\n",
|
||||
qPrintable(qFormatSpec), getNameInDocument());
|
||||
return Base::Tools::toStdString(qFormatSpec);
|
||||
}
|
||||
QRegExp rxUnits(QString::fromUtf8(" \\D*$")); //space + any non digits at end of string
|
||||
QString userVal = qUserString;
|
||||
userVal.remove(rxUnits); //getUserString(defaultDecimals) without units
|
||||
|
||||
QLocale loc;
|
||||
double userValNum = loc.toDouble(userVal);
|
||||
|
||||
// for older TD drawings the formatSpecifier "%g" was used, but the number of decimals was
|
||||
// neverheless limited. To keep old drawings, we limit the number of decimals too
|
||||
// if the TD preferences option to use the global decimal number is set
|
||||
// the formatSpecifier can have a prefix and/or suffix
|
||||
if (useDecimals() && formatSpecifier.contains(QString::fromLatin1("%g"), Qt::CaseInsensitive)) {
|
||||
int globalPrecision = Base::UnitsApi::getDecimals();
|
||||
// change formatSpecifier to e.g. "%.2f"
|
||||
QString newSpecifier = QString::fromStdString("%." + std::to_string(globalPrecision) + "f");
|
||||
formatSpecifier.replace(QString::fromLatin1("%g"), newSpecifier, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
// qUserString is the value + unit with default decimals, so extract the unit
|
||||
// we cannot just use unit.getString() because this would convert '°' to 'deg'
|
||||
QRegExp rxUnits(QString::fromUtf8(" \\D*$")); // space + any non digits at end of string
|
||||
int pos = 0;
|
||||
if ((pos = rxUnits.indexIn(qUserString, 0)) != -1) {
|
||||
qUserStringUnits = rxUnits.cap(0); //entire capture - non numerics at end of qUserString
|
||||
if ((pos = rxUnits.indexIn(qUserString, 0)) != -1) {
|
||||
qUserStringUnits = rxUnits.cap(0); // entire capture - non numerics at end of qUserString
|
||||
}
|
||||
formattedValue = userVal; //sensible default
|
||||
#if QT_VERSION >= 0x050000
|
||||
formattedValue = QString::asprintf(Base::Tools::toStdString(formatSpecifier).c_str(),userValNum);
|
||||
#else
|
||||
|
||||
// we can have 2 possible results:
|
||||
// - the value in the base unit but without displayed unit
|
||||
// - the value + unit (not necessarily the base unit!)
|
||||
// the user can overwrite the decimal settings, so we must in every case use the formatSpecifier
|
||||
// if useDecimals(), then formatSpecifier = global decimals, otherwise it is %.2f
|
||||
QLocale loc;
|
||||
double userVal;
|
||||
bool checkDecimals = true;
|
||||
if (showUnits() || (Type.isValue("Angle")) || (Type.isValue("Angle3Pt"))) {
|
||||
formattedValue = qUserString; // result value + unit (not necessarily base unit!)
|
||||
// remove unit
|
||||
formattedValue.remove(rxUnits);
|
||||
// to number
|
||||
userVal = loc.toDouble(formattedValue);
|
||||
if (userVal >= 1.0)
|
||||
// we can assure we didn't make an error > 10% via getUserString()
|
||||
checkDecimals = false;
|
||||
}
|
||||
if (checkDecimals){
|
||||
// get value in the base unit with default decimals
|
||||
// for the conversion we use the same method as in DlgUnitsCalculator::valueChanged
|
||||
// get the conversion factor for the unit
|
||||
double convertValue = Base::Quantity::parse(QString::fromLatin1("1") + QString::fromStdString(BaseLengthUnit)).getValue();
|
||||
// the result is now just val / convertValue because val is always in the base unit
|
||||
userVal = asQuantity.getValue() / convertValue;
|
||||
}
|
||||
// we reformat the value
|
||||
#if QT_VERSION >= 0x050000
|
||||
formattedValue = QString::asprintf(Base::Tools::toStdString(formatSpecifier).c_str(), userVal);
|
||||
#else
|
||||
QString qs2;
|
||||
formattedValue = qs2.sprintf(Base::Tools::toStdString(formatSpecifier).c_str(),userValNum);
|
||||
#endif
|
||||
|
||||
QString repl = userVal;
|
||||
if (useDecimals()) {
|
||||
if (showUnits() || (Type.isValue("Angle")) ||(Type.isValue("Angle3Pt")) ) {
|
||||
repl = qUserString;
|
||||
} else {
|
||||
repl = userVal;
|
||||
}
|
||||
} else {
|
||||
if (showUnits() || (Type.isValue("Angle")) || (Type.isValue("Angle3Pt"))) {
|
||||
repl = formattedValue + qUserStringUnits;
|
||||
} else {
|
||||
repl = formattedValue;
|
||||
}
|
||||
formattedValue = qs2.sprintf(Base::Tools::toStdString(formatSpecifier).c_str(), userVal);
|
||||
#endif
|
||||
// if abs(1 - userVal / formattedValue) > 0.1 we know that we make an error greater than 10%
|
||||
// then we need more digits
|
||||
if (abs(userVal - formattedValue.toDouble()) > 0.1 * userVal) {
|
||||
int i = 1;
|
||||
do { // increase decimals step by step until error is < 10 %
|
||||
formattedValue = QLocale().toString(userVal, 'f', i);
|
||||
++i;
|
||||
} while (abs(userVal - loc.toDouble(formattedValue)) > 0.1 * userVal);
|
||||
// We purposely don't reset the formatSpecifier.
|
||||
// Why "%.1f" is overwritten for a value of e.g. "0.001" is obvious,
|
||||
// moreover such cases only occurs when
|
||||
// changing unit schemes on existing drawings. Moreover a typical case is that
|
||||
// you accidentally used e.g. a building scheme, see your mistake and go back
|
||||
// then you would end up with e.g. "%.5f" and must manually correct this.
|
||||
}
|
||||
|
||||
qFormatSpec.replace(formatSpecifier,repl);
|
||||
//this next bit is so inelegant!!!
|
||||
// replace decimal sign if necessary
|
||||
QChar dp = QChar::fromLatin1('.');
|
||||
if (loc.decimalPoint() != dp) {
|
||||
qFormatSpec.replace(dp,loc.decimalPoint());
|
||||
formattedValue.replace(dp,loc.decimalPoint());
|
||||
}
|
||||
//Remove space between dimension and degree sign
|
||||
if ((Type.isValue("Angle")) || (Type.isValue("Angle3Pt"))) {
|
||||
QRegExp space(QString::fromUtf8("\\s"));
|
||||
qFormatSpec.remove(space);
|
||||
formattedValue.replace(dp, loc.decimalPoint());
|
||||
}
|
||||
}
|
||||
//formattedValue - formatted numeric value
|
||||
//qUserStringUnits - unit abbrev
|
||||
//qFormatSpec - prefix + formattedValue w/units + suffix
|
||||
|
||||
//partial = 0 --> prefix + formattedValue w/units +suffix
|
||||
// prefix 4' 11" suffix
|
||||
result = qFormatSpec.toUtf8().constData();
|
||||
if ((unitSystem == Base::UnitSystem::ImperialBuilding) &&
|
||||
!angularMeasure) {
|
||||
multiValueSchema = true;
|
||||
qMultiValueStr = formattedValue;
|
||||
if (!genPrefix.empty()) {
|
||||
//qUserString from Quantity includes units - prefix + R + nnn ft + suffix
|
||||
qMultiValueStr = formatPrefix + qGenPrefix + qUserString + formatSuffix;
|
||||
}
|
||||
|
||||
std::string ssPrefix = Base::Tools::toStdString(formatPrefix);
|
||||
std::string ssSuffix = Base::Tools::toStdString(formatSuffix);
|
||||
std::string ssUnits = Base::Tools::toStdString(qUserStringUnits);
|
||||
if (multiValueSchema) {
|
||||
result = ssPrefix +
|
||||
Base::Tools::toStdString(qMultiValueStr) +
|
||||
ssSuffix +
|
||||
ssUnits;
|
||||
formattedValue = qMultiValueStr;
|
||||
}
|
||||
|
||||
if (partial == 1) { //prefix number suffix
|
||||
result = ssPrefix +
|
||||
Base::Tools::toStdString(formattedValue) +
|
||||
ssSuffix;
|
||||
} else if (partial == 2) { //just the unit
|
||||
result = formattedValue.toStdString();
|
||||
|
||||
if (partial == 0) { // then also multiValueSchema is true
|
||||
result = Base::Tools::toStdString(formatPrefix) +
|
||||
Base::Tools::toStdString(qMultiValueStr) +
|
||||
Base::Tools::toStdString(formatSuffix) +
|
||||
Base::Tools::toStdString(qUserStringUnits);
|
||||
}
|
||||
else if (partial == 1) { // prefix number suffix
|
||||
result = Base::Tools::toStdString(formatPrefix) +
|
||||
result +
|
||||
Base::Tools::toStdString(formatSuffix);
|
||||
}
|
||||
else if (partial == 2) { // just the unit
|
||||
if ((Type.isValue("Angle")) || (Type.isValue("Angle3Pt"))) {
|
||||
QRegExp space(QString::fromUtf8("\\s"));
|
||||
qUserStringUnits.remove(space);
|
||||
// remove space between dimension and unit if unit is not "deg"
|
||||
if ( !qUserStringUnits.contains(QString::fromLatin1("deg")) ) {
|
||||
QRegExp space(QString::fromUtf8("\\s"));
|
||||
qUserStringUnits.remove(space);
|
||||
}
|
||||
result = Base::Tools::toStdString(qUserStringUnits);
|
||||
} else if (showUnits()) {
|
||||
result = Base::Tools::toStdString(qUserStringUnits);
|
||||
@@ -759,7 +812,6 @@ std::pair<std::string, std::string> DrawViewDimension::getFormattedToleranceValu
|
||||
|
||||
std::string DrawViewDimension::getFormattedDimensionValue(int partial)
|
||||
{
|
||||
// Base::Console().Message("DVD::getFormattedValue(%d)\n", partial);
|
||||
QString qFormatSpec = QString::fromUtf8(FormatSpec.getStrValue().data());
|
||||
|
||||
if (Arbitrary.getValue()) {
|
||||
@@ -774,9 +826,8 @@ QStringList DrawViewDimension::getPrefixSuffixSpec(QString fSpec)
|
||||
QStringList result;
|
||||
QString formatPrefix;
|
||||
QString formatSuffix;
|
||||
QString formatted;
|
||||
//find the %x.y tag in FormatSpec
|
||||
QRegExp rxFormat(QString::fromUtf8("%[+-]?[0-9]*\\.*[0-9]*[aefgAEFG]")); //printf double format spec
|
||||
QRegExp rxFormat(QString::fromUtf8("%[+-]?[0-9]*\\.*[0-9]*[aefgAEFG]")); //printf double format spec
|
||||
QString match;
|
||||
int pos = 0;
|
||||
if ((pos = rxFormat.indexIn(fSpec, 0)) != -1) {
|
||||
|
||||
Reference in New Issue
Block a user