diff --git a/src/libs/kernel/kptduration.cpp b/src/libs/kernel/kptduration.cpp index f8a742f5..0b3e675b 100644 --- a/src/libs/kernel/kptduration.cpp +++ b/src/libs/kernel/kptduration.cpp @@ -1,338 +1,346 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas Zander zander@kde.org Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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; either version 2 of the License, or (at your option) any later version. 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. */ // clazy:excludeall=qstring-arg #include "kptduration.h" #include "kptdatetime.h" #include "kptdebug.h" #include #include #include #include #include namespace KPlato { // Set the value of Duration::zeroDuration to zero. const Duration Duration::zeroDuration( 0, 0, 0 ); Duration::Duration() { m_ms = 0; } Duration::Duration( double value, Duration::Unit unit ) { if (unit == Unit_ms) m_ms = (qint64)value; else if (unit == Unit_s) m_ms = (qint64)(value * 1000); else if (unit == Unit_m) m_ms = (qint64)(value * ( 1000 * 60 )); else if (unit == Unit_h) m_ms = (qint64)(value * ( 1000 * 60 * 60 )); else if (unit == Unit_d) m_ms = (qint64)(value * ( 1000 * 60 * 60 * 24 )); else if (unit == Unit_w) m_ms = (qint64)(value * ( 1000 * 60 * 60 * 24 * 7 )); else if (unit == Unit_M) m_ms = (qint64)(value * (qint64)( 1000 * 60 * 60 ) * ( 24 * 30 )); else if (unit == Unit_Y) m_ms = (qint64)(value * (qint64)( 1000 * 60 * 60 ) * ( 24 * 365 )); } Duration::Duration(unsigned d, unsigned h, unsigned m, unsigned s, unsigned ms) { m_ms = ms; m_ms += static_cast(s) * 1000; // cast to avoid potential overflow problem m_ms += static_cast(m) * 60 * 1000; m_ms += static_cast(h) * 60 * 60 * 1000; m_ms += static_cast(d) * 24 * 60 * 60 * 1000; } Duration::Duration(const qint64 value, Duration::Unit unit) { if (unit == Unit_ms) m_ms = value; else if (unit == Unit_s) m_ms = (qint64)(value * 1000); else if (unit == Unit_m) m_ms = (qint64)(value * ( 1000 * 60 )); else if (unit == Unit_h) m_ms = (qint64)(value * ( 1000 * 60 * 60 )); else if (unit == Unit_d) m_ms = (qint64)(value * ( 1000 * 60 * 60 * 24 )); else if (unit == Unit_w) m_ms = (qint64)(value * ( 1000 * 60 * 60 * 24 * 7 )); else if (unit == Unit_M) m_ms = (qint64)(value * (qint64)( 1000 * 60 * 60 ) * ( 24 * 30 )); else if (unit == Unit_Y) m_ms = (qint64)(value * (qint64)( 1000 * 60 * 60 ) * ( 24 * 365 )); else errorPlan<<"Unknown unit: "<toString(); m_ms = 0; return; } m_ms = tmp; } void Duration::subtract(KPlato::Duration delta) { if (m_ms < delta.m_ms) { debugPlan<<"Underflow"<toString(); m_ms = 0; return; } m_ms -= delta.m_ms; } Duration Duration::operator*(int value) const { Duration dur(*this); if (value < 0) { debugPlan<<"Underflow"<toString(); } else { dur.m_ms = m_ms * value; //FIXME } return dur; } Duration Duration::operator/(int value) const { Duration dur(*this); if (value <= 0) { debugPlan<<"Underflow"<toString(); } else { dur.m_ms = m_ms / value; //FIXME } return dur; } Duration Duration::operator*(const double value) const { Duration dur(*this); dur.m_ms = qAbs(m_ms * (qint64)value); return dur; } Duration Duration::operator*(const Duration value) const { Duration dur(*this); dur.m_ms = m_ms * value.m_ms; return dur; } double Duration::operator/(KPlato::Duration d) const { if (d == zeroDuration) { debugPlan<<"Divide by zero:"<toString(); return 0.0; } return (double)(m_ms) / (double)(d.m_ms); } QString Duration::format(Unit unit, int pres) const { /* FIXME if necessary return i18nc( "", "%1%2", QLocale().toString(toDouble(unit), 'f', pres), unitToString(unit) );*/ return QLocale().toString( toDouble( unit ), 'f', pres ) + unitToString( unit ); } QString Duration::toString(Format format) const { qint64 ms; double days; unsigned hours; unsigned minutes; unsigned seconds; QString result; switch (format) { case Format_Hour: ms = m_ms; hours = ms / (1000 * 60 * 60); ms -= (qint64)hours * (1000 * 60 * 60); minutes = ms / (1000 * 60); result = QStringLiteral("%1h%2m").arg(hours).arg(minutes); break; case Format_Day: days = m_ms / (1000 * 60 * 60 * 24.0); result = QStringLiteral("%1d").arg(QString::number(days, 'f', 4)); break; case Format_DayTime: ms = m_ms; days = m_ms / (1000 * 60 * 60 * 24); ms -= (qint64)days * (1000 * 60 * 60 * 24); hours = ms / (1000 * 60 * 60); ms -= (qint64)hours * (1000 * 60 * 60); minutes = ms / (1000 * 60); ms -= minutes * (1000 * 60); seconds = ms / (1000); ms -= seconds * (1000); result.sprintf("%u %02u:%02u:%02u.%u", (unsigned)days, hours, minutes, seconds, (unsigned)ms); break; case Format_HourFraction: result = QLocale().toString(toDouble(Unit_h), 'f', 2); break; // i18n case Format_i18nHour: ms = m_ms; hours = ms / (1000 * 60 * 60); ms -= (qint64)hours * (1000 * 60 * 60); minutes = ms / (1000 * 60); - result = i18nc("h:m", "%1h:%2m", hours, minutes); + if (minutes > 0) { + result = i18nc("h:m", "%1h:%2m", hours, minutes); + } else { + result = i18nc("h:m", "%1h", hours); + } break; case Format_i18nDay: result = KFormat().formatSpelloutDuration( m_ms ); break; case Format_i18nWeek: result = this->format( Unit_w, 2 ); break; case Format_i18nMonth: result = this->format( Unit_M, 2 ); break; case Format_i18nYear: result = this->format( Unit_Y, 2 ); break; case Format_i18nDayTime: ms = m_ms; days = m_ms / (1000 * 60 * 60 * 24); ms -= (qint64)days * (1000 * 60 * 60 * 24); hours = ms / (1000 * 60 * 60); ms -= (qint64)hours * (1000 * 60 * 60); minutes = ms / (1000 * 60); ms -= minutes * (1000 * 60); seconds = ms / (1000); ms -= seconds * (1000); if (days == 0) { result = toString(Format_i18nHour); - } else { + } else if (minutes > 0) { result = i18nc("d h:m", "%1d %2h:%3m", days, hours, minutes); + } else if (hours > 0 ) { + result = i18nc("d h:m", "%1d %2h", days, hours); + } else { + result = i18nc("d h:m", "%1d", days); } break; case Format_i18nHourFraction: result = QLocale().toString(toDouble(Unit_h), 'f', 2); break; default: qFatal("Unknown format"); break; } return result; } Duration Duration::fromString(const QString &s, Format format, bool *ok) { if (ok) *ok = false; QRegExp matcher; Duration tmp; switch (format) { case Format_Hour: { matcher.setPattern(QStringLiteral("^(\\d*)h(\\d*)m$") ); int pos = matcher.indexIn(s); if (pos > -1) { tmp.addHours(matcher.cap(1).toUInt()); tmp.addMinutes(matcher.cap(2).toUInt()); if (ok) *ok = true; } break; } case Format_DayTime: { matcher.setPattern(QStringLiteral("^(\\d*) (\\d*):(\\d*):(\\d*)\\.(\\d*)$") ); int pos = matcher.indexIn(s); if (pos > -1) { tmp.addDays(matcher.cap(1).toUInt()); tmp.addHours(matcher.cap(2).toUInt()); tmp.addMinutes(matcher.cap(3).toUInt()); tmp.addSeconds(matcher.cap(4).toUInt()); tmp.addMilliseconds(matcher.cap(5).toUInt()); if (ok) *ok = true; } break; } case Format_HourFraction: { // should be in double format bool res; double f = QLocale().toDouble(s, &res); if (ok) *ok = res; if (res) { return Duration((qint64)(f)*3600*1000); } break; } default: qFatal("Unknown format"); break; } return tmp; } QStringList Duration::unitList( bool trans ) { QStringList lst; lst << ( trans ? i18nc( "Year. Note: Letter(s) only!", "Y" ) : QStringLiteral("Y") ) << ( trans ? i18nc( "Month. Note: Letter(s) only!", "M" ) : QStringLiteral("M") ) << ( trans ? i18nc( "Week. Note: Letter(s) only!", "w" ) : QStringLiteral("w") ) << ( trans ? i18nc( "Day. Note: Letter(s) only!", "d" ) : QStringLiteral("d") ) << ( trans ? i18nc( "Hour. Note: Letter(s) only!", "h" ) : QStringLiteral("h") ) << ( trans ? i18nc( "Minute. Note: Letter(s) only!", "m" ) : QStringLiteral("m") ) << ( trans ? i18nc( "Second. Note: Letter(s) only!", "s" ) : QStringLiteral("s") ) << ( trans ? i18nc( "Millisecond. Note: Letter(s) only!", "ms" ) : QStringLiteral("ms") ); return lst; } QString Duration::unitToString( Duration::Unit unit, bool trans ) { return unitList( trans ).at( unit ); } Duration::Unit Duration::unitFromString( const QString &u ) { int i = unitList().indexOf( u ); if ( i < 0 ) { errorPlan<<"Illegal unit: "< "<