1 /* This file is part of Step.
2 Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
3
4 Step is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 Step is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Step; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "unitscalc.h"
20
21 #ifdef STEP_WITH_QALCULATE
22 #include <libqalculate/qalculate.h>
23 #endif
24
25 class UnitsCalcHelper
26 {
27 public:
UnitsCalcHelper()28 UnitsCalcHelper(): q(0) {}
~UnitsCalcHelper()29 ~UnitsCalcHelper() { delete q; }
30 UnitsCalc* q;
31 };
32
Q_GLOBAL_STATIC(UnitsCalcHelper,s_unitsCalcHelper)33 Q_GLOBAL_STATIC(UnitsCalcHelper, s_unitsCalcHelper)
34
35 UnitsCalc* UnitsCalc::self()
36 {
37 if(!s_unitsCalcHelper->q) {
38 new UnitsCalc();
39 }
40
41 return s_unitsCalcHelper->q;
42 }
43
44 class UnitsCalcPrivate
45 {
46 public:
47 #ifdef STEP_WITH_QALCULATE
48 EvaluationOptions eo;
49 #endif
50 };
51
UnitsCalc()52 UnitsCalc::UnitsCalc()
53 {
54 Q_ASSERT(!s_unitsCalcHelper->q);
55 s_unitsCalcHelper->q = this;
56
57 d = new UnitsCalcPrivate;
58
59 #ifdef STEP_WITH_QALCULATE
60 new Calculator();
61 CALCULATOR->loadGlobalPrefixes();
62 CALCULATOR->loadGlobalUnits();
63 CALCULATOR->loadGlobalVariables();
64 CALCULATOR->loadGlobalFunctions();
65
66 ParseOptions po;
67 po.unknowns_enabled = false;
68 po.limit_implicit_multiplication = true;
69 po.angle_unit = ANGLE_UNIT_RADIANS;
70
71 d->eo.parse_options = po;
72 d->eo.approximation = APPROXIMATION_APPROXIMATE;
73 d->eo.allow_complex = false;
74 d->eo.auto_post_conversion = POST_CONVERSION_BEST;
75 d->eo.structuring = STRUCTURING_SIMPLIFY;
76 #endif
77 }
78
~UnitsCalc()79 UnitsCalc::~UnitsCalc()
80 {
81 delete d;
82
83 #ifdef STEP_WITH_QALCULATE
84 delete CALCULATOR;
85 #endif
86 }
87
88 #ifdef STEP_WITH_QALCULATE
parseNumber(const QString & expression,const QString & units,double & result)89 bool UnitsCalc::parseNumber(const QString& expression, const QString& units, double& result)
90 {
91 std::string ulexpression = CALCULATOR->unlocalizeExpression(
92 expression.toUtf8().constData(), d->eo.parse_options);
93
94 MathStructure expr;
95 CALCULATOR->parse(&expr, ulexpression, d->eo.parse_options);
96 expr.eval(d->eo);
97
98 if(!units.isEmpty()) {
99 CompositeUnit *cu = NULL;
100 Unit *u = NULL;
101 std::string strUnits(units.toUtf8().constData());
102 u = CALCULATOR->getUnit(strUnits);
103 if(!u) {
104 cu = new CompositeUnit("", "temporary_composite_convert", "", strUnits);
105 if(cu->get(1)) u = cu;
106 else return false;
107 }
108
109 expr.convert(u, true);
110 expr.divide(u, true);
111 expr.eval(d->eo);
112
113 delete cu;
114 }
115
116 if(!expr.isNumber() && expr.countChildren()) return false;
117 result = expr.number().floatValue();
118 return true;
119
120 }
121 #else
parseNumber(const QString &,const QString &,double &)122 bool UnitsCalc::parseNumber(const QString&, const QString&, double&)
123 {
124 return false;
125 }
126 #endif
127
128