// // ui.h extension file, included from the uic-generated form implementation. // // If you wish to add, delete or rename functions or slots use // TQt Designer which will update this file, preserving your code. Create an // init() function in place of a constructor, and a destroy() function in // place of a destructor. // /* This file is part of the KDE project Copyright (C) 2004 - 2006 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include namespace KPlato { /** * This structure describes one of the fields shown. */ struct FieldDescriptor { // Which field is to my left, and what conversion factor separates us? TQLineEdit *left; double leftScale; // Which field am I, and how am I formatted? TQLineEdit *current; const char *format; // Which field is to my right, and what conversion factor separates us? TQLineEdit *right; double rightScale; // If I am hidden, who else hides with me? TQLabel *separator; // Used for calculating a correct duration double fullScale; double scale; // Used for displaying a unit behind each field TQLabel *unit; }; #define setField(f, l, ls, c, fmt, r, rs, s, fs, sc, u) \ do \ { \ m_fields[f].left = l; \ m_fields[f].leftScale = ls; \ m_fields[f].current = c; \ m_fields[f].format = fmt; \ m_fields[f].right = r; \ m_fields[f].rightScale = rs; \ m_fields[f].separator = s; \ m_fields[f].fullScale = fs; \ m_fields[f].scale = sc; \ m_fields[f].unit = u; \ } while (0) void DurationWidget::init() { // Use the user's decimal point! m_decimalPoint = TDEGlobal::locale()->decimalSymbol(); //NOTE: // This isn't as flexible/general as Shaheed once made it. // It's now a long list of hacks. // Introducing double in scales and allowing leftscale/scale/rightscale // *NOT* to be multiples of each other increases the complexity and also // introduces rounding errors. (eg. hour = 60 minutes, day = 7,5 hours) // // If you know how, please make a better solution! // // Any field can be entered as an integer or a floating point value. Whatever // is entered is treated as follows: // // - any fractional part is moved right one field // // - any overflow from the integer part is carried left one field // // and the process repeated until the rightmost and leftmost fields are reached. TQRegExp re(TQString("\\d{1,10}|\\d{1,7}\\") + m_decimalPoint + TQString("\\d{0,10}|\\d{0,7}\\") + m_decimalPoint + TQString("\\d{1,3}")); m_validator = new TQRegExpValidator(re, this); m_ddd->setValidator(m_validator); m_hh->setValidator(m_validator); m_mm->setValidator(m_validator); m_ss->setValidator(m_validator); m_ms->setValidator(m_validator); m_ddUnit->hide(); m_hhUnit->hide(); m_mmUnit->hide(); m_ssUnit->hide(); m_msUnit->hide(); m_fields = new FieldDescriptor[5]; setField(0, NULL, 0, m_ddd, "%u", m_hh, 24, m_hhSpace, 24, 24, m_ddUnit); setField(1, m_ddd, 24, m_hh, "%02u", m_mm, 60, m_mmColon, 60, 60, m_hhUnit); setField(2, m_hh, 60, m_mm, "%02u", m_ss, 60, NULL, 60, 60, m_mmUnit); setField(3, m_mm, 60, m_ss, "%02u", m_ms, 1000, m_ssColon, 60, 60, m_ssUnit); setField(4, m_ss, 1000, m_ms, "%03u", NULL, 0, m_dot, 1000, 1000, m_msUnit); } void DurationWidget::destroy() { delete m_fields; //delete m_validator; //TQWidget takes care of this } TQ_INT64 DurationWidget::setValueMilliseconds(TQ_INT64 milliseconds) { unsigned sc = (unsigned)m_fields[4].leftScale; TQ_INT64 secs = milliseconds / sc; TQ_INT64 ms = milliseconds % sc; TQString tmp; tmp.sprintf(m_fields[4].format, ms); m_fields[4].current->setText(tmp); return secs; } TQ_INT64 DurationWidget::setValueSeconds(TQ_INT64 seconds) { unsigned sc = (unsigned)m_fields[3].leftScale; TQ_INT64 mins = seconds / sc; TQ_INT64 s = seconds % sc; TQString tmp; tmp.sprintf(m_fields[3].format, s); m_fields[3].current->setText(tmp); return mins; } TQ_INT64 DurationWidget::setValueMinutes(TQ_INT64 mins) { unsigned sc = (unsigned)m_fields[2].leftScale; TQ_INT64 hours = mins / sc; TQ_INT64 m = mins % sc; TQString tmp; tmp.sprintf(m_fields[2].format, m); m_fields[2].current->setText(tmp); return hours; } // NOTE: Input is minutes and also returns minutes! TQ_INT64 DurationWidget::setValueHours(TQ_INT64 mins) { if (m_fields[1].current->isHidden()) return mins; unsigned sc = (unsigned)m_fields[1].rightScale; TQ_INT64 hours = (TQ_INT64)(mins / sc); TQ_INT64 m = mins - (TQ_INT64)(hours * sc); //kdDebug()< hours="< days="< 0: "<isHidden() && m_fields[i].scale > 0 && m_fields[i].scale <= m_fields[i].fullScale) { double v = m_fields[i].current->text().toDouble(); v = v * m_fields[i].scale / m_fields[i].fullScale;; d.addMilliseconds((TQ_INT64)(v*(1000*60*60*24))); } ++i; if (!m_fields[i].current->isHidden() && m_fields[i].scale > 0 && m_fields[i].scale <= m_fields[i].fullScale) { double v = m_fields[i].current->text().toDouble(); v = v * m_fields[i].scale / m_fields[i].fullScale;; d.addMilliseconds((TQ_INT64)(v*(1000*60*60))); } ++i; if (!m_fields[i].current->isHidden() && m_fields[i].scale > 0 && m_fields[i].scale <= m_fields[i].fullScale) { double v = m_fields[i].current->text().toDouble(); v = v * m_fields[i].scale / m_fields[i].fullScale;; d.addMilliseconds((TQ_INT64)(v*(1000*60))); } ++i; if (!m_fields[i].current->isHidden() && m_fields[i].scale > 0 && m_fields[i].scale <= m_fields[i].fullScale) { double v = m_fields[i].current->text().toDouble(); v = v * m_fields[i].scale / m_fields[i].fullScale;; d.addMilliseconds((TQ_INT64)(v*(1000))); } ++i; if (!m_fields[i].current->isHidden()) { TQ_INT64 v = m_fields[i].current->text().toUInt(); d.addMilliseconds(v); } return d; } void DurationWidget::dddLostFocus() { handleLostFocus(0); emit valueChanged(); } void DurationWidget::hhLostFocus( ) { handleLostFocus(1); emit valueChanged(); } void DurationWidget::mmLostFocus() { handleLostFocus(2); emit valueChanged(); } void DurationWidget::ssLostFocus() { handleLostFocus(3); emit valueChanged(); } void DurationWidget::msLostFocus() { handleLostFocus(4); emit valueChanged(); } void DurationWidget::handleLostFocus( int field) { // Get our own info, and that of our left and right neighbours. TQLineEdit *left = m_fields[field].left; double leftScale = m_fields[field].leftScale; const char *leftFormat = left ? m_fields[field - 1].format : NULL; TQLineEdit *current = m_fields[field].current; const char *currentFormat = m_fields[field].format; TQLineEdit *right = m_fields[field].right; double rightScale = m_fields[field].rightScale; const char *rightFormat = right ? m_fields[field + 1].format : NULL; // avoid possible crash if (leftScale == 0) leftScale = 1; // Get the text and start processing... TQString newValue(current->text()); double v = TDEGlobal::locale()->readNumber(newValue); unsigned currentValue = 0; TQString tmp; //kdDebug()<formatNumber(v, 19), 0); //kdDebug()<