00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <kdebug.h>
00030 #include <kglobal.h>
00031 #include <klocale.h>
00032
00033 #include <cmath>
00034
00035 namespace KPlato
00036 {
00037
00041 struct FieldDescriptor
00042 {
00043
00044 QLineEdit *left;
00045 double leftScale;
00046
00047
00048 QLineEdit *current;
00049 const char *format;
00050
00051
00052 QLineEdit *right;
00053 double rightScale;
00054
00055
00056 QLabel *separator;
00057
00058
00059 double fullScale;
00060 double scale;
00061
00062
00063 QLabel *unit;
00064 };
00065
00066 #define setField(f, l, ls, c, fmt, r, rs, s, fs, sc, u) \
00067 do \
00068 { \
00069 m_fields[f].left = l; \
00070 m_fields[f].leftScale = ls; \
00071 m_fields[f].current = c; \
00072 m_fields[f].format = fmt; \
00073 m_fields[f].right = r; \
00074 m_fields[f].rightScale = rs; \
00075 m_fields[f].separator = s; \
00076 m_fields[f].fullScale = fs; \
00077 m_fields[f].scale = sc; \
00078 m_fields[f].unit = u; \
00079 } while (0)
00080
00081 void DurationWidget::init()
00082 {
00083
00084 m_decimalPoint = KGlobal::locale()->decimalSymbol();
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 QRegExp re(QString("\\d{1,10}|\\d{1,7}\\") + m_decimalPoint +
00104 QString("\\d{0,10}|\\d{0,7}\\") + m_decimalPoint +
00105 QString("\\d{1,3}"));
00106 m_validator = new QRegExpValidator(re, this);
00107 m_ddd->setValidator(m_validator);
00108 m_hh->setValidator(m_validator);
00109 m_mm->setValidator(m_validator);
00110 m_ss->setValidator(m_validator);
00111 m_ms->setValidator(m_validator);
00112
00113 m_ddUnit->hide();
00114 m_hhUnit->hide();
00115 m_mmUnit->hide();
00116 m_ssUnit->hide();
00117 m_msUnit->hide();
00118
00119 m_fields = new FieldDescriptor[5];
00120 setField(0, NULL, 0, m_ddd, "%u", m_hh, 24, m_hhSpace, 24, 24, m_ddUnit);
00121 setField(1, m_ddd, 24, m_hh, "%02u", m_mm, 60, m_mmColon, 60, 60, m_hhUnit);
00122 setField(2, m_hh, 60, m_mm, "%02u", m_ss, 60, NULL, 60, 60, m_mmUnit);
00123 setField(3, m_mm, 60, m_ss, "%02u", m_ms, 1000, m_ssColon, 60, 60, m_ssUnit);
00124 setField(4, m_ss, 1000, m_ms, "%03u", NULL, 0, m_dot, 1000, 1000, m_msUnit);
00125 }
00126
00127 void DurationWidget::destroy()
00128 {
00129 delete m_fields;
00130
00131 }
00132
00133 Q_INT64 DurationWidget::setValueMilliseconds(Q_INT64 milliseconds)
00134 {
00135 unsigned sc = (unsigned)m_fields[4].leftScale;
00136 Q_INT64 secs = milliseconds / sc;
00137 Q_INT64 ms = milliseconds % sc;
00138 QString tmp;
00139 tmp.sprintf(m_fields[4].format, ms);
00140 m_fields[4].current->setText(tmp);
00141 return secs;
00142 }
00143
00144 Q_INT64 DurationWidget::setValueSeconds(Q_INT64 seconds)
00145 {
00146 unsigned sc = (unsigned)m_fields[3].leftScale;
00147 Q_INT64 mins = seconds / sc;
00148 Q_INT64 s = seconds % sc;
00149 QString tmp;
00150 tmp.sprintf(m_fields[3].format, s);
00151 m_fields[3].current->setText(tmp);
00152 return mins;
00153 }
00154
00155 Q_INT64 DurationWidget::setValueMinutes(Q_INT64 mins)
00156 {
00157 unsigned sc = (unsigned)m_fields[2].leftScale;
00158 Q_INT64 hours = mins / sc;
00159 Q_INT64 m = mins % sc;
00160 QString tmp;
00161 tmp.sprintf(m_fields[2].format, m);
00162 m_fields[2].current->setText(tmp);
00163 return hours;
00164 }
00165
00166
00167 Q_INT64 DurationWidget::setValueHours(Q_INT64 mins)
00168 {
00169 if (m_fields[1].current->isHidden())
00170 return mins;
00171 unsigned sc = (unsigned)m_fields[1].rightScale;
00172 Q_INT64 hours = (Q_INT64)(mins / sc);
00173 Q_INT64 m = mins - (Q_INT64)(hours * sc);
00174
00175 QString tmp;
00176 tmp.sprintf(m_fields[1].format, hours);
00177 m_fields[1].current->setText(tmp);
00178 return m;
00179 }
00180
00181
00182 Q_INT64 DurationWidget::setValueDays(Q_INT64 mins)
00183 {
00184 if (m_fields[0].current->isHidden())
00185 return mins;
00186 double sc = m_fields[1].rightScale * m_fields[0].rightScale;
00187 Q_INT64 days = (Q_INT64)(mins / sc);
00188 Q_INT64 m = mins - (Q_INT64)(days * sc);
00189
00190 QString tmp;
00191 tmp.sprintf(m_fields[0].format, days);
00192 m_fields[0].current->setText(tmp);
00193 return m;
00194 }
00195
00196 void DurationWidget::setValue(const KPlato::Duration &newDuration)
00197 {
00198 Q_INT64 value = newDuration.milliseconds();
00199
00200 value = setValueMilliseconds(value);
00201 value = setValueSeconds(value);
00202
00203 value = setValueDays(value);
00204 value = setValueHours(value);
00205 value = setValueMinutes(value);
00206 if (value > 0) kdError()<<k_funcinfo<<"Remainder > 0: "<<value<<endl;
00207
00208 emit valueChanged();
00209 }
00210
00211 Duration DurationWidget::value() const
00212 {
00213 Duration d;
00214 int i=0;
00215 if (!m_fields[i].current->isHidden() &&
00216 m_fields[i].scale > 0 &&
00217 m_fields[i].scale <= m_fields[i].fullScale)
00218 {
00219 double v = m_fields[i].current->text().toDouble();
00220 v = v * m_fields[i].scale / m_fields[i].fullScale;;
00221 d.addMilliseconds((Q_INT64)(v*(1000*60*60*24)));
00222 }
00223 ++i;
00224 if (!m_fields[i].current->isHidden() &&
00225 m_fields[i].scale > 0 &&
00226 m_fields[i].scale <= m_fields[i].fullScale)
00227 {
00228 double v = m_fields[i].current->text().toDouble();
00229 v = v * m_fields[i].scale / m_fields[i].fullScale;;
00230 d.addMilliseconds((Q_INT64)(v*(1000*60*60)));
00231 }
00232 ++i;
00233 if (!m_fields[i].current->isHidden() &&
00234 m_fields[i].scale > 0 &&
00235 m_fields[i].scale <= m_fields[i].fullScale)
00236 {
00237 double v = m_fields[i].current->text().toDouble();
00238 v = v * m_fields[i].scale / m_fields[i].fullScale;;
00239 d.addMilliseconds((Q_INT64)(v*(1000*60)));
00240 }
00241 ++i;
00242 if (!m_fields[i].current->isHidden() &&
00243 m_fields[i].scale > 0 &&
00244 m_fields[i].scale <= m_fields[i].fullScale)
00245 {
00246 double v = m_fields[i].current->text().toDouble();
00247 v = v * m_fields[i].scale / m_fields[i].fullScale;;
00248 d.addMilliseconds((Q_INT64)(v*(1000)));
00249 }
00250 ++i;
00251 if (!m_fields[i].current->isHidden())
00252 {
00253 Q_INT64 v = m_fields[i].current->text().toUInt();
00254 d.addMilliseconds(v);
00255 }
00256 return d;
00257 }
00258
00259 void DurationWidget::dddLostFocus()
00260 {
00261 handleLostFocus(0);
00262 emit valueChanged();
00263 }
00264
00265 void DurationWidget::hhLostFocus( )
00266 {
00267 handleLostFocus(1);
00268 emit valueChanged();
00269 }
00270
00271 void DurationWidget::mmLostFocus()
00272 {
00273 handleLostFocus(2);
00274 emit valueChanged();
00275 }
00276
00277 void DurationWidget::ssLostFocus()
00278 {
00279 handleLostFocus(3);
00280 emit valueChanged();
00281 }
00282
00283 void DurationWidget::msLostFocus()
00284 {
00285 handleLostFocus(4);
00286 emit valueChanged();
00287 }
00288
00289 void DurationWidget::handleLostFocus(
00290 int field)
00291 {
00292
00293 QLineEdit *left = m_fields[field].left;
00294 double leftScale = m_fields[field].leftScale;
00295 const char *leftFormat = left ? m_fields[field - 1].format : NULL;
00296 QLineEdit *current = m_fields[field].current;
00297 const char *currentFormat = m_fields[field].format;
00298 QLineEdit *right = m_fields[field].right;
00299 double rightScale = m_fields[field].rightScale;
00300 const char *rightFormat = right ? m_fields[field + 1].format : NULL;
00301
00302
00303 if (leftScale == 0)
00304 leftScale = 1;
00305
00306
00307 QString newValue(current->text());
00308 double v = KGlobal::locale()->readNumber(newValue);
00309 unsigned currentValue = 0;
00310 QString tmp;
00311
00312 if (left && v >= leftScale)
00313 {
00314
00315
00316 tmp.sprintf(leftFormat, (unsigned)(v / leftScale));
00317 left->setText(tmp);
00318 handleLostFocus(field - 1);
00319
00320
00321 v = v - (tmp.toUInt() * leftScale);
00322 newValue = KGlobal::locale()->formatNumber(v);
00323 }
00324 int point = newValue.find(m_decimalPoint);
00325 if (point != -1)
00326 {
00327
00328 int p;
00329 double frac = fraction(newValue, &p);
00330 if (right && frac > 0.0)
00331 {
00332
00333
00334 v = rightScale * (frac*power(10.0, -p));
00335 frac = fraction(KGlobal::locale()->formatNumber(v, 19), 0);
00336
00337 if (frac > 0.0)
00338 {
00339 tmp = KGlobal::locale()->formatNumber(v, 19);
00340 right->setText(tmp);
00341 handleLostFocus(field + 1);
00342 } else {
00343 tmp.sprintf(rightFormat, (unsigned)(v));
00344 right->setText(tmp);
00345 }
00346
00347 }
00348
00349 newValue = newValue.left(point);
00350 }
00351 currentValue = newValue.toUInt();
00352 tmp.sprintf(currentFormat, currentValue);
00353 current->setText(tmp);
00354 }
00355
00356
00357 void DurationWidget::setVisibleFields( int fieldMask )
00358 {
00359 int i;
00360 for (i = 0; i < 5; i++)
00361 {
00362 bool visible = ((fieldMask >> i) & 1) == 1;
00363
00364
00365 if (visible)
00366 {
00367 m_fields[i].current->show();
00368 if (m_fields[i].separator)
00369 {
00370 m_fields[i].separator->show();
00371 }
00372 if (m_fields[i].unit)
00373 {
00374 m_fields[i].unit->show();
00375 }
00376 }
00377 else
00378 {
00379 m_fields[i].current->hide();
00380 if (m_fields[i].separator)
00381 {
00382 m_fields[i].separator->hide();
00383 }
00384 if (m_fields[i].unit)
00385 {
00386 m_fields[i].unit->hide();
00387 }
00388 }
00389 }
00390 }
00391
00392
00393 int DurationWidget::visibleFields()
00394 {
00395 int i;
00396 int fieldMask = 0;
00397 for (i = 0; i < 5; i++)
00398 {
00399 if (m_fields[i].current->isHidden())
00400 {
00401 fieldMask |= (1 << i);
00402 }
00403 }
00404 return fieldMask;
00405 }
00406
00407 void DurationWidget::setFieldLeftscale(int f, double ls)
00408 {
00409 m_fields[f].leftScale = ls;
00410 }
00411
00412 void DurationWidget::setFieldRightscale(int f, double rs)
00413 {
00414 m_fields[f].rightScale = rs;
00415 }
00416
00417 void DurationWidget::setFieldScale(int f, double scale)
00418 {
00419 m_fields[f].scale = scale;
00420 }
00421
00422 void DurationWidget::setFieldUnit(int f, QString unit)
00423 {
00424 if (m_fields[f].unit)
00425 {
00426 m_fields[f].unit->setText(unit);
00427 }
00428 }
00429
00430 double DurationWidget::power(double m, int e) {
00431 int c = e > 0 ? e : -e;
00432 double value = 1;
00433 for (int i=0; i < c; ++i) {
00434 value = e > 0 ? value * m : value / m;
00435 }
00436 return value;
00437 }
00438
00439 double DurationWidget::fraction(QString number, int *exp) {
00440 int point = number.find(m_decimalPoint);
00441 if (point == -1) {
00442 return 0.0;
00443 }
00444 QString v;
00445 if (exp) {
00446 v = number.mid(point+m_decimalPoint.length());
00447 *exp = v.length();
00448
00449 } else {
00450 v = number.mid(point);
00451 }
00452 return KGlobal::locale()->readNumber(v);
00453 }
00454
00455 }