File indexing completed on 2024-04-28 03:51:21
0001 /*. 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "unitscalc.h" 0008 0009 #ifdef STEP_WITH_QALCULATE 0010 #include <libqalculate/qalculate.h> 0011 #endif 0012 0013 class UnitsCalcHelper 0014 { 0015 public: 0016 UnitsCalcHelper(): q(nullptr) {} 0017 ~UnitsCalcHelper() { delete q; } 0018 UnitsCalc* q; 0019 }; 0020 0021 Q_GLOBAL_STATIC(UnitsCalcHelper, s_unitsCalcHelper) 0022 0023 UnitsCalc* UnitsCalc::self() 0024 { 0025 if(!s_unitsCalcHelper->q) { 0026 new UnitsCalc(); 0027 } 0028 0029 return s_unitsCalcHelper->q; 0030 } 0031 0032 class UnitsCalcPrivate 0033 { 0034 public: 0035 #ifdef STEP_WITH_QALCULATE 0036 EvaluationOptions eo; 0037 #endif 0038 }; 0039 0040 UnitsCalc::UnitsCalc() 0041 { 0042 Q_ASSERT(!s_unitsCalcHelper->q); 0043 s_unitsCalcHelper->q = this; 0044 0045 d = new UnitsCalcPrivate; 0046 0047 #ifdef STEP_WITH_QALCULATE 0048 new Calculator(); 0049 CALCULATOR->loadGlobalPrefixes(); 0050 CALCULATOR->loadGlobalUnits(); 0051 CALCULATOR->loadGlobalVariables(); 0052 CALCULATOR->loadGlobalFunctions(); 0053 0054 ParseOptions po; 0055 po.unknowns_enabled = false; 0056 po.limit_implicit_multiplication = true; 0057 po.angle_unit = ANGLE_UNIT_RADIANS; 0058 0059 d->eo.parse_options = po; 0060 d->eo.approximation = APPROXIMATION_APPROXIMATE; 0061 d->eo.allow_complex = false; 0062 d->eo.auto_post_conversion = POST_CONVERSION_BEST; 0063 d->eo.structuring = STRUCTURING_SIMPLIFY; 0064 #endif 0065 } 0066 0067 UnitsCalc::~UnitsCalc() 0068 { 0069 delete d; 0070 0071 #ifdef STEP_WITH_QALCULATE 0072 delete CALCULATOR; 0073 #endif 0074 } 0075 0076 #ifdef STEP_WITH_QALCULATE 0077 bool UnitsCalc::parseNumber(const QString& expression, const QString& units, double& result) 0078 { 0079 std::string ulexpression = CALCULATOR->unlocalizeExpression( 0080 expression.toUtf8().constData(), d->eo.parse_options); 0081 0082 MathStructure expr; 0083 CALCULATOR->parse(&expr, ulexpression, d->eo.parse_options); 0084 expr.eval(d->eo); 0085 0086 if(!units.isEmpty()) { 0087 CompositeUnit *cu = nullptr; 0088 Unit *u = nullptr; 0089 std::string strUnits(units.toUtf8().constData()); 0090 u = CALCULATOR->getUnit(strUnits); 0091 if(!u) { 0092 cu = new CompositeUnit("", "temporary_composite_convert", "", strUnits); 0093 if(cu->get(1)) u = cu; 0094 else return false; 0095 } 0096 0097 expr.convert(u, true); 0098 expr.divide(u, true); 0099 expr.eval(d->eo); 0100 0101 delete cu; 0102 } 0103 0104 if(!expr.isNumber() && expr.countChildren()) return false; 0105 result = expr.number().floatValue(); 0106 return true; 0107 0108 } 0109 #else 0110 bool UnitsCalc::parseNumber(const QString&, const QString&, double&) 0111 { 0112 return false; 0113 } 0114 #endif 0115