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