1 /***************************************************************************
2 * file klfunitinput.cpp
3 * This file is part of the KLatexFormula Project.
4 * Copyright (C) 2011 by Philippe Faist
5 * philippe.faist at bluewin.ch
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 /* $Id: klfunitinput.cpp 604 2011-02-27 23:34:37Z phfaist $ */
23
24 #include <math.h>
25
26 #include <QDebug>
27 #include <QVariant>
28 #include <QStringList>
29 #include <QComboBox>
30 #include <QDoubleSpinBox>
31 #include <QEvent>
32
33 #include "klfunitinput.h"
34
35
KLFUnitChooser(QWidget * parent)36 KLFUnitChooser::KLFUnitChooser(QWidget *parent)
37 : QComboBox(parent)
38 {
39 connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(internalCurrentIndexChanged(int)));
40 }
~KLFUnitChooser()41 KLFUnitChooser::~KLFUnitChooser()
42 {
43 }
44
setUnits(const QString & unitstr)45 void KLFUnitChooser::setUnits(const QString& unitstr)
46 {
47 QStringList unitstrlist = unitstr.split(';');
48 QList<Unit> units;
49 int k;
50 for (k = 0; k < unitstrlist.size(); ++k) {
51 QStringList parts = unitstrlist[k].split('=');
52 if (parts.size() != 3) {
53 qWarning()<<KLF_FUNC_NAME<<": Invalid unit specification: "<<unitstrlist[k];
54 continue;
55 }
56 Unit u;
57 u.name = parts[0];
58 u.abbrev = parts[1];
59 u.factor = parts[2].toDouble();
60 units << u;
61 }
62 setUnits(units);
63 }
64
setUnits(const QList<Unit> & unitlist)65 void KLFUnitChooser::setUnits(const QList<Unit>& unitlist)
66 {
67 clear(); // clear combo box
68 pUnits = unitlist;
69 int k;
70 for (k = 0; k < pUnits.size(); ++k) {
71 Unit u = pUnits[k];
72 // add this cbx item
73 addItem(u.name, QVariant::fromValue<Unit>(u));
74 }
75 }
76
unitStringDescription() const77 QString KLFUnitChooser::unitStringDescription() const
78 {
79 QStringList l;
80 int k;
81 for (k = 0; k < pUnits.size(); ++k)
82 l << QString("%2=%3=%1").arg(pUnits[k].factor, 0, 'g').arg(pUnits[k].name, pUnits[k].abbrev);
83 return l.join(";");
84 }
85
setCurrentUnit(const QString & unitname)86 void KLFUnitChooser::setCurrentUnit(const QString& unitname)
87 {
88 int k;
89 for (k = 0; k < count(); ++k) {
90 if (itemData(k).value<Unit>().name == unitname) {
91 setCurrentUnitIndex(k);
92 return;
93 }
94 }
95 qWarning()<<KLF_FUNC_NAME<<": unit "<<unitname<<" not found.";
96 }
setCurrentUnitAbbrev(const QString & unitAbbrev)97 void KLFUnitChooser::setCurrentUnitAbbrev(const QString& unitAbbrev)
98 {
99 int k;
100 for (k = 0; k < count(); ++k) {
101 if (itemData(k).value<Unit>().abbrev == unitAbbrev) {
102 setCurrentUnitIndex(k);
103 return;
104 }
105 }
106 qWarning()<<KLF_FUNC_NAME<<": unit abbrev. "<<unitAbbrev<<" not found.";
107 }
108
109 // private
setCurrentUnitIndex(int k)110 void KLFUnitChooser::setCurrentUnitIndex(int k)
111 {
112 if (isEnabled()) {
113 setCurrentIndex(k);
114 } else {
115 pDelayedUnitSet = pUnits[k].name;
116 emit unitChanged(pUnits[k].name);
117 emit unitChanged(pUnits[k].factor);
118 emit unitChanged(pUnits[k].factor, pUnits[k].abbrev);
119 }
120 }
121
changeEvent(QEvent * event)122 void KLFUnitChooser::changeEvent(QEvent *event)
123 {
124 if (event->type() == QEvent::EnabledChange) {
125 if (isEnabled() && !pDelayedUnitSet.isEmpty()) {
126 setCurrentUnit(pDelayedUnitSet);
127 pDelayedUnitSet = QString();
128 }
129 }
130 QComboBox::changeEvent(event);
131 }
132
133
internalCurrentIndexChanged(int index)134 void KLFUnitChooser::internalCurrentIndexChanged(int index)
135 {
136 if (index < 0 || index >= count())
137 return;
138
139 Unit u = itemData(index).value<Unit>();
140 klfDbg("New unit selected : #"<<index<<" = "<<u.name) ;
141 emit unitChanged(u.name);
142 emit unitChanged(u.factor);
143 emit unitChanged(u.factor, u.abbrev);
144 }
145
146
147 // -------------------------
148
149
KLFUnitSpinBox(QWidget * parent)150 KLFUnitSpinBox::KLFUnitSpinBox(QWidget *parent)
151 : QDoubleSpinBox(parent)
152 {
153 pUnitFactor = 1.0f;
154 pShowUnitSuffix = true;
155 connect(this, SIGNAL(valueChanged(double)), this, SLOT(internalValueChanged(double)));
156 }
~KLFUnitSpinBox()157 KLFUnitSpinBox::~KLFUnitSpinBox()
158 {
159 }
160
setUnit(double unitfactor)161 void KLFUnitSpinBox::setUnit(double unitfactor)
162 {
163 double curValue = value();
164 double curMinimum = minimum();
165 double curMaximum = maximum();
166 double curUnitFactor = pUnitFactor;
167 int curPrecision = decimals();
168
169 klfDbg("unitfactor="<<unitfactor<<" cur: val="<<curValue<<",min="<<curMinimum<<",max="<<curMaximum
170 <<",prec="<<curPrecision) ;
171
172 pUnitFactor = unitfactor;
173
174 // calculate the right number of decimal places.
175 // due to round-off errors, we need to first determine how many decimals we started
176 // off with, then re-calculate the number of decimals.
177 int unitRefDecimals = curPrecision - (int)( log((double)curUnitFactor)/log((double)10.0) + 0.5 );
178
179 setDecimals(unitRefDecimals + (int)( log((double)pUnitFactor)/log((double)10.0) + 0.5 ) );
180
181 // set the appropriate range
182 setMinimum(curMinimum * curUnitFactor / pUnitFactor);
183 setMaximum(curMaximum * curUnitFactor / pUnitFactor);
184
185 // and set the value
186 setValue(curValue * curUnitFactor / pUnitFactor);
187 }
188
setUnitWithSuffix(double unitfactor,const QString & suffix)189 void KLFUnitSpinBox::setUnitWithSuffix(double unitfactor, const QString& suffix)
190 {
191 setUnit(unitfactor);
192 if (pShowUnitSuffix)
193 setSuffix(" "+suffix);
194 }
195
setValueInRefUnit(double value)196 void KLFUnitSpinBox::setValueInRefUnit(double value)
197 {
198 setValue(value / pUnitFactor);
199 }
200
setShowUnitSuffix(bool show)201 void KLFUnitSpinBox::setShowUnitSuffix(bool show)
202 {
203 pShowUnitSuffix = show;
204 }
205
206
internalValueChanged(double valueInExtUnits)207 void KLFUnitSpinBox::internalValueChanged(double valueInExtUnits)
208 {
209 klfDbg("val in ext. units="<<valueInExtUnits<<"; our unitfactor="<<pUnitFactor) ;
210 emit valueInRefUnitChanged(valueInExtUnits / pUnitFactor);
211 }
212
213
214
215
216