File indexing completed on 2024-04-21 07:37:58

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