Rev 8440 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4430 | cbradney | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
3 | paul | 7 | /*************************************************************************** |
8 | mspinbox.cpp - description |
||
9 | ------------------- |
||
10 | begin : Sat Jun 16 2001 |
||
11 | copyright : (C) 2001 by Franz Schmid |
||
12 | email : Franz.Schmid@altmuehlnet.de |
||
13 | ***************************************************************************/ |
||
14 | |||
15 | /*************************************************************************** |
||
16 | * * |
||
17 | * This program is free software; you can redistribute it and/or modify * |
||
18 | * it under the terms of the GNU General Public License as published by * |
||
19 | * the Free Software Foundation; either version 2 of the License, or * |
||
20 | * (at your option) any later version. * |
||
21 | * * |
||
22 | ***************************************************************************/ |
||
23 | |||
24 | #include "mspinbox.h" |
||
280 | Franz | 25 | #include "mspinbox.moc" |
137 | Franz | 26 | #include <qapplication.h> |
333 | Franz | 27 | #include <qlineedit.h> |
4112 | cbradney | 28 | #include <qregexp.h> |
1568 | cbradney | 29 | #include <cmath> |
137 | Franz | 30 | #include "fparser.h" |
1568 | cbradney | 31 | #include "units.h" |
3 | paul | 32 | |
146 | Franz | 33 | |
3 | paul | 34 | MSpinBox::MSpinBox(QWidget *pa, int s):QSpinBox(pa) |
35 | { |
||
333 | Franz | 36 | setParameters(s); |
37 | setValidator(0); |
||
38 | ed = editor(); |
||
39 | QSpinBox::setLineStep(Decimals); |
||
40 | oldLineStep=0; |
||
41 | readOnly=false; |
||
1617 | fschmid | 42 | edited = false; |
43 | connect( ed, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) ); |
||
333 | Franz | 44 | } |
45 | |||
46 | MSpinBox::MSpinBox(double minValue, double maxValue, QWidget *pa, int s):QSpinBox(pa) |
||
47 | { |
||
48 | setParameters(s); |
||
49 | setValidator(0); |
||
50 | ed = editor(); |
||
51 | QSpinBox::setLineStep(Decimals); |
||
52 | oldLineStep=0; |
||
53 | setMinValue(minValue); |
||
54 | setMaxValue(maxValue); |
||
55 | readOnly=false; |
||
1617 | fschmid | 56 | edited = false; |
57 | connect( ed, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) ); |
||
333 | Franz | 58 | } |
59 | |||
60 | void MSpinBox::setParameters( int s ) |
||
61 | { |
||
1795 | cbradney | 62 | if (s>=0 && s <=unitGetMaxIndex()) |
161 | Franz | 63 | { |
1568 | cbradney | 64 | Width=s; |
10812 | cbradney | 65 | Decimals=static_cast<int>(pow(10.0, s)); |
161 | Franz | 66 | } |
1568 | cbradney | 67 | else |
68 | { |
||
69 | Width = 2; |
||
70 | Decimals = 100; |
||
71 | } |
||
1617 | fschmid | 72 | edited = false; |
3 | paul | 73 | } |
74 | |||
75 | bool MSpinBox::eventFilter( QObject* ob, QEvent* ev ) |
||
76 | { |
||
2680 | cbradney | 77 | bool retval = false; |
3 | paul | 78 | if ( ev->type() == QEvent::KeyPress ) |
161 | Franz | 79 | { |
3 | paul | 80 | QKeyEvent* k = (QKeyEvent*)ev; |
6004 | cbradney | 81 | bool shiftB=k->state() & ShiftButton; |
82 | bool controlB=k->state() & ControlButton; |
||
83 | if (k->key() == Key_Shift && !controlB) |
||
161 | Franz | 84 | { |
138 | Franz | 85 | setLineStep(QMAX(Decimals / 10, 1)); |
3 | paul | 86 | retval = true; |
6004 | cbradney | 87 | qApp->sendEvent( this, ev ); |
3 | paul | 88 | return retval; |
89 | } |
||
6004 | cbradney | 90 | else if (k->key() == Key_Control && !shiftB) |
3736 | fschmid | 91 | { |
92 | setLineStep(QMAX(Decimals * 10, 1)); |
||
93 | retval = true; |
||
6004 | cbradney | 94 | qApp->sendEvent( this, ev ); |
3736 | fschmid | 95 | return retval; |
96 | } |
||
6004 | cbradney | 97 | else if ((k->key() == Key_Control && shiftB) || (k->key() == Key_Shift && controlB)) |
98 | { |
||
99 | setLineStep(QMAX(Decimals / 100, 1)); |
||
100 | retval = true; |
||
101 | qApp->sendEvent( this, ev ); |
||
102 | return retval; |
||
103 | } |
||
161 | Franz | 104 | } |
3736 | fschmid | 105 | if (ev->type() == QEvent::KeyRelease ) |
161 | Franz | 106 | { |
3 | paul | 107 | QKeyEvent* k = (QKeyEvent*)ev; |
6004 | cbradney | 108 | bool shiftB=k->stateAfter() & ShiftButton; |
109 | bool controlB=k->stateAfter() & ControlButton; |
||
110 | if ((k->key() == Key_Shift && !controlB) || (k->key() == Key_Control && !shiftB)) |
||
161 | Franz | 111 | { |
3 | paul | 112 | setLineStep(Decimals); |
113 | retval = true; |
||
161 | Franz | 114 | qApp->sendEvent( this, ev ); |
3 | paul | 115 | return retval; |
364 | Franz | 116 | } |
6004 | cbradney | 117 | else if (k->key() == Key_Shift && controlB) |
118 | { |
||
119 | setLineStep(QMAX(Decimals * 10, 1)); |
||
120 | retval = true; |
||
121 | qApp->sendEvent( this, ev ); |
||
122 | return retval; |
||
123 | } |
||
124 | else if (k->key() == Key_Control && shiftB) |
||
125 | { |
||
126 | setLineStep(QMAX(Decimals / 10, 1)); |
||
127 | retval = true; |
||
128 | qApp->sendEvent( this, ev ); |
||
129 | return retval; |
||
130 | } |
||
364 | Franz | 131 | } |
132 | if ( ev->type() == QEvent::Wheel ) |
||
133 | { |
||
4013 | cbradney | 134 | //If read only dont spin |
135 | if (readOnly) |
||
136 | return false; |
||
364 | Franz | 137 | QWheelEvent* k = (QWheelEvent*)ev; |
4027 | cbradney | 138 | bool shiftB=k->state() & ShiftButton; |
139 | bool controlB=k->state() & ControlButton; |
||
140 | if (shiftB && !controlB) |
||
364 | Franz | 141 | { |
142 | setLineStep(QMAX(Decimals / 10, 1)); |
||
143 | retval = true; |
||
144 | qApp->sendEvent( this, ev ); |
||
145 | return retval; |
||
6004 | cbradney | 146 | } |
4027 | cbradney | 147 | else if (!shiftB && controlB) |
364 | Franz | 148 | { |
3736 | fschmid | 149 | setLineStep(QMAX(Decimals * 10, 1)); |
150 | retval = true; |
||
151 | qApp->sendEvent( this, ev ); |
||
152 | return retval; |
||
153 | } |
||
4027 | cbradney | 154 | else if (shiftB && controlB) |
3736 | fschmid | 155 | { |
4027 | cbradney | 156 | setLineStep(QMAX(Decimals / 100, 1)); |
157 | retval = true; |
||
158 | qApp->sendEvent( this, ev ); |
||
159 | return retval; |
||
160 | } |
||
161 | else |
||
162 | if (!shiftB && !controlB) |
||
163 | { |
||
364 | Franz | 164 | setLineStep(Decimals); |
165 | retval = true; |
||
166 | qApp->sendEvent( this, ev ); |
||
167 | return retval; |
||
4027 | cbradney | 168 | } |
161 | Franz | 169 | } |
3 | paul | 170 | return QSpinBox::eventFilter(ob, ev); |
171 | } |
||
172 | |||
173 | QString MSpinBox::mapValueToText(int value) |
||
174 | { |
||
5448 | cbradney | 175 | QString s; |
176 | s.setNum(static_cast<double>(value) / Decimals, 'f', Width); |
||
177 | return s; |
||
3 | paul | 178 | } |
179 | |||
180 | int MSpinBox::mapTextToValue(bool *) |
||
181 | { |
||
161 | Franz | 182 | FunctionParser fp; |
4110 | cbradney | 183 | setFPConstants(fp); |
138 | Franz | 184 | QString ts = text(); |
286 | Franz | 185 | QString su = suffix().stripWhiteSpace(); |
138 | Franz | 186 | ts.replace(",", "."); |
272 | Franz | 187 | ts.replace("%", ""); |
4944 | fschmid | 188 | int pos = ts.length(); |
189 | while (pos > 0) |
||
190 | { |
||
191 | pos = ts.findRev(".", pos); |
||
6004 | cbradney | 192 | if (pos >= 0) |
4944 | fschmid | 193 | { |
194 | if (pos < static_cast<int>(ts.length())) |
||
195 | { |
||
196 | if (!ts[pos+1].isDigit()) |
||
197 | ts.insert(pos+1, "0 "); |
||
198 | } |
||
199 | pos--; |
||
200 | } |
||
201 | } |
||
202 | if (ts.endsWith(".")) |
||
203 | ts.append("0"); |
||
6004 | cbradney | 204 | |
4114 | cbradney | 205 | //Get all our units strings |
4539 | cbradney | 206 | QString trStrPT=unitGetStrFromIndex(SC_PT); |
207 | QString trStrMM=unitGetStrFromIndex(SC_MM); |
||
208 | QString trStrIN=unitGetStrFromIndex(SC_IN); |
||
209 | QString trStrP =unitGetStrFromIndex(SC_P); |
||
210 | QString trStrCM=unitGetStrFromIndex(SC_CM); |
||
211 | QString trStrC =unitGetStrFromIndex(SC_C); |
||
212 | QString strPT=unitGetUntranslatedStrFromIndex(SC_PT); |
||
213 | QString strMM=unitGetUntranslatedStrFromIndex(SC_MM); |
||
214 | QString strIN=unitGetUntranslatedStrFromIndex(SC_IN); |
||
215 | QString strP =unitGetUntranslatedStrFromIndex(SC_P); |
||
216 | QString strCM=unitGetUntranslatedStrFromIndex(SC_CM); |
||
217 | QString strC =unitGetUntranslatedStrFromIndex(SC_C); |
||
218 | //CB FParser doesn't handle unicode well/at all. |
||
219 | //So, instead of just getting the translated strings and |
||
220 | //sticking them in as variables in the parser, if they are |
||
221 | //not the same as the untranslated version, then we replace them. |
||
6004 | cbradney | 222 | //We lose the ability for now to have some strings in languages |
4539 | cbradney | 223 | //that might use them in variables. |
224 | //To return to previous functionality, remove the follow replacement ifs, |
||
6004 | cbradney | 225 | //S&R in the trStr* assignments trStrPT->strPT and remove the current str* ones. |
4539 | cbradney | 226 | //IE, send the translated strings through to the regexp. |
227 | if (trStrPT.localeAwareCompare(strPT)!=0) |
||
228 | ts.replace(trStrPT, strPT); |
||
229 | if (trStrMM.localeAwareCompare(strMM)!=0) |
||
230 | ts.replace(trStrMM, strMM); |
||
231 | if (trStrIN.localeAwareCompare(strIN)!=0) |
||
232 | ts.replace(trStrIN, strIN); |
||
233 | if (trStrP.localeAwareCompare(strP)!=0) |
||
234 | ts.replace(trStrP, strP); |
||
235 | if (trStrCM.localeAwareCompare(strCM)!=0) |
||
236 | ts.replace(trStrCM, strCM); |
||
8440 | jghali | 237 | if (trStrC.localeAwareCompare(strC)!=0) |
4539 | cbradney | 238 | ts.replace(trStrC, strC); |
4114 | cbradney | 239 | //Replace in our typed text all of the units strings with *unitstring |
4112 | cbradney | 240 | QRegExp rx("\\b(\\d+)\\s*("+strPT+"|"+strP+"|"+strMM+"|"+strC+"|"+strCM+"|"+strIN+")\\b"); |
4944 | fschmid | 241 | pos = 0; |
4112 | cbradney | 242 | while (pos >= 0) { |
243 | pos = rx.search(ts, pos); |
||
244 | if (pos >= 0) { |
||
245 | QString replacement = rx.cap(1) + "*" + rx.cap(2); |
||
246 | ts.replace(pos, rx.cap(0).length(), replacement); |
||
247 | } |
||
248 | } |
||
4114 | cbradney | 249 | //Get the index of our suffix |
250 | int toConvertToIndex=unitIndexFromString(su); |
||
251 | //Add in the fparser constants using our unit strings, and the conversion factors. |
||
8440 | jghali | 252 | fp.AddConstant(strPT.local8Bit().data(), value2value(1.0, SC_PT, toConvertToIndex)); |
253 | fp.AddConstant(strMM.local8Bit().data(), value2value(1.0, SC_MM, toConvertToIndex)); |
||
254 | fp.AddConstant(strIN.local8Bit().data(), value2value(1.0, SC_IN, toConvertToIndex)); |
||
255 | fp.AddConstant(strP.local8Bit().data(), value2value(1.0, SC_P, toConvertToIndex)); |
||
256 | fp.AddConstant(strCM.local8Bit().data(), value2value(1.0, SC_CM, toConvertToIndex)); |
||
257 | fp.AddConstant(strC.local8Bit().data(), value2value(1.0, SC_C, toConvertToIndex)); |
||
161 | Franz | 258 | int ret = fp.Parse(ts.latin1(), "", true); |
137 | Franz | 259 | if (ret >= 0) |
260 | return 0; |
||
161 | Franz | 261 | double erg = fp.Eval(NULL); |
139 | Franz | 262 | return qRound(erg*Decimals); |
3 | paul | 263 | } |
264 | |||
1617 | fschmid | 265 | void MSpinBox::textChanged() |
266 | { |
||
267 | edited = true; |
||
268 | } |
||
269 | |||
270 | void MSpinBox::stepDown() |
||
271 | { |
||
272 | if ( edited ) |
||
273 | QSpinBox::interpretText(); |
||
274 | if ( wrapping() && ( QSpinBox::value()-lineStep() < QSpinBox::minValue() ) ) |
||
275 | QSpinBox::setValue( QSpinBox::maxValue() - (QSpinBox::maxValue() % lineStep())); |
||
276 | else |
||
277 | QSpinBox::subtractLine(); |
||
278 | } |
||
279 | |||
333 | Franz | 280 | void MSpinBox::setValues(double min, double max, int deci, double val) |
281 | { |
||
282 | setDecimals(deci); |
||
283 | setMinValue(min); |
||
284 | setMaxValue(max); |
||
285 | setValue(val); |
||
1617 | fschmid | 286 | edited = false; |
333 | Franz | 287 | } |
288 | |||
289 | void MSpinBox::getValues(double *min, double *max, int *deci, double *val) |
||
290 | { |
||
291 | *deci = Decimals; |
||
292 | *min = static_cast<double>(QSpinBox::minValue()) / Decimals; |
||
293 | *max = static_cast<double>(QSpinBox::maxValue()) / Decimals; |
||
294 | *val = static_cast<double>(QSpinBox::value()) / Decimals; |
||
295 | } |
||
296 | |||
3 | paul | 297 | void MSpinBox::setDecimals(int deci) |
298 | { |
||
299 | Decimals = deci; |
||
146 | Franz | 300 | QSpinBox::setLineStep(Decimals); |
138 | Franz | 301 | if (deci < 10) |
302 | Width = 0; |
||
199 | Franz | 303 | if ((deci > 9) && (deci < 100)) |
3 | paul | 304 | Width = 1; |
199 | Franz | 305 | if ((deci > 99) && (deci < 1000)) |
3 | paul | 306 | Width = 2; |
199 | Franz | 307 | if ((deci > 999) && (deci < 10000)) |
139 | Franz | 308 | Width = 3; |
309 | if (deci > 9999) |
||
310 | Width = 4; |
||
3 | paul | 311 | } |
146 | Franz | 312 | |
313 | void MSpinBox::setMaxValue(double val) |
||
314 | { |
||
315 | QSpinBox::setMaxValue(qRound(val*Decimals)); |
||
316 | } |
||
317 | |||
318 | void MSpinBox::setMinValue(double val) |
||
319 | { |
||
320 | QSpinBox::setMinValue(qRound(val*Decimals)); |
||
321 | } |
||
322 | |||
323 | void MSpinBox::setValue(double val) |
||
324 | { |
||
325 | QSpinBox::setValue(qRound(val*Decimals)); |
||
1617 | fschmid | 326 | edited = false; |
146 | Franz | 327 | } |
328 | |||
329 | double MSpinBox::value() |
||
330 | { |
||
331 | return static_cast<double>(QSpinBox::value()) / Decimals; |
||
332 | } |
||
199 | Franz | 333 | |
334 | double MSpinBox::minValue() |
||
335 | { |
||
336 | return static_cast<double>(QSpinBox::minValue()) / Decimals; |
||
337 | } |
||
338 | |||
339 | double MSpinBox::maxValue() |
||
340 | { |
||
341 | return static_cast<double>(QSpinBox::maxValue()) / Decimals; |
||
342 | } |
||
333 | Franz | 343 | |
344 | void MSpinBox::setReadOnly( bool ro ) |
||
345 | { |
||
6004 | cbradney | 346 | if (readOnly!=ro) |
335 | Franz | 347 | { |
333 | Franz | 348 | if (!readOnly && ro) { |
349 | oldLineStep=QSpinBox::lineStep(); |
||
350 | QSpinBox::setLineStep( 0 ); |
||
351 | } |
||
352 | else if (readOnly && !ro) { |
||
353 | QSpinBox::setLineStep( oldLineStep ); |
||
354 | oldLineStep=0; |
||
355 | } |
||
356 | ed->setReadOnly( ro ); |
||
335 | Franz | 357 | readOnly=ro; |
333 | Franz | 358 | } |
359 | } |
||
360 | |||
361 | bool MSpinBox::isReadOnly() const |
||
362 | { |
||
363 | return readOnly; |
||
364 | } |
||
365 | |||
4110 | cbradney | 366 | void MSpinBox::setConstants(const QMap<QString, double>& newConstants) |
367 | { |
||
368 | functionParserConstants=newConstants; |
||
369 | } |
||
370 | |||
371 | void MSpinBox::setFPConstants(FunctionParser &fp) |
||
372 | { |
||
373 | if (functionParserConstants.isEmpty()) |
||
374 | return; |
||
6004 | cbradney | 375 | |
4115 | cbradney | 376 | fp.AddConstant("old", static_cast<double>(QSpinBox::value()) / Decimals); |
4110 | cbradney | 377 | QMap<QString, double>::Iterator itend=functionParserConstants.end(); |
378 | QMap<QString, double>::Iterator it=functionParserConstants.begin(); |
||
379 | while(it!=itend) |
||
380 | { |
||
8440 | jghali | 381 | fp.AddConstant(it.key().local8Bit().data(), it.data()); |
4110 | cbradney | 382 | ++it; |
383 | } |
||
384 | } |