diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index 9f176d1ee8..6ec0b6f679 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -10,6 +10,8 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
set(TARGET_NAME interface)
project(${TARGET_NAME})
+find_package(Qt5LinguistTools REQUIRED)
+
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
set(FACESHIFT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/faceshift")
@@ -77,6 +79,10 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
# add them to the interface source files
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}")
+set(QM ${TARGET_NAME}_en.qm)
+set(TS ${TARGET_NAME}_en.ts)
+qt5_create_translation(${QM} ${INTERFACE_SRCS} ${QT_UI_FILES} ${TS})
+
if (APPLE)
# configure CMake to use a custom Info.plist
SET_TARGET_PROPERTIES( ${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in )
@@ -105,7 +111,7 @@ if (APPLE)
endif()
# create the executable, make it a bundle on OS X
-add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
+add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
# link in the hifi shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
diff --git a/interface/interface_en.ts b/interface/interface_en.ts
new file mode 100644
index 0000000000..8198d97a8f
--- /dev/null
+++ b/interface/interface_en.ts
@@ -0,0 +1,161 @@
+
+
+
+
+ Application
+
+
+ Export Voxels
+
+
+
+
+ Sparse Voxel Octree Files (*.svo)
+
+
+
+
+ Open Script
+
+
+
+
+ JavaScript Files (*.js)
+
+
+
+
+ ChatWindow
+
+
+
+ Chat
+
+
+
+
+
+ Connecting to XMPP...
+
+
+
+
+
+ online now:
+
+
+
+
+ day
+
+ %n day
+ %n days
+
+
+
+
+ hour
+
+ %n hour
+ %n hours
+
+
+
+
+ minute
+
+ %n minute
+ %n minutes
+
+
+
+ second
+
+ %n second
+ %n seconds
+
+
+
+
+ %1 online now:
+
+
+
+
+ Dialog
+
+
+
+
+
+ Update Required
+
+
+
+
+
+ Download
+
+
+
+
+
+ Skip Version
+
+
+
+
+
+ Close
+
+
+
+
+ Menu
+
+
+ Open .ini config file
+
+
+
+
+
+ Text files (*.ini)
+
+
+
+
+ Save .ini config file
+
+
+
+
+ QObject
+
+
+
+ Import Voxels
+
+
+
+
+ Loading ...
+
+
+
+
+ Place voxels
+
+
+
+
+ <b>Import</b> %1 as voxels
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/interface/src/main.cpp b/interface/src/main.cpp
index 2d30fc06bc..f2c516792b 100644
--- a/interface/src/main.cpp
+++ b/interface/src/main.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
int main(int argc, const char * argv[]) {
@@ -40,6 +41,10 @@ int main(int argc, const char * argv[]) {
{
QSettings::setDefaultFormat(QSettings::IniFormat);
Application app(argc, const_cast(argv), startup_time);
+
+ QTranslator translator;
+ translator.load("interface_en");
+ app.installTranslator(&translator);
qDebug( "Created QT Application.");
exitCode = app.exec();
diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp
index 5770eff31e..4e4b869cda 100644
--- a/interface/src/ui/ChatWindow.cpp
+++ b/interface/src/ui/ChatWindow.cpp
@@ -1,13 +1,24 @@
+//
+// ChatWindow.cpp
+// interface
+//
+// Created by Dimitar Dobrev on 3/6/14.
+// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
+//
+
#include
#include
#include
+#include
#include
#include
#include
+#include
#include "ChatWindow.h"
#include "ui_chatwindow.h"
#include "FlowLayout.h"
+#include "qtimespan.h"
#include
#include
@@ -16,16 +27,17 @@
const QString DEFAULT_SERVER = "chat.highfidelity.io";
const QString DEFAULT_CHAT_ROOM = "public@public-chat.highfidelity.io";
+const int NUM_MESSAGES_TO_TIME_STAMP = 20;
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)");
ChatWindow::ChatWindow() :
QDialog(Application::getInstance()->getGLWidget(), Qt::Tool),
- ui(new Ui::ChatWindow) {
+ ui(new Ui::ChatWindow),
+ numMessagesAfterLastTimeStamp(0) {
ui->setupUi(this);
- FlowLayout* flowLayout = new FlowLayout();
- flowLayout->setContentsMargins(0, 8, 0, 8);
+ FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
ui->usersWidget->setLayout(flowLayout);
ui->messagePlainTextEdit->installEventFilter(this);
@@ -61,8 +73,11 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {
QKeyEvent* keyEvent = static_cast(event);
if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) &&
(keyEvent->modifiers() & Qt::ShiftModifier) == 0) {
- _xmppClient.sendMessage(_chatRoom->jid(), ui->messagePlainTextEdit->document()->toPlainText());
- ui->messagePlainTextEdit->document()->clear();
+ QString message = ui->messagePlainTextEdit->document()->toPlainText();
+ if (!message.trimmed().isEmpty()) {
+ _xmppClient.sendMessage(_chatRoom->jid(), message);
+ ui->messagePlainTextEdit->document()->clear();
+ }
return true;
}
return false;
@@ -72,6 +87,26 @@ QString ChatWindow::getParticipantName(const QString& participant) {
return participant.right(participant.count() - 1 - _chatRoom->jid().count());
}
+void ChatWindow::addTimeStamp() {
+ QTimeSpan timePassed = QDateTime::currentDateTime() - lastMessageStamp;
+ int times[] = { timePassed.daysPart(), timePassed.hoursPart(), timePassed.minutesPart() };
+ QString strings[] = { tr("day", 0, times[0]), tr("hour", 0, times[1]), tr("minute", 0, times[2]) };
+ QString timeString = "";
+ for (int i = 0; i < 3; i++) {
+ if (times[i] > 0) {
+ timeString += strings[i] + " ";
+ }
+ }
+ timeString.chop(1);
+ QLabel* timeLabel = new QLabel(timeString);
+ timeLabel->setStyleSheet("color: palette(shadow);"
+ "background-color: palette(highlight);"
+ "padding: 4px;");
+ timeLabel->setAlignment(Qt::AlignHCenter);
+ ui->messagesFormLayout->addRow(timeLabel);
+ numMessagesAfterLastTimeStamp = 0;
+}
+
void ChatWindow::connected() {
_chatRoom = _xmppMUCManager.addRoom(DEFAULT_CHAT_ROOM);
connect(_chatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged()));
@@ -83,6 +118,17 @@ void ChatWindow::connected() {
ui->usersWidget->show();
ui->messagesScrollArea->show();
ui->messagePlainTextEdit->show();
+
+ QTimer* timer = new QTimer(this);
+ timer->setInterval(10 * 60 * 1000);
+ connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ timer->start();
+}
+
+void ChatWindow::timeout() {
+ if (numMessagesAfterLastTimeStamp >= NUM_MESSAGES_TO_TIME_STAMP) {
+ addTimeStamp();
+ }
}
void ChatWindow::error(QXmppClient::Error error) {
@@ -98,13 +144,12 @@ void ChatWindow::participantsChanged() {
}
foreach (const QString& participant, participants) {
QLabel* userLabel = new QLabel(getParticipantName(participant));
- userLabel->setStyleSheet(
- "background-color: palette(light);"
- "border-radius: 5px;"
- "color: #267077;"
- "padding: 2px;"
- "border: 1px solid palette(shadow);"
- "font-weight: bold");
+ userLabel->setStyleSheet("background-color: palette(light);"
+ "border-radius: 5px;"
+ "color: #267077;"
+ "padding: 2px;"
+ "border: 1px solid palette(shadow);"
+ "font-weight: bold");
ui->usersWidget->layout()->addWidget(userLabel);
}
}
@@ -115,15 +160,25 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
font.setBold(true);
userLabel->setFont(font);
userLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ userLabel->setStyleSheet("padding: 4px;");
QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "\\1"));
messageLabel->setWordWrap(true);
messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageLabel->setOpenExternalLinks(true);
+ messageLabel->setStyleSheet("padding: 4px;");
ui->messagesFormLayout->addRow(userLabel, messageLabel);
ui->messagesFormLayout->parentWidget()->updateGeometry();
Application::processEvents();
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(verticalScrollBar->maximum());
+
+ ++numMessagesAfterLastTimeStamp;
+ if (message.stamp().isValid()) {
+ lastMessageStamp = message.stamp().toLocalTime();
+ }
+ else {
+ lastMessageStamp = QDateTime::currentDateTime();
+ }
}
diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h
index c1963b5342..afa1947268 100644
--- a/interface/src/ui/ChatWindow.h
+++ b/interface/src/ui/ChatWindow.h
@@ -1,7 +1,17 @@
+//
+// ChatWindow.h
+// interface
+//
+// Created by Dimitar Dobrev on 3/6/14.
+// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
+//
+
#ifndef __interface__ChatWindow__
#define __interface__ChatWindow__
#include
+#include
+#include
#include
@@ -23,15 +33,19 @@ protected:
bool eventFilter(QObject* sender, QEvent* event);
private:
+ QString getParticipantName(const QString& participant);
+ void addTimeStamp();
+
Ui::ChatWindow* ui;
QXmppClient _xmppClient;
QXmppMucManager _xmppMUCManager;
QXmppMucRoom* _chatRoom;
-
- QString getParticipantName(const QString& participant);
+ int numMessagesAfterLastTimeStamp;
+ QDateTime lastMessageStamp;
private slots:
void connected();
+ void timeout();
void error(QXmppClient::Error error);
void participantsChanged();
void messageReceived(const QXmppMessage& message);
diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui
index 554b42833e..1723e72665 100644
--- a/interface/ui/chatWindow.ui
+++ b/interface/ui/chatWindow.ui
@@ -54,7 +54,7 @@
- font-weight: bold; color: palette(shadow)
+ font-weight: bold; color: palette(shadow); margin-bottom: 4px; online now:
@@ -66,6 +66,12 @@
+
+ margin-top: 12px;
+
+
+ Qt::ScrollBarAlwaysOff
+ true
@@ -74,16 +80,19 @@
00
- 382
- 356
+ 358
+ 328
+
+ margin-top: 0px;
+ QFormLayout::AllNonFixedFieldsGrow
- 4
+ 04
@@ -112,6 +121,9 @@
0
+
+ Qt::ScrollBarAlwaysOff
+
diff --git a/libraries/shared/src/qtimespan.cpp b/libraries/shared/src/qtimespan.cpp
new file mode 100644
index 0000000000..2ddddb30f3
--- /dev/null
+++ b/libraries/shared/src/qtimespan.cpp
@@ -0,0 +1,2290 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+//#include "private/qdatetime_p.h"
+#include
+#include
+#include
+#include "qdatastream.h"
+#include "qlocale.h"
+#include "qtimespan.h"
+#include "qdebug.h"
+#include "qcoreapplication.h"
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+#include
+#endif
+#ifndef Q_WS_WIN
+#include
+#endif
+
+#include
+#if defined(Q_OS_WINCE)
+#include "qfunctions_wince.h"
+#endif
+
+#if defined(Q_WS_MAC)
+#include
+#endif
+
+#if defined(Q_OS_SYMBIAN)
+#include
+#endif
+
+
+
+/*!
+ \class QTimeSpan
+ \brief The QTimeSpan represents a span of time
+ \since 4.8
+
+ QTimeSpan represents a span of time, which is optionally in reference to a specific
+ point in time. A QTimeSpan behaves slightly different if it has a reference date or time
+ or not.
+
+ \section1 Constructing a QTimeSpan
+ A QTimeSpan can be created by initializing it directly with a length and optionally with
+ a reference (start) date, or by substracting two QDate or QDateTime values. By substracting
+ QDate or QDateTime values, you create a QTimeSpan with the QDate or QDateTime on the right
+ hand side of the - operator as the reference date.
+
+ \code
+ //Creates a QTimeSpan representing the time from October 10, 1975 to now
+ QDate birthDay(1975, 10, 10);
+ QTimeSpan age = QDate::currentDate() - birthDay;
+ \endcode
+
+ QTimeSpan defines a series of constants that can be used for initializing a QTimeSpan.
+ Second, Minute, Hour, Day and Week are all QTimeSpan instances with the corresponding
+ length and no reference date. You can use those to create new instances. See the
+ section on Date arithmatic below.
+
+ \code
+ //Creates a QTimeSpan representing 2 days, 4 hours and 31 minutes.
+ QTimeSpan span(2 * QTimeSpan::Day + 4 * QTimeSpan::Hour + 31 * QTimeSpan::Minute);
+ \endcode
+
+ Finally, a QTimeSpan can be constructed by using one of the static constructors
+ fromString or fromTimeUnit.
+
+ \section1 Date arithmatic
+ A negative QTimeSpan means that the reference date lies before the referenced date. Call
+ normalize() to ensure that the reference date is smaller or equal than the referenced date.
+
+ Basic arithmatic can be done with QTimeSpan. QTimeSpans can be added up or substracted, or
+ be multiplied by a scalar factor. For this, the usual operators are implemented. The union
+ of QTimeSpans will yield the minimal QTimeSpan that covers both the original QTimeSpans,
+ while the intersection will yield the overlap between them (or an empty one if there is no
+ overlap). Please refer to the method documentation for details on what happens to a
+ reference date when using these methods.
+
+ QTimeSpans can also be added to or substracted from a QDate, QTime or QDateTime. This will yield
+ a new QDate, QTime or QDateTime moved by the value of the QTimeSpan. Note that the QTimeSpan must
+ be the right-hand argument of the operator. You can not add a QDate to a QTimeSpan, but you
+ can do the reverse.
+
+ \code
+ QTimeSpan span(QTimeSpan::Hour * 5 + 45 * QTimeSpan::Minute);
+ QDateTime t1 = QDateTime::currentDateTime();
+ QDateTime t2 = t1 + span; // t2 is now the date time 5 hours and 45 minutes in the future.
+ \endcode
+
+ \section1 Accessing the length of a QTimeSpan
+ There are two sets of methods that return the length of a QTimeSpan. The to* methods such
+ as toSeconds and toMinutes return the total time in the requested unit. That may be a
+ fractional number.
+
+ \code
+ QTimeSpan span = QTimeSpan::Hour * 6;
+ qreal days = span.toDays(); //yields 0.25
+ \endcode
+
+ On the other hand, you may be interested in a number of units at the same time. If you want
+ to know the number of days, hours and minutes in a QTimeSpan, you can use the to*Part
+ methods such as toDayPart and toHourPart. These functions take a QTimeSpan::TimeSpanFormat
+ argument to indicate the units you want to use for the presentation of the QTimeSpan.
+ This is used to calculate the number of the requested time units. You can also use the
+ parts method directly, passing pointers to ints for the units you are interested in and 0
+ for the other units.
+
+ \section1 Using months and years
+ QTimeSpan can be used to describe any length of time, ranging from milliseconds to decades and
+ beyond (up to the maximum value of a qint64 milliseconds; enough for any application not
+ dealing with geological or astronomical time scales.) It is natural to use units like months
+ and years when dealing with longer time periods, such as the age of people. The problem with
+ these units is that unlike the time units for a week or shorter, the length of a month or a
+ year is not fixed. It it dependent on the reference date. The time period '1 month' has a
+ different meaning when we are speaking of februari or januari.
+
+ QTimeSpan can only use the month and year time units if a valid reference date has been
+ set. Without a valid reference date, month and year as time units are meaningless and their
+ use will result in an assert. The largest unit of time that can be expressed without a reference
+ date is a week. The time period of one month is understood to mean the period
+ from a day and time one month to the same date and time in the next. If the next month does
+ not have that date and time, one month will be taken to mean the period to the end of that
+ month.
+
+ \example The time from januari 2, 12 PM to februari 2, 12 PM will be understood as exactly one month.
+ \example The time from januari 30, 2 PM to march 1, 00:00:00.000 will also be one month, because
+ februari does not have 30 days but 28 or 29 depending on the year.
+ \example The time from januari 30, 2 PM to march 30, 2 PM will be 2 months.
+
+ The same goes for years.
+
+ QTimeSpan stores the length of time intervals as a 64 bits integer representing milliseconds.
+ That means that arithmatic with time periods set as months or years may not always yield what you
+ expect. A time period set as the year describing the whole of 2007 that you multiply by two or
+ add to itself, will not end up having a length of two years, but of 1 year, 11 months and 30
+ days, as 2008 is one day longer than 2007. When months and years are used, they are
+ converted to the exact time span they describe in reference to the reference date set for
+ the QTimeSpan. With another reference date, or when negated, that time span may or may not
+ describe the same number of years and months.
+*/
+
+QT_BEGIN_NAMESPACE
+
+const QTimeSpan QTimeSpan::Second = QTimeSpan(qint64(1000));
+const QTimeSpan QTimeSpan::Minute = QTimeSpan(qint64(1000 * 60));
+const QTimeSpan QTimeSpan::Hour = QTimeSpan(qint64(1000 * 60 * 60));
+const QTimeSpan QTimeSpan::Day = QTimeSpan(qint64(1000 * 60 * 60 * 24));
+const QTimeSpan QTimeSpan::Week = QTimeSpan(qint64(1000 * 60 * 60 * 24 * 7));
+
+class QTimeSpanPrivate : public QSharedData {
+public:
+ qint64 interval;
+ QDateTime reference;
+ static const int s_daysPerMonth[12];
+
+ void addUnit(QTimeSpan* self, Qt::TimeSpanUnit unit, qreal value)
+ {
+ if (unit >= Qt::Months) {
+ QTimeSpan tempSpan(self->referencedDate());
+ tempSpan.setFromTimeUnit(unit, value);
+ interval += tempSpan.toMSecs();
+ } else {
+ switch (unit) {
+ case Qt::Weeks:
+ interval += value * 1000LL * 60LL * 60LL * 24LL * 7LL;
+ break;
+ case Qt::Days:
+ interval += value * 1000LL * 60LL * 60LL * 24LL;
+ break;
+ case Qt::Hours:
+ interval += value * 1000LL * 60LL * 60LL ;
+ break;
+ case Qt::Minutes:
+ interval += value * 1000LL * 60LL;
+ break;
+ case Qt::Seconds:
+ interval += value * 1000LL;
+ break;
+ case Qt::Milliseconds:
+ interval += value;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ class TimePartHash: public QHash
+ {
+ public:
+ TimePartHash(Qt::TimeSpanFormat format)
+ {
+ for (int i(Qt::Milliseconds); i <= Qt::Years; i *= 2) {
+ Qt::TimeSpanUnit u = static_cast(i);
+ if (format.testFlag(u)) {
+ int* newValue = new int;
+ *newValue = 0;
+ insert(u, newValue); //perhaps we can optimize this not to new each int individually?
+
+ } else {
+ insert(u, 0);
+ }
+ }
+ }
+
+ ~TimePartHash()
+ {
+ qDeleteAll(*this);
+ }
+
+ inline bool fill(const QTimeSpan& span)
+ {
+ bool result = span.parts(value(Qt::Milliseconds),
+ value(Qt::Seconds),
+ value(Qt::Minutes),
+ value(Qt::Hours),
+ value(Qt::Days),
+ value(Qt::Weeks),
+ value(Qt::Months),
+ value(Qt::Years));
+ return result;
+ }
+
+ inline void addUnit(const Qt::TimeSpanUnit unit)
+ {
+ if (value(unit) != 0)
+ return;
+
+ int* newValue = new int;
+ *newValue = 0;
+ insert(unit, newValue);
+ }
+
+ };
+
+ //returns a string representation of time in a single time unit
+ QString unitString(Qt::TimeSpanUnit unit, int num) const
+ {
+ switch (unit) {
+ case::Qt::Milliseconds:
+ return qApp->translate("QTimeSpanPrivate", "%n millisecond(s)", 0, num);
+ case::Qt::Seconds:
+ return qApp->translate("QTimeSpanPrivate", "%n second(s)", 0, num);
+ case::Qt::Minutes:
+ return qApp->translate("QTimeSpanPrivate", "%n minute(s)", 0, num);
+ case::Qt::Hours:
+ return qApp->translate("QTimeSpanPrivate", "%n hour(s)", 0, num);
+ case::Qt::Days:
+ return qApp->translate("QTimeSpanPrivate", "%n day(s)", 0, num);
+ case::Qt::Weeks:
+ return qApp->translate("QTimeSpanPrivate", "%n week(s)", 0, num);
+ case::Qt::Months:
+ return qApp->translate("QTimeSpanPrivate", "%n month(s)", 0, num);
+ case::Qt::Years:
+ return qApp->translate("QTimeSpanPrivate", "%n year(s)", 0, num);
+ default:
+ return QString();
+ }
+ }
+
+#ifndef QT_NO_DATESTRING
+ struct TimeFormatToken
+ {
+ Qt::TimeSpanUnit type; //Qt::NoUnit is used for string literal types
+ int length; //number of characters to use
+ QString string; //only used for string literals
+ };
+
+ QList parseFormatString(const QString& formatString, Qt::TimeSpanFormat &format) const
+ {
+ QHash tokenHash;
+ tokenHash.insert(QChar('y'), Qt::Years);
+ tokenHash.insert(QChar('M'), Qt::Months);
+ tokenHash.insert(QChar('w'), Qt::Weeks);
+ tokenHash.insert(QChar('d'), Qt::Days);
+ tokenHash.insert(QChar('h'), Qt::Hours);
+ tokenHash.insert(QChar('m'), Qt::Minutes);
+ tokenHash.insert(QChar('s'), Qt::Seconds);
+ tokenHash.insert(QChar('z'), Qt::Milliseconds);
+
+
+ QList tokenList;
+ format = Qt::NoUnit;
+ int pos(0);
+ int length(formatString.length());
+ bool inLiteral(false);
+ while (pos < length) {
+ const QChar currentChar(formatString[pos]);
+ if (inLiteral) {
+ if (currentChar == QLatin1Char('\'')) {
+ inLiteral = false; //exit literal string mode
+ if ((pos+1)interval = 0;
+}
+
+/*!
+ \brief Constructor
+
+ Constructs QTimeSpan of size msecs milliseconds. The reference date will
+ be invalid.
+*/
+QTimeSpan::QTimeSpan(qint64 msecs)
+ : d(new QTimeSpanPrivate)
+{
+ d->interval = msecs;
+}
+
+/*!
+ \brief Copy Constructor
+*/
+QTimeSpan::QTimeSpan(const QTimeSpan& other):
+ d(other.d)
+{
+}
+
+/*!
+ \brief Constructor
+
+ Constructs QTimeSpan of size msecs milliseconds from the given reference date
+ and time.
+*/
+QTimeSpan::QTimeSpan(const QDateTime &reference, qint64 msecs)
+ : d(new QTimeSpanPrivate)
+{
+ d->interval = msecs;
+ d->reference = reference;
+}
+
+/*!
+ \brief Constructor
+
+ Constructs QTimeSpan of size msecs milliseconds from the given reference date.
+ The reference time will be 0:00:00.000
+*/
+QTimeSpan::QTimeSpan(const QDate &reference, quint64 msecs)
+ : d(new QTimeSpanPrivate)
+{
+ d->interval = msecs;
+ d->reference = QDateTime(reference);
+}
+
+/*!
+ \brief Constructor
+
+ Constructs QTimeSpan of size msecs milliseconds from the given reference time.
+ The reference date will be today's date.
+*/
+QTimeSpan::QTimeSpan(const QTime &reference, quint64 msecs)
+ : d(new QTimeSpanPrivate)
+{
+ d->interval = msecs;
+ QDateTime todayReference(QDate::currentDate());
+ todayReference.setTime(reference);
+ d->reference = todayReference;
+}
+
+/*!
+ \brief Constructor
+
+ Constructs a QTimeSpan of the same length as other from the given reference date time.
+*/
+QTimeSpan::QTimeSpan(const QDateTime& reference, const QTimeSpan& other)
+ : d(new QTimeSpanPrivate)
+{
+ d->reference = reference;
+ d->interval = other.d->interval;
+}
+
+/*!
+ \brief Constructor
+
+ Constructs a QTimeSpan of the same length as other from the given reference date.
+ The reference time will be 00:00:00.000
+*/
+QTimeSpan::QTimeSpan(const QDate& reference, const QTimeSpan& other)
+ : d(new QTimeSpanPrivate)
+{
+ d->reference = QDateTime(reference);
+ d->interval = other.d->interval;
+}
+
+/*!
+ \brief Constructor
+
+ Constructs a QTimeSpan of the same length as other from the given reference time.
+ The reference date will be today's date.
+*/
+QTimeSpan::QTimeSpan(const QTime& reference, const QTimeSpan& other)
+ : d(new QTimeSpanPrivate)
+{
+ QDateTime todayReference(QDate::currentDate());
+ todayReference.setTime(reference);
+ d->reference = todayReference;
+ d->interval = other.d->interval;
+}
+
+
+/*!
+ \brief Destructor
+*/
+QTimeSpan::~QTimeSpan()
+{
+}
+
+/*!
+ \returns true if the time span is 0; that is, if no time is spanned by
+ this instance. There may or may not be a valid reference date.
+
+ \sa isNull hasValidReference
+*/
+bool QTimeSpan::isEmpty() const
+{
+ return d->interval == 0;
+}
+
+/*!
+ \returns true if the time span is 0; that is, if no time is spanned by
+ this instance and there is no valid reference date.
+
+ \sa isEmpty
+*/
+bool QTimeSpan::isNull() const
+{
+ return isEmpty() && (!hasValidReference());
+}
+
+/*!
+ \brief Assignment operator
+*/
+QTimeSpan& QTimeSpan::operator=(const QTimeSpan& other) {
+ if (&other == this)
+ return *this;
+
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \returns a new QTimeSpan instance initialized to the indicated number of
+ time units. The default reference date is invalid.
+
+ \note that you can only construct a valid QTimeSpan using the Months or Years
+ time units if you supply a valid reference date.
+
+ \sa setFromTimeUnit
+*/
+QTimeSpan QTimeSpan::fromTimeUnit(Qt::TimeSpanUnit unit, qreal interval, const QDateTime& reference )
+{
+ switch (unit){ //note: fall through is intentional!
+ case Qt::Weeks:
+ interval *= 7.0;
+ case Qt::Days:
+ interval *= 24.0;
+ case Qt::Hours:
+ interval *= 60.0;
+ case Qt::Minutes:
+ interval *= 60.0;
+ case Qt::Seconds:
+ interval *= 1000.0;
+ case Qt::Milliseconds:
+ break;
+ default:
+ if (reference.isValid()) {
+ QTimeSpan result(reference);
+ result.setFromTimeUnit(unit, interval);
+ return result;
+ }
+ Q_ASSERT_X(false, "static constructor", "Can not construct QTimeSpan from Month or Year TimeSpanUnit without a valid reference date.");
+ return QTimeSpan();
+ }
+
+ return QTimeSpan(reference, qint64(interval));
+}
+
+/*!
+ \returns the number of the requested units indicated by unit when formatted
+ as format.
+
+ \sa parts()
+*/
+int QTimeSpan::part(Qt::TimeSpanUnit unit, Qt::TimeSpanFormat format) const
+{
+ if (!format.testFlag(unit))
+ return 0;
+
+ if (!hasValidReference()) {
+ if (unit == Qt::Months || unit == Qt::Years) {
+ Q_ASSERT_X(false, "part", "Can not calculate Month or Year part without a reference date");
+ }
+ if (format.testFlag(Qt::Months) || format.testFlag(Qt::Years)) {
+ qWarning() << "Unsetting Qt::Months and Qt::Years flags from format. Not supported without a reference date";
+ //should this assert instead?
+ format&= (Qt::AllUnits ^ (Qt::Months | Qt::Years));
+ }
+ }
+
+ //build up hash with pointers to ints for the units that are set in format, and 0's for those that are not.
+ QTimeSpanPrivate::TimePartHash partsHash(format);
+ bool result = partsHash.fill(*this);
+
+ if (!result) {
+ //what to do? Assert perhaps?
+ qWarning() << "Result is invalid!";
+ return 0;
+ }
+
+ int val = *(partsHash.value(unit));
+ return val;
+}
+
+#define CHECK_INT_LIMIT(interval, unitFactor) if (interval >= (qint64(unitFactor) * qint64(std::numeric_limits::max()) ) ) {qWarning() << "out of range" << unitFactor; return false;}
+
+/*!
+ Retreives a breakup of the length of the QTimeSpan in different time units.
+
+ While part() allows you to retreive the value of a single unit for a specific
+ representation of time, this method allows you to retreive all these values
+ with a single call. The units that you want to use in the representation of the
+ time span is defined implicitly by the pointers you pass. Passing a valid pointer
+ for a time unit will include that unit in the representation, while passing 0
+ for that pointer will exclude it.
+
+ The passed integer pointers will be set to the correct value so that together
+ they represent the whole time span. This function will then return true.
+ If it is impossible to represent the whole time span in the requested units,
+ this function returns false.
+
+ The fractionalSmallestUnit qreal pointer can optionally be passed in to
+ retreive the value for the smallest time unit passed in as a fractional number.
+ For instance, if your time span contains 4 minutes and 30 seconds, but the
+ smallest time unit you pass in an integer pointer for is the minute unit, then
+ the minute integer will be set to 4 and the fractionalSmallestUnit will be set
+ to 4.5.
+
+ A negative QTimeSpan will result in all the parts of the representation to be
+ negative, while a positive QTimeSpan will result in an all positive
+ representation.
+
+ \note Months and years are only valid as units for time spans that have a valid
+ reference date. Requesting the number of months or years for time spans without
+ a valid reference date will return false.
+
+ If this function returns false, the value of the passed in pointers is undefined.
+
+ \sa part()
+*/
+bool QTimeSpan::parts(int *msecondsPtr,
+ int *secondsPtr,
+ int *minutesPtr,
+ int *hoursPtr,
+ int *daysPtr,
+ int *weeksPtr,
+ int *monthsPtr,
+ int *yearsPtr,
+ qreal *fractionalSmallestUnit) const
+{
+ /* \todo We should probably cache the results of this operation. However, that requires keeping a dirty flag
+ in the private data store, or a copy of the reference date, interval and last used parts. Is that worth it?
+ */
+
+ // Has the user asked for a fractional component? If yes, find which unit it corresponds to.
+ Qt::TimeSpanUnit smallestUnit = Qt::NoUnit;
+ if (fractionalSmallestUnit)
+ {
+ if (yearsPtr)
+ smallestUnit = Qt::Years;
+ if (monthsPtr)
+ smallestUnit = Qt::Months;
+ if (weeksPtr)
+ smallestUnit = Qt::Weeks;
+ if (daysPtr)
+ smallestUnit = Qt::Days;
+ if (hoursPtr)
+ smallestUnit = Qt::Hours;
+ if (minutesPtr)
+ smallestUnit = Qt::Minutes;
+ if (secondsPtr)
+ smallestUnit = Qt::Seconds;
+ if (msecondsPtr)
+ smallestUnit = Qt::Milliseconds;
+ }
+
+ QTimeSpan ts(*this);
+ if (yearsPtr || monthsPtr) { //deal with months and years
+ //we can not deal with months or years if there is no valid reference date
+ if (!hasValidReference()) {
+ qWarning() << "Can not request month or year parts of a QTimeSpan without a valid reference date.";
+ return false;
+ }
+
+ int* _years = yearsPtr;
+ if (!yearsPtr)
+ _years = new int;
+
+ *_years = 0;
+ QDate startDate = ts.startDate().date();
+ QDate endDate = ts.endDate().date();
+ *_years = endDate.year() - startDate.year();
+ if (endDate.month() < startDate.month()) {
+ (*_years)--;
+ } else if (endDate.month() == startDate.month()) {
+ if (endDate.day() < startDate.day()) {
+ (*_years)--;
+ }
+ }
+
+ /** \todo Handle fractional years component */
+
+ int* _months = monthsPtr;
+ if (!monthsPtr)
+ _months = new int;
+
+ *_months = endDate.month() - startDate.month();
+ if (*_months < 0)
+ (*_months) += 12;
+ if (endDate.day() < startDate.day()) {
+ (*_months)--;
+ }
+ int totalMonths = (*_months);
+ if (!yearsPtr)
+ totalMonths += (*_years) * 12;
+
+ QDate newStartDate(startDate);
+ newStartDate = newStartDate.addYears(*_years);
+ newStartDate = newStartDate.addMonths(*_months);
+ //qDebug() << "working with new start date" << newStartDate << "and end date" << endDate;
+ ts = QDateTime(endDate, ts.endDate().time()) - QDateTime(newStartDate, ts.startDate().time());
+ *_months = totalMonths;
+
+ /** \todo Handle fractional months component */
+
+ //clean up temporary variables on the heap
+ if (!monthsPtr)
+ delete _months;
+ if (!yearsPtr)
+ delete _years;
+ }
+
+ //from here on, we use ts as the time span!
+ qint64 intervalLeft = ts.toMSecs();
+ qint64 unitFactor;
+ //qDebug() << "intervalLeft" << intervalLeft;
+ if (weeksPtr) {
+ unitFactor = (7 * 24 * 60 * 60 * 1000);
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *weeksPtr = intervalLeft / unitFactor;
+ if (smallestUnit == Qt::Weeks)
+ {
+ QTimeSpan leftOverTime(referencedDate(), -intervalLeft);
+ leftOverTime.normalize();
+ *fractionalSmallestUnit = leftOverTime.toTimeUnit(smallestUnit);
+ }
+
+ if (*weeksPtr != 0) {
+ intervalLeft = intervalLeft % unitFactor;
+ }
+ }
+
+ if (daysPtr) {
+ unitFactor = (24 * 60 * 60 * 1000);
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *daysPtr = intervalLeft / unitFactor;
+ if (smallestUnit == Qt::Days)
+ {
+ QTimeSpan leftOverTime(referencedDate(), -intervalLeft);
+ leftOverTime.normalize();
+ *fractionalSmallestUnit = leftOverTime.toTimeUnit(smallestUnit);
+ }
+
+ if (*daysPtr != 0 ) {
+ intervalLeft = intervalLeft % unitFactor;
+ }
+ }
+
+ if (hoursPtr) {
+ unitFactor = (60 * 60 * 1000);
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *hoursPtr = intervalLeft / unitFactor;
+ if (smallestUnit == Qt::Hours)
+ {
+ QTimeSpan leftOverTime(referencedDate(), -intervalLeft);
+ leftOverTime.normalize();
+ *fractionalSmallestUnit = leftOverTime.toTimeUnit(smallestUnit);
+ }
+
+ if (*hoursPtr != 0 ) {
+ intervalLeft = intervalLeft % unitFactor;
+ }
+ }
+
+ if (minutesPtr) {
+ unitFactor = (60 * 1000);
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *minutesPtr = intervalLeft / unitFactor;
+ if (smallestUnit == Qt::Minutes)
+ {
+ QTimeSpan leftOverTime(referencedDate(), -intervalLeft);
+ leftOverTime.normalize();
+ *fractionalSmallestUnit = leftOverTime.toTimeUnit(smallestUnit);
+ }
+
+ if (*minutesPtr != 0 ) {
+ intervalLeft = intervalLeft % unitFactor;
+ }
+ }
+
+ if (secondsPtr) {
+ unitFactor = (1000);
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *secondsPtr = intervalLeft / unitFactor;
+ if (smallestUnit == Qt::Seconds)
+ {
+ QTimeSpan leftOverTime(referencedDate(), -intervalLeft);
+ leftOverTime.normalize();
+ *fractionalSmallestUnit = leftOverTime.toTimeUnit(smallestUnit);
+ }
+
+ if (*secondsPtr > 0 ) {
+ intervalLeft = intervalLeft % unitFactor;
+ }
+ }
+
+ if (msecondsPtr) {
+ unitFactor = 1;
+ CHECK_INT_LIMIT(intervalLeft, unitFactor)
+
+ *msecondsPtr = intervalLeft;
+ if (smallestUnit == Qt::Weeks)
+ {
+ *fractionalSmallestUnit = qreal(intervalLeft);
+ }
+ }
+
+ return true;
+}
+
+/*!
+ Sets a part of the time span in the given format.
+
+ setPart allows you to adapt the current time span interval unit-by-unit based on
+ any time format. Where setFromTimeUnit resets the complete time interval, setPart
+ only sets a specific part in a chosen format.
+
+ \example If you have a time span representing 3 weeks, 2 days, 4 hours, 31 minutes
+ and 12 seconds, you can change the number of hours to 2 by just calling
+ span.setPart(Qt::Hours, 2, Qt::Weeks | Qt::Days | Qt::Hours | Qt::Minutes | Qt::Seconds);
+
+ Note that just like with any other function, you can not use the Months and Years
+ units without using a reference date.
+*/
+void QTimeSpan::setPart(Qt::TimeSpanUnit unit, int interval, Qt::TimeSpanFormat format)
+{
+ if (!format.testFlag(unit)) {
+ qWarning() << "Can not set a unit that is not part of the format. Ignoring.";
+ return;
+ }
+
+ QTimeSpanPrivate::TimePartHash partsHash(format);
+ bool result = partsHash.fill(*this);
+
+ if (!result) {
+ qWarning() << "Retreiving parts failed, cannot set parts. Ignoring.";
+ return;
+ }
+
+ d->addUnit(this, unit, interval - *(partsHash.value(unit) ) );
+}
+
+/*!
+ Returns Qt::TimeSpanUnit representing the order of magnitude of the time span.
+ That is, the largest unit that can be used to display the time span that
+ will result in a non-zero value.
+
+ If the QTimeSpan does not have a valid reference date, the largest
+ possible time unit that will be returned is Qt::Weeks. Otherwise,
+ the largest possible time unit is Qt::Years.
+
+ \returns Unit representing the order of magnitude of the time span.
+*/
+Qt::TimeSpanUnit QTimeSpan::magnitude()
+{
+ //abs(qint64) doesnt't compile properly with mingw32?
+ qint64 mag = d->interval;
+ if (mag < 0)
+ mag = -mag;
+
+ if (mag < 1000)
+ return Qt::Milliseconds;
+ if (mag < (1000LL * 60LL))
+ return Qt::Seconds;
+ if (mag < (1000LL * 60LL * 60LL))
+ return Qt::Minutes;
+ if (mag < (1000LL * 60LL * 60LL * 24LL))
+ return Qt::Hours;
+ if (mag < (1000LL * 60LL * 60LL * 24LL * 7LL))
+ return Qt::Days;
+
+ //those the simple cases. The rest is dependent on if there is a reference date
+ if (hasValidReference()) {
+ //simple test. If bigger than 366 (not 365!) then we are certain of dealing with years
+ if (mag > (1000LL * 60LL * 60LL * 24LL * 366LL))
+ return Qt::Years;
+ //we need a more complicated test
+ int years = 0;
+ int months = 0;
+ parts(0, 0, 0, 0, 0, 0, &months, &years);
+ if (years > 0)
+ return Qt::Years;
+ if (months > 0)
+ return Qt::Months;
+ }
+
+ return Qt::Weeks;
+}
+
+/*!
+ \returns true if there is a valid reference date set, false otherwise.
+*/
+bool QTimeSpan::hasValidReference() const
+{
+ return d->reference.isValid();
+}
+
+/*!
+ \returns the reference date. Note that the reference date may be invalid.
+*/
+QDateTime QTimeSpan::referenceDate() const
+{
+ return d->reference;
+}
+
+/*!
+ Sets the reference date.
+
+ If there currently is a reference date, the referenced date will
+ not be affected. That means that the length of the time span will
+ change. If there currently is no reference date set, the interval
+ will not be affected and this function will have the same
+ effect as moveReferenceDate.
+
+ /sa moveReferenceDate setReferencedDate moveReferencedDate
+*/
+void QTimeSpan::setReferenceDate(const QDateTime &referenceDate)
+{
+ if (d->reference.isValid() && referenceDate.isValid()) {
+ *this = referencedDate() - referenceDate;
+ } else {
+ d->reference = referenceDate;
+ }
+}
+
+/*!
+ Moves the time span to align the time spans reference date with the
+ new reference date.
+
+ Note that the length of the time span will not be modified, so the
+ referenced date will shift as well. If no reference date was set
+ before, it is set now and the referenced date will become valid.
+
+ /sa setReferenceDate setReferencedDate moveReferencedDate
+*/
+void QTimeSpan::moveReferenceDate(const QDateTime &referenceDate)
+{
+ d->reference = referenceDate;
+}
+
+/*!
+ Sets the referenced date.
+
+ If there currently is a reference date, that reference date will
+ not be affected. This implies that the length of the time span changes.
+ If there currently is no reference date set, the interval
+ will not be affected and this function will have the same
+ effect as moveReferencedDate.
+
+ /sa setReferenceDate moveReferenceDate moveReferencedDate
+
+*/
+void QTimeSpan::setReferencedDate(const QDateTime &referencedDate)
+{
+ if (d->reference.isValid()) {
+ *this = referencedDate - d->reference;
+ } else {
+ d->reference = referencedDate.addMSecs(-(d->interval));
+ }
+}
+
+/*!
+ Moves the time span to align the time spans referenced date with the
+ new referenced date.
+
+ Note that the length of the time span will not be modified, so the
+ reference date will shift as well. If no reference date was set
+ before, it is set now.
+
+ /sa setReferenceDate setReferencedDate moveReferencedDate
+*/
+void QTimeSpan::moveReferencedDate(const QDateTime &referencedDate)
+{
+ d->reference = referencedDate.addMSecs(-(d->interval));
+}
+
+/*!
+ Returns the referenced date and time.
+
+ The referenced QDateTime is the "other end" of the QTimeSpan from
+ the reference date.
+
+ An invalid QDateTime will be returned if no valid reference date
+ has been set.
+*/
+QDateTime QTimeSpan::referencedDate() const
+{
+ if (!(d->reference.isValid()))
+ return QDateTime();
+
+ QDateTime dt(d->reference);
+ dt = dt.addMSecs(d->interval);
+ return dt;
+}
+
+// Comparison operators
+/*!
+ Returns true if the two compared QTimeSpans have both the same
+ reference date and the same length.
+
+ Note that two QTimeSpan objects that span the same period, but
+ where one is positive and the other is negative are not considdered
+ equal. If you need to compare those, compare the normalized
+ versions.
+
+ \sa matchesLength
+*/
+bool QTimeSpan::operator==(const QTimeSpan &other) const
+{
+ return ((d->interval == other.d->interval) &&
+ (d->reference == other.d->reference));
+}
+
+/*!
+ Returns true if the interval of this QTimeSpan is shorter than
+ the interval of the other QTimeSpan.
+*/
+bool QTimeSpan::operator<(const QTimeSpan &other) const
+{
+ return d->interval < other.d->interval;
+}
+
+/*!
+ Returns true if the interval of this QTimeSpan is shorter or equal
+ than the interval of the other QTimeSpan.
+*/
+bool QTimeSpan::operator<=(const QTimeSpan &other) const
+{
+ return d->interval <= other.d->interval;
+}
+
+/*!
+ Returns true if the interval of this QTimeSpan is equal
+ to the interval of the other QTimeSpan. That is, if they have the
+ same length.
+
+ The default value of normalize is false. If normalize is true, the
+ absolute values of the interval lengths are compared instead of the
+ real values.
+
+ \code
+ QTimeSpan s1 = 2 * QTimeSpan::Day;
+ QTimeSpan s2 = -2 * QTimeSpan::Day;
+ qDebug() << s1.matchesLength(s2); //returns false
+ qDebug() << s1.matchesLength(s2, true); //returns true
+ \endcode
+*/
+bool QTimeSpan::matchesLength(const QTimeSpan &other, bool normalize) const
+{
+ if (!normalize) {
+ return d->interval == other.d->interval;
+ } else {
+ return qAbs(d->interval) == qAbs(other.d->interval);
+ }
+}
+
+// Arithmatic operators
+/*!
+ Adds the interval of the other QTimeSpan to the interval of
+ this QTimeSpan. The reference date of the other QTimeSpan is
+ ignored.
+*/
+QTimeSpan & QTimeSpan::operator+=(const QTimeSpan &other)
+{
+ d->interval += other.d->interval;
+ return *this;
+}
+
+/*!
+ Adds the number of milliseconds to the interval of
+ this QTimeSpan. The reference date of the QTimeSpan is
+ not affected.
+*/
+QTimeSpan & QTimeSpan::operator+=(qint64 msecs)
+{
+ d->interval += msecs;
+ return *this;
+}
+
+/*!
+ Substracts the interval of the other QTimeSpan from the interval of
+ this QTimeSpan. The reference date of the other QTimeSpan is
+ ignored while the reference date of this QTimeSpan is not affected.
+*/
+QTimeSpan & QTimeSpan::operator-=(const QTimeSpan &other)
+{
+ d->interval -= (other.d->interval);
+ return *this;
+}
+
+/*!
+ Substracts the number of milliseconds from the interval of
+ this QTimeSpan. The reference date of the QTimeSpan is
+ not affected.
+*/
+QTimeSpan & QTimeSpan::operator-=(qint64 msecs)
+{
+ d->interval -= msecs;
+ return *this;
+}
+
+/*!
+ Multiplies the interval described by this QTimeSpan by the
+ given factor. The reference date of the QTimeSpan is not
+ affected.
+*/
+QTimeSpan & QTimeSpan::operator*=(qreal factor)
+{
+ d->interval *= factor;
+ return *this;
+}
+
+/*!
+ Multiplies the interval described by this QTimeSpan by the
+ given factor. The reference date of the QTimeSpan is not
+ affected.
+*/
+QTimeSpan & QTimeSpan::operator*=(int factor)
+{
+ d->interval *= factor;
+ return *this;
+}
+
+/*!
+ Divides the interval described by this QTimeSpan by the
+ given factor. The reference date of the QTimeSpan is not
+ affected.
+*/
+QTimeSpan & QTimeSpan::operator/=(qreal factor)
+{
+ d->interval /= factor;
+ return *this;
+}
+
+/*!
+ Divides the interval described by this QTimeSpan by the
+ given factor. The reference date of the QTimeSpan is not
+ affected.
+*/
+QTimeSpan & QTimeSpan::operator/=(int factor)
+{
+ d->interval /= factor;
+ return *this;
+}
+
+/*!
+ \brief Modifies this QTimeSpan to be the union of two QTimeSpans.
+
+ The union of two QTimeSpans is defined as the minimum QTimeSpan that
+ encloses both QTimeSpans. The QTimeSpans need not be overlapping.
+
+ \warning Only works if both QTimeSpans have a valid reference date.
+ \sa operator&=(const QTimeSpan& other)
+ \sa operator|(const QTimeSpan& other)
+ \sa united(const QTimeSpan& other)
+*/
+QTimeSpan& QTimeSpan::operator|=(const QTimeSpan& other) // Union
+{
+ Q_ASSERT_X((hasValidReference() && other.hasValidReference()), "assignment-or operator", "Both participating time spans need a valid reference date");
+
+ //do we need to check for self-assignment?
+
+ QDateTime start = qMin(startDate(), other.startDate());
+ QDateTime end = qMax(endDate(), other.endDate());
+
+ *this = end - start;
+ return *this;
+}
+
+/*!
+ \brief Modifies this QTimeSpan to be the intersection of two QTimeSpans.
+
+ The intersection of two QTimeSpans is defined as the maximum QTimeSpan that
+ both QTimeSpans have in common. If the QTimeSpans don't overlap, a null QTimeSpan
+ will be returned. The returned QTimeSpan will be positive.
+
+ \warning Only works if both QTimeSpans have a valid reference date.
+ \sa operator&=(const QTimeSpan& other)
+ \sa operator&(const QTimeSpan& other)
+ \sa overlapped(const QTimeSpan& other)
+*/
+QTimeSpan& QTimeSpan::operator&=(const QTimeSpan &other) // Intersection
+{
+ Q_ASSERT_X((hasValidReference() && other.hasValidReference()), "assignment-or operator", "Both participating time spans need a valid reference date");
+
+ //do we need to check for self-assignment?
+
+ const QTimeSpan* first = this;
+ const QTimeSpan* last = &other;
+ if (other.startDate() < startDate()) {
+ first = &other;
+ last = this;
+ }
+
+ //check if there is overlap at all. If not, reset the interval to 0
+ if (!(first->endDate() > last->startDate()) ) {
+ d->interval = 0;
+ return *this;
+ }
+
+ *this = qMin(first->endDate(), last->endDate()) - last->startDate();
+ return *this;
+}
+
+/*!
+ Returns true if this QTimeSpan overlaps with the other QTimeSpan.
+ If one of the QTimeSpans does not have a valid reference date, this
+ function returns false.
+*/
+bool QTimeSpan::overlaps(const QTimeSpan &other) const
+{
+ if (!hasValidReference() || !other.hasValidReference())
+ return false;
+
+ const QTimeSpan* first = this;
+ const QTimeSpan* last = &other;
+ if (other.startDate() < startDate()) {
+ first = &other;
+ last = this;
+ }
+
+ return (first->endDate() > last->startDate());
+}
+
+/*!
+ \brief Returns a new QTimeSpan that represents the intersection of the two QTimeSpans.
+
+ The intersection of two QTimeSpans is defined as the maximum QTimeSpan that
+ both QTimeSpans have in common. If the QTimeSpans don't overlap, a null QTimeSpan
+ will be returned. Any valid returned QTimeSpan will be positive.
+
+ \warning Only works if both QTimeSpans have a valid reference date. Will assert otherwise.
+ \sa operator&=(const QTimeSpan& other)
+ \sa operator&(const QTimeSpan& other)
+
+*/
+QTimeSpan QTimeSpan::overlapped(const QTimeSpan &other) const
+{
+ Q_ASSERT_X((hasValidReference() && other.hasValidReference()), "assignment-or operator", "Both participating time spans need a valid reference date");
+
+ const QTimeSpan* first = this;
+ const QTimeSpan* last = &other;
+ if (other.startDate() < startDate()) {
+ first = &other;
+ last = this;
+ }
+
+ //check if there is overlap at all. If not, reset the interval to 0
+ if (!(first->endDate() >= last->startDate()) ) {
+ return QTimeSpan();
+ }
+
+ return qMin(first->endDate(), last->endDate()) - last->startDate();
+}
+
+/*!
+ \brief Returns a new QTimeSpan that represents the union of two QTimeSpans.
+
+ The union of two QTimeSpans is defined as the minimum QTimeSpan that
+ encloses both QTimeSpans. The QTimeSpans need not be overlapping.
+
+ \warning Only works if both QTimeSpans have a valid reference date. Will assert otherwise.
+ \sa operator|=(const QTimeSpan& other)
+ \sa operator|(const QTimeSpan& other)
+*/
+QTimeSpan QTimeSpan::united(const QTimeSpan &other) const
+{
+ Q_ASSERT_X((hasValidReference() && other.hasValidReference()), "assignment-or operator", "Both participating time spans need a valid reference date");
+
+ QDateTime start = qMin(startDate(), other.startDate());
+ QDateTime end = qMax(endDate(), other.endDate());
+
+ return ( end - start );
+}
+
+/*!
+ Determines if the given dateTime lies within the time span. The begin
+ and end times are taken to be contained in the time span in this function.
+
+ If the time span does not have a valid reference date, this function
+ returns false.
+*/
+bool QTimeSpan::contains(const QDateTime &dateTime) const
+{
+ if (!hasValidReference())
+ return false;
+
+ return ((startDate() <= dateTime) &&
+ (endDate()) >= dateTime);
+}
+
+/*!
+ Determines if the given date lies within the time span. The begin
+ and end times are taken to be contained in the time span in this function.
+ Just like in the QTimeSpan constructors that take a QDate, the time will assumed
+ to be 00:00:00.000.
+
+ If the time span does not have a valid reference date, this function
+ returns false.
+*/
+bool QTimeSpan::contains(const QDate &date) const
+{
+ QDateTime dt(date);
+ return contains(dt);
+}
+
+/*!
+ Determines if the given time lies within the time span. The begin
+ and end times are taken to be contained in the time span in this function.
+ Just like in the QTimeSpan constructors that take a QTime, the date
+ will be set to today.
+
+ If the time span does not have a valid reference date, this function
+ returns false.
+*/
+bool QTimeSpan::contains(const QTime &time) const
+{
+ QDateTime dt(QDate::currentDate());
+ dt.setTime(time);
+ return contains(dt);
+}
+
+/*!
+ Determines if the other QTimeSpan lies within this time span. Another
+ time span is contained if its start time is the same or later then the
+ start time of this time span, and its end time is the same or earlier
+ than the end time of this time span.
+
+ If either time span does not have a valid reference date, this function
+ returns false.
+*/
+bool QTimeSpan::contains(const QTimeSpan &other) const
+{
+ if (!(hasValidReference() && other.hasValidReference()))
+ return false;
+
+ return ((startDate() <= other.startDate()) &&
+ (endDate()) >= other.endDate());
+}
+
+/*!
+ Returns a new QTimeSpan representing the same time span as this QTimeSpan, but
+ that is guaranteed to be positive; that is, to have the reference date before or
+ equal to the referenced date.
+
+ \sa normalize abs
+ */
+QTimeSpan QTimeSpan::normalized() const
+{
+ QTimeSpan ts(*this);
+ ts.normalize();
+ return ts;
+}
+
+/*!
+ Modifies this QTimeSpan to represent the same time span, but
+ that is guaranteed to be positive; that is, to have the reference date before or
+ equal to the referenced date. If there is no valid reference date, the interval
+ will just be made positive.
+
+ \sa normalized abs
+ */
+void QTimeSpan::normalize()
+{
+ if (d->interval < 0) {
+ if (hasValidReference()) {
+ d->reference = referencedDate();
+ }
+ d->interval = qAbs(d->interval);
+ }
+}
+
+/*!
+ Returns a copy of this QTimeSpan that is guaranteed to be positive; that is,
+ to have the reference date before or equal to the referenced date. The reference
+ date is not modified. That implies that if there is a reference date, and the
+ QTimeSpan is negative, the returned QTimeSpan will describe the time span \i after
+ the reference date instead of the time span \i before.
+
+ If there is no valid reference date, the interval will just be made positive.
+
+ \sa normalize normalized
+ */
+QTimeSpan QTimeSpan::abs() const
+{
+ QTimeSpan result(*this);
+ result.d->interval = qAbs(result.d->interval);
+
+ return result;
+}
+
+/*!
+ Returns true if the interval is negative.
+ \sa isNormal
+ */
+bool QTimeSpan::isNegative() const
+{
+ return d->interval < 0;
+}
+
+/*!
+ \fn QTimeSpan::isNormal() const
+
+ Returns true if the interval is normal, that is: not negative.
+ \sa isNegative
+ */
+
+/*!
+ Returns the first date of the spanned time period. If there is no valid
+ reference date, an invalid QDateTime will be returned.
+ */
+QDateTime QTimeSpan::startDate() const
+{
+ if (isNegative())
+ return referencedDate();
+
+ return referenceDate();
+}
+
+/*!
+ Returns the last date of the spanned time period. If there is no valid
+ reference date, an invalid QDateTime will be returned.
+ */
+QDateTime QTimeSpan::endDate() const
+{
+ if (isNegative())
+ return referenceDate();
+
+ return referencedDate();
+}
+
+/*!
+ Returns the duration of the QTimeSpan expressed in milliseconds. This
+ value may be negative.
+*/
+qint64 QTimeSpan::toMSecs() const
+{
+ return d->interval;
+}
+
+/*!
+ Returns the duration of the QTimeSpan expressed in the given TimeSpanUnit. This
+ value may be negative.
+*/
+qreal QTimeSpan::toTimeUnit(Qt::TimeSpanUnit unit) const
+{
+ qreal interval = qreal(d->interval);
+ switch (unit){ //fall through is intentional
+ case Qt::Weeks:
+ interval /= 7.0;
+ case Qt::Days:
+ interval /= 24.0;
+ case Qt::Hours:
+ interval /= 60.0;
+ case Qt::Minutes:
+ interval /= 60.0;
+ case Qt::Seconds:
+ interval /= 1000.0;
+ case Qt::Milliseconds:
+ break;
+ default:
+ Q_ASSERT_X(hasValidReference(), "toTimeUnit", "Can not convert to time units that depend on the reference date (month and year).");
+ qreal result(0.0);
+ int intResult(0);
+ bool succes(false);
+ if (unit == Qt::Months) {
+ succes = parts(0, 0, 0, 0, 0, 0, &intResult, 0, &result);
+ } else if (unit == Qt::Years) {
+ succes = parts(0, 0, 0, 0, 0, 0, 0, &intResult, &result);
+ }
+
+ if (!succes)
+ return 0.0;
+
+ return result;
+ }
+
+ return interval;
+}
+
+/*!
+ Sets the length of this QTimeSpan from the given number of milliseconds. The reference date is not
+ affected.
+ */
+void QTimeSpan::setFromMSecs(qint64 msecs)
+{
+ d->interval = msecs;
+}
+
+/*!
+ Sets the length of this QTimeSpan from the given number of TimeSpanUnits. The reference date is not
+ affected.
+ */
+void QTimeSpan::setFromTimeUnit(Qt::TimeSpanUnit unit, qreal interval)
+{
+ switch (unit){
+ case Qt::Weeks: //fall through of cases is intentional!
+ interval *= 7.0;
+ case Qt::Days:
+ interval *= 24.0;
+ case Qt::Hours:
+ interval *= 60.0;
+ case Qt::Minutes:
+ interval *= 60.0;
+ case Qt::Seconds:
+ interval *= 1000.0;
+ case Qt::Milliseconds:
+ break;
+ case Qt::Months:
+ setFromMonths(interval);
+ return;
+ case Qt::Years:
+ setFromYears(interval);
+ return;
+ default:
+ Q_ASSERT_X(false, "setFromTimeUnit", "Can not set a QTimeSpan duration from unknown TimeSpanUnit.");
+ }
+
+ d->interval = qint64(interval);
+}
+
+/*!
+ Sets the interval of the time span as a number of months.
+
+ \warning This function can only be used if a valid reference date has been set!
+
+ The setFromMonths method deals with fractional months in the following way: first,
+ the whole number of months is extracted and added to the reference date. The fractional
+ part of the number of months is then multiplied with the number of days in the month
+ in which that date falls. If the number of months is negative and adding a whole month
+ yields a date exactly on a month boundary, the number of days in the month before is
+ used instead.
+ That number is used as the number of days and is added to the interval.
+
+ \code
+ QTimeSpan ts(QDate(2010,01,01));
+ ts.setFromMonths(1.5); // ts's referenced date is now februari 14, 0:00:00
+ ts.setFromMonths(2.5); // ts's referenced date is now march 15, 0:00:00
+ QTimeSpan ts2(QDate(2008,01,01)); //2008 is a leap year!
+ ts2.setFromMonths(1.5); // ts2's referenced date is now februari 14, 12:00:00
+ QTimeSpan ts3(QDate(2008,03,01)); //2008 is a leap year
+ ts3.setFromMonths(-0.5); // ts3's referenced date is now februari 14: 12:00:00 //
+ \endcode
+ */
+void QTimeSpan::setFromMonths(qreal months)
+{
+ Q_ASSERT_X(hasValidReference(), "setFromMonths", "Can not set interval from time unit month if there is no reference date.");
+
+ int fullMonths = int(months);
+ qreal fractionalMonth = months - fullMonths;
+
+ QDateTime endDate = d->reference;
+ endDate = endDate.addMonths(fullMonths);
+
+ int days = d->s_daysPerMonth[endDate.date().month()-1];
+ QDateTime measureDate(endDate);
+ if (fractionalMonth < 0) {
+ measureDate = measureDate.addMSecs(-1);
+ }
+ if (QDate::isLeapYear(measureDate.date().year()) && measureDate.date().month() == 2) {
+ ++days; //februari has an extra day this year...
+ }
+
+ QTimeSpan tmp = endDate - d->reference;
+ qreal fractionalDays = fractionalMonth * days;
+ d->interval = tmp.toMSecs() + qint64(fractionalDays * 24.0 * 60.0 * 60.0 * 1000.0);
+}
+
+/*!
+ Sets the interval of the time span as a number of years.
+
+ \warning This function can only be used if a valid reference date has been set!
+
+ The setFromYears method deals with fractional years in the following way: first,
+ the whole number of years is extracted and added to the reference date. The fractional
+ part of the number of years is then multiplied with the number of days in the year
+ in which that date falls. That number is used as the number of days and is added to the
+ interval.
+ If the number of years is negative and adding the whole years yields a date exactly on
+ a year boundary, the number of days in the year before is used instead.
+ */
+void QTimeSpan::setFromYears(qreal years)
+{
+ Q_ASSERT_X(hasValidReference(), "setFromYears", "Can not set interval from time unit year if there is no reference date.");
+
+ int fullYears = int(years);
+ qreal fractionalYear = years - fullYears;
+
+ QDateTime endDate = d->reference;
+ endDate = endDate.addYears(fullYears);
+
+ qreal days = 365.0;
+ QDateTime measureDate(endDate);
+ if (fractionalYear < 0) {
+ measureDate = measureDate.addMSecs(-1);
+ }
+ if (QDate::isLeapYear(measureDate.date().year())) {
+ days += 1.0; //februari has an extra day this year...
+ }
+
+ QTimeSpan tmp = endDate - d->reference;
+ qreal fractionalDays = fractionalYear * days;
+ d->interval = tmp.toMSecs() + qint64(fractionalDays * 24.0 * 60.0 * 60.0 * 1000.0);
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ Streaming operator.
+
+ This operator allows you to stream a QTimeSpan into a QDataStream.
+ /sa operator>>(QDataStream &stream, QTimeSpan &span)
+ */
+QDataStream & operator<<(QDataStream &stream, const QTimeSpan & span)
+{
+ stream << span.d->reference << span.d->interval;
+ return stream;
+}
+
+/*!
+ Streaming operator.
+
+ This operator allows you to stream a QTimeSpan out of a QDataStream.
+ /sa operator>>(QDataStream &stream, QTimeSpan &span)
+ */
+QDataStream & operator>>(QDataStream &stream, QTimeSpan &span)
+{
+ stream >> span.d->reference >> span.d->interval;
+ return stream;
+}
+#endif
+
+/*!
+ Adds another QTimeSpan to this QTimeSpan.
+
+ The values of the intervals of the QTimeSpans are added up with normal
+ arithmatic. Negative values will work as expected.
+
+ If the left argument has a reference date, that reference will be kept.
+ If only the right argument has a reference date, then that reference
+ date will be used as the new reference date.
+
+ The above can have suprising consequences:
+ \code
+ // s1 and s2 are two QTimeSpan objects
+ QTimeSpan s12 = s1 + s2;
+ QTimeSpan s21 = s2 + s1;
+
+ if (s12 == s21) {
+ //may or may not happen, depending on the reference dates of s1 and s2.
+ }
+ \endcode
+*/
+QTimeSpan operator+(const QTimeSpan &left, const QTimeSpan &right)
+{
+ QTimeSpan result(left);
+ result += right;
+
+ // only keep the right reference date if the left argument does not have one
+ if (!left.hasValidReference() && right.hasValidReference()) {
+ result.setReferenceDate(right.referenceDate());
+ }
+
+ return result;
+}
+
+/*!
+ Substracts another QTimeSpan from this QTimeSpan.
+
+ The value of the interval of the right QTimeSpan is substracted from the
+ left QTimeSpan with normal arithmatic. Negative values will work as expected.
+
+ If the left argument has a reference date, that reference will be kept.
+ If only the right argument has a reference date, then that reference
+ date will be used as the new reference date.
+
+ \sa operator+
+*/
+QTimeSpan operator-(const QTimeSpan &left, const QTimeSpan &right)
+{
+ QTimeSpan result(left);
+ result -= right;
+
+ // only keep the right reference date if the left argument does not have one
+ if (!left.hasValidReference() && right.hasValidReference()) {
+ result.setReferenceDate(right.referenceDate());
+ }
+
+ return result;
+
+}
+
+/*!
+ Multiply a QTimeSpan by a scalar factor.
+
+ \returns a new QTimeSpan object that has the same reference date as the
+ left QTimeSpan, but with an interval length that is multiplied by the
+ right argument.
+*/
+QTimeSpan operator*(const QTimeSpan &left, qreal right)
+{
+ QTimeSpan result(left);
+ result*=right;
+ return result;
+}
+
+/*!
+ Multiply a QTimeSpan by a scalar factor.
+
+ \returns a new QTimeSpan object that has the same reference date as the
+ left QTimeSpan, but with an interval length that is multiplied by the
+ right argument.
+*/
+QTimeSpan operator*(const QTimeSpan &left, int right)
+{
+ QTimeSpan result(left);
+ result*=right;
+ return result;
+}
+
+/*!
+ Devide a QTimeSpan by a scalar factor.
+
+ \returns a new QTimeSpan object that has the same reference date as the
+ left QTimeSpan, but with an interval length that is devided by the
+ right argument.
+*/
+QTimeSpan operator/(const QTimeSpan &left, qreal right)
+{
+ QTimeSpan result(left);
+ result/=right;
+ return result;
+}
+
+/*!
+ Devide a QTimeSpan by a scalar factor.
+
+ \returns a new QTimeSpan object that has the same reference date as the
+ left QTimeSpan, but with an interval length that is devided by the
+ right argument.
+*/
+QTimeSpan operator/(const QTimeSpan &left, int right)
+{
+ QTimeSpan result(left);
+ result/=right;
+ return result;
+}
+
+/*!
+ Devides two QTimeSpans. The devision works on the interval lengths of
+ the two QTimeSpan objects as you would expect from normal artithmatic.
+*/
+qreal operator/(const QTimeSpan &left, const QTimeSpan &right)
+{
+ return (qreal(left.toMSecs()) / qreal(right.toMSecs()));
+}
+
+/*!
+ Returns a QTimeSpan object with the same reference date as the right
+ hand argument, but with a negated interval. Note that unlike with the
+ normalize() method, this function will result in a QTimeSpan that
+ describes a different period if the QTimeSpan has a reference date because
+ the reference date is not modified.
+*/
+QTimeSpan operator-(const QTimeSpan &right) // Unary negation
+{
+ QTimeSpan result(right);
+ result.setFromMSecs(-result.toMSecs());
+ return result;
+}
+
+/*!
+ \returns the union of the two QTimeSpans.
+
+ \sa united
+*/
+QTimeSpan operator|(const QTimeSpan &left, const QTimeSpan &right) // Union
+{
+ QTimeSpan result(left);
+ result|=right;
+ return result;
+}
+
+/*!
+ \returns the intersection of the two QTimeSpans.
+
+ \sa intersected
+*/
+QTimeSpan operator&(const QTimeSpan &left, const QTimeSpan &right) // Intersection
+{
+ QTimeSpan result(left);
+ result&=right;
+ return result;
+}
+
+// Operators that use QTimeSpan and other date/time classes
+/*!
+ Creates a new QTimeSpan object that describes the period between the two
+ QDateTime objects. The right hand object will be used as the reference date,
+ so that substracting a date in the past from a date representing now will yield
+ a positive QTimeSpan.
+
+ \note that while substracting two dates will result in a QTimeSpan describing
+ the time between those dates, there is no pendant operation for adding two dates.
+
+ Substractions involving an invalid QDateTime, will result in a time span with
+ an interval length 0. If the right-hand QDateTime is valid, it will still be
+ used as the reference date.
+*/
+QTimeSpan operator-(const QDateTime &left, const QDateTime &right)
+{
+ QTimeSpan result(right);
+#if QT_VERSION >= 0x040700
+ if (left.isValid() && right.isValid()) {
+ result = QTimeSpan(right, right.msecsTo(left));
+ }
+#else
+ if (left.isValid() && right.isValid()) {
+ QDateTime tmpLeft = left.toUTC();
+ QDateTime tmpRight = right.toUTC();
+ //don't use QDateTime::secsTo, you end up in rounding issues as well as overflow problems!
+ qint64 interval = 1000LL * 60LL * 60LL * 24LL * qint64(tmpRight.date().daysTo(tmpLeft.date()));
+ interval += tmpRight.time().msecsTo(tmpLeft.time());
+ result.setFromMSecs(interval);
+ }
+#endif
+ return result;
+}
+
+/*!
+ Creates a new QTimeSpan object that describes the period between the two
+ QDate objects. The right hand object will be used as the reference date,
+ so that substracting a date in the past from a date representing now will yield
+ a positive QTimeSpan.
+
+ \note that while substracting two dates will result in a QTimeSpan describing
+ the time between those dates, there is no pendant operation for adding two dates.
+*/
+QTimeSpan operator-(const QDate &left, const QDate &right)
+{
+ QTimeSpan result = QDateTime(left) - QDateTime(right);
+ return result;
+}
+
+/*!
+ Creates a new QTimeSpan object that describes the period between the two
+ QTime objects. The right hand time will be used as the reference time,
+ so that substracting a time in the past from a time representing now will yield
+ a positive QTimeSpan.
+
+ \note that that both times will be assumed to be on the current date.
+
+ \note that while substracting two times will result in a QTimeSpan describing
+ the time between those, there is no pendant operation for adding two times.
+*/
+QTimeSpan operator-(const QTime &left, const QTime &right)
+{
+ return QDateTime(QDate::currentDate(), left) - QDateTime(QDate::currentDate(), right);
+}
+
+/*!
+ \returns the date described by the left-hand date, shifted by the interval
+ described in the QTimeSpan. The reference date of the QTimeSpan, if set, is
+ ignored.
+
+ No rounding takes place. If a QTimeSpan describes 1 day, 23 hours and 59 minutes,
+ adding that QTimeSpan to a QDate respresenting April 1 will still yield April 2.
+*/
+QDate operator+(const QDate &left, const QTimeSpan &right)
+{
+ QDateTime dt(left);
+ return (dt + right).date();
+}
+
+/*!
+ \returns the date and time described by the left-hand QDateTime, shifted by
+ the interval described in the QTimeSpan. The reference date of the QTimeSpan, if set,
+ is ignored.
+*/
+QDateTime operator+(const QDateTime &left, const QTimeSpan &right)
+{
+ QDateTime result(left);
+ result = result.addMSecs(right.toMSecs());
+ return result;
+}
+
+/*!
+ \returns the time described by the left-hand QTime, shifted by
+ the interval described in the QTimeSpan. The reference date of the QTimeSpan, if set,
+ is ignored.
+
+ \note that since QTimeSpan works with dates and times, the time returned will never
+ be bigger than 23:59:59.999. The time will wrap to the next date. Use QDateTime objects
+ if you need to keep track of that.
+*/
+QTime operator+(const QTime &left, const QTimeSpan &right)
+{
+ QDateTime dt(QDate::currentDate(), left);
+ dt = dt.addMSecs(right.toMSecs());
+ return dt.time();
+}
+
+/*!
+ \returns the date described by the left-hand date, shifted by the negated interval
+ described in the QTimeSpan. The reference date of the QTimeSpan, if set, is
+ ignored.
+
+ No rounding takes place. If a QTimeSpan describes 1 day, 23 hours and 59 minutes,
+ adding that QTimeSpan to a QDate respresenting April 1 will still yield April 2.
+*/
+QDate operator-(const QDate &left, const QTimeSpan &right)
+{
+ QDateTime dt(left);
+ return (dt - right).date();
+}
+
+/*!
+ \returns the date and time described by the left-hand QDateTime, shifted by
+ the negated interval described in the QTimeSpan. The reference date of the
+ QTimeSpan, if set, is ignored.
+*/
+QDateTime operator-(const QDateTime &left, const QTimeSpan &right)
+{
+ QDateTime result(left);
+ result = result.addMSecs( -(right.toMSecs()) );
+ return result;
+}
+
+/*!
+ \returns the time described by the left-hand QTime, shifted by
+ the negated interval described in the QTimeSpan. The reference date of
+ the QTimeSpan, if set, is ignored.
+
+ \note that since QTimeSpan works with dates and times, the time returned will never
+ be bigger than 23:59:59.999. The time will wrap to the next date. Use QDateTimes
+ if you need to keep track of that.
+*/
+QTime operator-(const QTime &left, const QTimeSpan &right)
+{
+ QDateTime dt(QDate::currentDate(), left);
+ dt = dt.addMSecs( -(right.toMSecs()) );
+ return dt.time();
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
+/*!
+ Operator to stream QTimeSpan objects to a debug stream.
+*/
+QDebug operator<<(QDebug debug, const QTimeSpan &ts)
+{
+ debug << "QTimeSpan(Reference Date =" << ts.referenceDate()
+ << "msecs =" << ts.toMSecs() << ")";
+ return debug;
+}
+#endif
+
+//String conversions
+#ifndef QT_NO_DATESTRING
+/*!
+ \returns an approximate representation of the time span length
+
+ When representing the lenght of a time span, it is often not nessecairy to be
+ completely accurate. For instance, when dispaying the age of a person, it is
+ often enough to just state the number of years, or possibly the number of years
+ and the number of months. Similary, when displaying how long a certain operation
+ the user of your application started will run, it is useless to display the
+ number of seconds left if the operation will run for hours more.
+
+ toApproximateString() provides functionality to display the length of the
+ QTimeSpan in such an approximate way. It will format the time using one or two
+ neighbouring time units. The first time unit that will be used is the unit
+ that represents the biggest portion of time in the span. The second time unit
+ will be the time unit directly under that. The second unit will only be used
+ if it is not 0, and if the first number is smaller than the indicated
+ suppresSecondUnitLimit.
+
+ The suppressSecondUnitLimit argument can be used to suppres, for instance,
+ the number of seconds when the operation will run for more than five minutes
+ more. The idea is that for an approximate representation of the time length,
+ it is no longer relevant to display the second unit if the first respresents
+ a time span that is perhaps an order of magnitude larger already.
+
+ If you set suppressSecondUnitLimit to a negative number, the second unit will
+ always be displayed, unless no valid unit for it could be found.
+*/
+QString QTimeSpan::toApproximateString(int suppresSecondUnitLimit, Qt::TimeSpanFormat format)
+{
+ if (format==Qt::NoUnit)
+ return QString();
+
+ //retreive the time unit to use as the primairy unit
+ int primairy = -1;
+ int secondairy = -1;
+
+ Qt::TimeSpanUnit primairyUnit = magnitude();
+ while (!format.testFlag(primairyUnit ) && primairyUnit > Qt::NoUnit) {
+ primairyUnit = Qt::TimeSpanUnit(primairyUnit / 2);
+ }
+
+ Qt::TimeSpanUnit secondairyUnit = Qt::NoUnit;
+ if (primairyUnit > 1) {
+ secondairyUnit = Qt::TimeSpanUnit(primairyUnit / 2);
+ } else {
+ primairy = 0;
+ }
+ while (!format.testFlag(secondairyUnit) && secondairyUnit > Qt::NoUnit) {
+ secondairyUnit = Qt::TimeSpanUnit(secondairyUnit / 2);
+ }
+
+ //build up hash with pointers to ints for the units that are set in format, and 0's for those that are not.
+ if (primairy < 0) {
+ QTimeSpanPrivate::TimePartHash partsHash(format);
+ bool result = partsHash.fill(*this);
+
+ if (!result) {
+ qDebug() << "false result from parts function";
+ return QString();
+ }
+
+ primairy = *(partsHash.value(primairyUnit));
+ if (secondairyUnit > 0) {
+ secondairy = *(partsHash.value(secondairyUnit));
+ } else {
+ secondairy = 0;
+ }
+ }
+
+ if ((primairy > 0
+ && secondairy > 0
+ && primairy < suppresSecondUnitLimit)
+ || (suppresSecondUnitLimit < 0
+ && secondairyUnit > Qt::NoUnit) )
+ {
+ //we will display with two units
+ return d->unitString(primairyUnit, primairy) + QLatin1String(", ") + d->unitString(secondairyUnit, secondairy);
+ }
+
+ //we will display with only the primairy unit
+ return d->unitString(primairyUnit, primairy);
+}
+
+/*!
+ \returns a string representation of the duration of this time span in the requested format
+
+ This function returns a representation of only the length of this time span. If
+ you need the reference or referenced dates, access those using one of the provided
+ methods and output them directly.
+
+ The format parameter determines the format of the result string. The duration will be
+ expressed in the units you use in the format.
+
+ y The number of years
+ M The number of months
+ w The number of weeks
+ d The number of days
+ h The number of hours
+ m The number of minutes
+ s The number of seconds
+ z The number of milliseconds
+
+ Use multiple letters to force leading zeros.
+
+ \note You can not use years or months if the time span does not have a valid reference
+ date.
+
+ Characters in the string that don't represent a time unit, are used as literal strings in the
+ output. Everything between single quotes will always be used as a literal string. This makes
+ it possible to use the characters used for the time span format also as literal output. To use a
+ single quote in the output, put two consecutive single quotes within a single quote literal
+ string block. To just put a single quote in a the output, you need four consequtive single
+ quotes.
+*/
+QString QTimeSpan::toString(const QString &format) const
+{
+ Qt::TimeSpanFormat tsFormat = Qt::NoUnit;
+ QList tokenList = d->parseFormatString(format, tsFormat);
+
+ QTimeSpanPrivate::TimePartHash partsHash(tsFormat);
+ bool result = partsHash.fill(*this);
+
+ if (!result)
+ return QString();
+
+ QString formattedString;
+ foreach(QTimeSpanPrivate::TimeFormatToken token, tokenList) {
+ if (token.type == 0) {
+ formattedString.append(token.string);
+ } else {
+ Qt::TimeSpanUnit unit(token.type);
+ formattedString.append (QString("%1").arg(*partsHash.value( unit ),
+ token.length,
+ 10,
+ QChar('0') ) );
+ }
+ }
+
+ return formattedString;
+}
+
+/*!
+ Returns a time span represented by the string using the format given, or an empty
+ time span if the string cannot be parsed.
+
+ The optional reference argument will be used as the reference date for the string.
+
+ \note You can only use months or years if you also pass a valid reference.
+ */
+QTimeSpan QTimeSpan::fromString(const QString &string, const QString &format, const QDateTime &reference)
+{
+ /*
+
+ There are two possible ways of parsing a string. On the one hand, you could use the
+ lengths of string literals to determine the positions in the string where you expect
+ the different parts of the string. On the other hand, you could use the actual contents
+ of the literals as delimiters to figure out what parts of the string refer to what
+ unit of time. In that case, the length of the time units would only matter if they are
+ not surrounded by a string literal. Both seem useful. Perhaps we need two different
+ modes for this?
+
+ The code here implements the first option. The overloaded version below implements a
+ more flexible regexp based approach.
+ */
+
+ //stage one: parse the format string
+ QTimeSpan span(reference);
+ Qt::TimeSpanFormat tsFormat = Qt::NoUnit;
+ QList tokenList = span.d->parseFormatString(format, tsFormat);
+
+ //prepare the temporaries
+ QTimeSpanPrivate::TimePartHash partsHash(tsFormat);
+ QString input(string);
+
+ //extract the values from the input string into our temporary structure
+ foreach(const QTimeSpanPrivate::TimeFormatToken token, tokenList) {
+ if (token.type == Qt::NoUnit) {
+ input = input.remove(0, token.length);
+ } else {
+ QString part = input.left(token.length);
+ input = input.remove(0, token.length);
+
+ bool success(false);
+ part = part.trimmed();
+ int value = part.toInt(&success, 10);
+ if (!success) {
+ return QTimeSpan();
+ }
+ *(partsHash.value(token.type)) = value;
+ }
+ }
+
+ //construct the time span from the temporary data
+ //we must set the number of years and months first; for the rest order is not important
+ if (partsHash.value(Qt::Years)) {
+ span.d->addUnit(&span, Qt::Years, *(partsHash.value(Qt::Years)));
+ delete partsHash.value(Qt::Years);
+ partsHash.insert(Qt::Years, 0);
+ }
+ if (partsHash.value(Qt::Months)) {
+ span.d->addUnit(&span, Qt::Months, *(partsHash.value(Qt::Months)));
+ delete partsHash.value(Qt::Months);
+ partsHash.insert(Qt::Months, 0);
+ }
+
+ //add the rest of the units
+ QHashIterator it(partsHash);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value()) {
+ span.d->addUnit(&span, it.key(), *(it.value()));
+ qDebug() << "Added unit" << it.key() << "with value" << *(it.value()) << "new value" << span.d->interval;
+ }
+ }
+
+ return span;
+}
+
+/*!
+ Returns a time span represented by the string using the patern given, or an empty
+ time span if the string cannot be parsed. Each pair of capturing parenthesis can
+ extract a time unit. The order in which the units appear is given by the list of
+ arguments unit1 to unit8. Captures for which the corresponding type is set to
+ Qt::NoUnit will be ignored.
+
+ The reference argument will be used as the reference date for the string.
+
+ \note You can only use months or years if you also pass a valid reference.
+ */
+QTimeSpan QTimeSpan::fromString(const QString &string, const QRegExp &pattern, const QDateTime &reference,
+ Qt::TimeSpanUnit unit1, Qt::TimeSpanUnit unit2, Qt::TimeSpanUnit unit3,
+ Qt::TimeSpanUnit unit4, Qt::TimeSpanUnit unit5, Qt::TimeSpanUnit unit6,
+ Qt::TimeSpanUnit unit7, Qt::TimeSpanUnit unit8)
+{
+ if (pattern.indexIn(string) < 0)
+ return QTimeSpan();
+
+ QTimeSpanPrivate::TimePartHash partsHash(Qt::NoUnit);
+
+ QList unitList;
+ unitList << unit1 << unit2 << unit3 << unit4 << unit5 << unit6 << unit7 << unit8;
+
+ for (int i(0); i < qMin(pattern.captureCount(), 8 ); ++i) {
+ if (unitList.at(i) > Qt::NoUnit) {
+ partsHash.addUnit(unitList.at(i));
+ QString capture = pattern.cap(i + 1);
+ bool ok(false);
+ int value = capture.toInt(&ok, 10);
+ if (!ok)
+ return QTimeSpan();
+
+ *(partsHash.value(unitList.at(i))) = value;
+ }
+ }
+
+ //create the time span to return
+ QTimeSpan span(reference);
+
+ //construct the time span from the temporary data
+ //we must set the number of years and months first; for the rest order is not important
+ if (partsHash.value(Qt::Years)) {
+ span.d->addUnit(&span, Qt::Years, *(partsHash.value(Qt::Years)));
+ delete partsHash.value(Qt::Years);
+ partsHash.insert(Qt::Years, 0);
+ }
+ if (partsHash.value(Qt::Months)) {
+ span.d->addUnit(&span, Qt::Months, *(partsHash.value(Qt::Months)));
+ delete partsHash.value(Qt::Months);
+ partsHash.insert(Qt::Months, 0);
+ }
+
+ //add the rest of the units
+ QHashIterator it(partsHash);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value()) {
+ span.d->addUnit(&span, it.key(), *(it.value()));
+ }
+ }
+
+ return span;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/libraries/shared/src/qtimespan.h b/libraries/shared/src/qtimespan.h
new file mode 100644
index 0000000000..03ed69abe3
--- /dev/null
+++ b/libraries/shared/src/qtimespan.h
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTIMESPAN_H
+#define QTIMESPAN_H
+
+#include
+#include
+#include
+#include
+#include
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+//Move this to qnamespace.h when integrating
+namespace Qt
+{
+ enum TimeSpanUnit {
+ Milliseconds = 0x0001,
+ Seconds = 0x0002,
+ Minutes = 0x0004,
+ Hours = 0x0008,
+ Days = 0x0010,
+ Weeks = 0x0020,
+ Months = 0x0040,
+ Years = 0x0080,
+ DaysAndTime = Days | Hours | Minutes | Seconds,
+ AllUnits = Milliseconds | DaysAndTime | Months | Years,
+ NoUnit = 0
+ };
+
+ Q_DECLARE_FLAGS(TimeSpanFormat, TimeSpanUnit)
+}
+Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TimeSpanFormat)
+
+//end of section to move
+
+class QTimeSpanPrivate;
+
+class Q_CORE_EXPORT QTimeSpan
+{
+public:
+ QTimeSpan();
+ explicit QTimeSpan(qint64 msecs);
+ explicit QTimeSpan(const QDateTime& reference, qint64 msecs = 0);
+ explicit QTimeSpan(const QDate& reference, quint64 msecs = 0);
+ explicit QTimeSpan(const QTime& reference, quint64 msecs = 0);
+ explicit QTimeSpan(const QDateTime& reference, const QTimeSpan& other);
+ explicit QTimeSpan(const QDate& reference, const QTimeSpan& other);
+ explicit QTimeSpan(const QTime& reference, const QTimeSpan& other);
+ QTimeSpan(const QTimeSpan& other);
+
+
+ ~QTimeSpan();
+
+ // constant time units
+ static const QTimeSpan Second;
+ static const QTimeSpan Minute;
+ static const QTimeSpan Hour;
+ static const QTimeSpan Day;
+ static const QTimeSpan Week;
+
+ // status/validity of the time span
+ bool isEmpty() const;
+ bool isNull() const;
+
+ // This set of functions operates on a single component of the time span.
+ inline int msecsPart(Qt::TimeSpanFormat format = Qt::DaysAndTime | Qt::Milliseconds) const {return part(Qt::Milliseconds, format);}
+ inline int secsPart(Qt::TimeSpanFormat format = Qt::DaysAndTime) const {return part(Qt::Seconds, format);}
+ inline int minutesPart(Qt::TimeSpanFormat format = Qt::DaysAndTime) const {return part(Qt::Minutes, format);}
+ inline int hoursPart(Qt::TimeSpanFormat format = Qt::DaysAndTime) const {return part(Qt::Hours, format);}
+ inline int daysPart(Qt::TimeSpanFormat format = Qt::DaysAndTime) const {return part(Qt::Days, format);}
+ inline int weeksPart(Qt::TimeSpanFormat format = Qt::DaysAndTime) const {return part(Qt::Weeks, format);}
+ //int monthsPart(Qt::TimeSpanFormat format) const;
+ //int yearsPart(Qt::TimeSpanFormat format) const;
+ int part(Qt::TimeSpanUnit unit, Qt::TimeSpanFormat format = Qt::DaysAndTime) const;
+
+ bool parts(int *msecondsPtr,
+ int *secondsPtr = 0,
+ int *minutesPtr = 0,
+ int *hoursPtr = 0,
+ int *daysPtr = 0,
+ int *weeksPtr = 0,
+ int *monthsPtr = 0,
+ int *yearsPtr = 0,
+ qreal *fractionalSmallestUnit = 0) const;
+
+ Qt::TimeSpanUnit magnitude();
+
+ inline void setMSecsPart(int msecs, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Milliseconds, msecs, format);}
+ inline void setSecsPart(int seconds, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Seconds, seconds, format);}
+ inline void setMinutesPart(int minutes, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Minutes, minutes, format);}
+ inline void setHoursPart(int hours, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Hours, hours, format);}
+ inline void setDaysPart(int days, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Days, days, format);}
+ inline void setWeeksPart(int weeks, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Weeks, weeks, format);}
+ inline void setMonthsPart(int months, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Months, months, format);}
+ inline void setYearsPart(int years, Qt::TimeSpanFormat format = Qt::DaysAndTime) {setPart(Qt::Years, years, format);}
+ void setPart(Qt::TimeSpanUnit unit, int interval, Qt::TimeSpanFormat format = Qt::DaysAndTime);
+
+ // This set of functions operator on the entire timespan and not
+ // just a single component of it.
+ qint64 toMSecs() const;
+ inline qreal toSecs() const {return toTimeUnit(Qt::Seconds);}
+ inline qreal toMinutes() const {return toTimeUnit(Qt::Minutes);}
+ inline qreal toHours() const {return toTimeUnit(Qt::Hours);}
+ inline qreal toDays() const {return toTimeUnit(Qt::Days);}
+ inline qreal toWeeks() const {return toTimeUnit(Qt::Weeks);}
+ inline qreal toMonths() const {return toTimeUnit(Qt::Seconds);}
+ inline qreal toYears() const {return toTimeUnit(Qt::Seconds);}
+ qreal toTimeUnit(Qt::TimeSpanUnit unit) const;
+
+ void setFromMSecs(qint64 msecs);
+ inline void setFromSecs(qreal secs) {setFromTimeUnit(Qt::Seconds, secs);}
+ inline void setFromMinutes(qreal minutes) {setFromTimeUnit(Qt::Minutes, minutes);}
+ inline void setFromHours(qreal hours) {setFromTimeUnit(Qt::Hours, hours);}
+ inline void setFromDays(qreal days) {setFromTimeUnit(Qt::Days, days);}
+ inline void setFromWeeks(qreal weeks) {setFromTimeUnit(Qt::Weeks, weeks);}
+ void setFromMonths(qreal months);
+ void setFromYears(qreal years);
+ void setFromTimeUnit(Qt::TimeSpanUnit unit, qreal interval);
+
+ // Reference date
+ bool hasValidReference() const;
+ QDateTime referenceDate() const;
+ void setReferenceDate(const QDateTime &referenceDate);
+ void moveReferenceDate(const QDateTime &referenceDate);
+ void setReferencedDate(const QDateTime &referencedDate);
+ void moveReferencedDate(const QDateTime &referencedDate);
+
+ // Referenced date - referenceDate() + *this
+ QDateTime referencedDate() const;
+
+ // Pretty printing
+#ifndef QT_NO_DATESTRING
+ QString toString(const QString &format) const;
+ QString toApproximateString(int suppresSecondUnitLimit = 3,
+ Qt::TimeSpanFormat format = Qt::Seconds | Qt::Minutes | Qt::Hours | Qt::Days | Qt::Weeks);
+#endif
+
+ // Assignment operator
+ QTimeSpan &operator=(const QTimeSpan& other);
+
+ // Comparison operators
+ bool operator==(const QTimeSpan &other) const;
+ inline bool operator!=(const QTimeSpan &other) const {return !(operator==(other));}
+ bool operator<(const QTimeSpan &other) const;
+ bool operator<=(const QTimeSpan &other) const;
+ inline bool operator>(const QTimeSpan &other) const {return !(operator<=(other));}
+ inline bool operator>=(const QTimeSpan &other) const {return !(operator<(other));}
+ bool matchesLength(const QTimeSpan &other, bool normalize = false) const;
+
+ // Arithmetic operators. Operators that don't change *this are declared as non-members.
+ QTimeSpan &operator+=(const QTimeSpan &other);
+ QTimeSpan &operator+=(qint64 msecs);
+ QTimeSpan &operator-=(const QTimeSpan &other);
+ QTimeSpan &operator-=(qint64 msecs);
+ QTimeSpan &operator*=(qreal factor);
+ QTimeSpan &operator*=(int factor);
+ QTimeSpan &operator/=(qreal factor);
+ QTimeSpan &operator/=(int factor);
+ QTimeSpan &operator|=(const QTimeSpan &other); // Union
+ QTimeSpan &operator&=(const QTimeSpan &other); // Intersection
+
+ // Ensure the reference date is before the referenced date
+ QTimeSpan normalized() const;
+ void normalize();
+ QTimeSpan abs() const;
+ bool isNegative() const;
+ bool isNormal() const {return !isNegative();}
+
+ // Naturally ordered dates
+ QDateTime startDate() const;
+ QDateTime endDate() const;
+
+ // Containment
+ bool contains(const QDateTime &dateTime) const;
+ bool contains(const QDate &date) const;
+ bool contains(const QTime &time) const;
+ bool contains(const QTimeSpan &other) const;
+
+ bool overlaps(const QTimeSpan &other) const;
+ QTimeSpan overlapped(const QTimeSpan &other) const;
+ QTimeSpan united(const QTimeSpan &other) const;
+
+ // Static construction methods
+#ifndef QT_NO_DATESTRING
+ static QTimeSpan fromString(const QString &string, const QString &format, const QDateTime& reference = QDateTime());
+ static QTimeSpan fromString(const QString &string, const QRegExp &pattern, const QDateTime& reference,
+ Qt::TimeSpanUnit unit1,
+ Qt::TimeSpanUnit unit2 = Qt::NoUnit, Qt::TimeSpanUnit unit3 = Qt::NoUnit,
+ Qt::TimeSpanUnit unit4 = Qt::NoUnit, Qt::TimeSpanUnit unit5 = Qt::NoUnit,
+ Qt::TimeSpanUnit unit6 = Qt::NoUnit, Qt::TimeSpanUnit unit7 = Qt::NoUnit,
+ Qt::TimeSpanUnit unit8 = Qt::NoUnit);
+#endif
+ //static QTimeSpan fromString(const QString &string, Qt::TimeSpanFormat format);
+ static QTimeSpan fromTimeUnit(Qt::TimeSpanUnit unit, qreal interval, const QDateTime& reference = QDateTime());
+ /*
+ static QTimeSpan fromMSecs(qint64 msecs);
+ static QTimeSpan fromSecs(qreal secs) {return QTimeSpan::Second * secs;}
+ static QTimeSpan fromMinutes(qreal minutes) {return QTimeSpan::Minute * minutes;}
+ static QTimeSpan fromHours(qreal hours) {return QTimeSpan::Hour * hours;}
+ static QTimeSpan fromDays(qreal days) {return QTimeSpan::Day * days;}
+ static QTimeSpan fromWeeks(qreal weeks) {return QTimeSpan::Week * weeks;}
+ */
+
+private:
+#ifndef QT_NO_DATASTREAM
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTimeSpan &);
+ friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTimeSpan &);
+#endif
+
+ QSharedDataPointer d;
+};
+Q_DECLARE_TYPEINFO(QTimeSpan, Q_MOVABLE_TYPE);
+Q_DECLARE_METATYPE(QTimeSpan);
+Q_DECLARE_METATYPE(Qt::TimeSpanUnit);
+
+//non-member operators
+Q_CORE_EXPORT QTimeSpan operator+(const QTimeSpan &left, const QTimeSpan &right);
+Q_CORE_EXPORT QTimeSpan operator-(const QTimeSpan &left, const QTimeSpan &right);
+Q_CORE_EXPORT QTimeSpan operator*(const QTimeSpan &left, qreal right);//no problem
+Q_CORE_EXPORT QTimeSpan operator*(const QTimeSpan &left, int right);//no problem
+inline QTimeSpan operator*(qreal left, const QTimeSpan &right) {return right * left;} // works
+inline QTimeSpan operator*(int left, const QTimeSpan &right) {return right * left;} // works
+//Q_CORE_EXPORT QTimeSpan operator*(qreal left, const QTimeSpan &right) {return right * left;} //does not work
+//Q_CORE_EXPORT QTimeSpan operator*(int left, const QTimeSpan &right) {return right * left;} //does not work
+Q_CORE_EXPORT QTimeSpan operator/(const QTimeSpan &left, qreal right);
+Q_CORE_EXPORT QTimeSpan operator/(const QTimeSpan &left, int right);
+Q_CORE_EXPORT qreal operator/(const QTimeSpan &left, const QTimeSpan &right);
+Q_CORE_EXPORT QTimeSpan operator-(const QTimeSpan &right); // Unary negation
+Q_CORE_EXPORT QTimeSpan operator|(const QTimeSpan &left, const QTimeSpan &right); // Union
+Q_CORE_EXPORT QTimeSpan operator&(const QTimeSpan &left, const QTimeSpan &right); // Intersection
+
+// Operators that use QTimeSpan and other date/time classes
+Q_CORE_EXPORT QTimeSpan operator-(const QDateTime &left, const QDateTime &right);
+Q_CORE_EXPORT QTimeSpan operator-(const QDate &left, const QDate &right);
+Q_CORE_EXPORT QTimeSpan operator-(const QTime &left, const QTime &right);
+Q_CORE_EXPORT QDate operator+(const QDate &left, const QTimeSpan &right);
+Q_CORE_EXPORT QDate operator-(const QDate &left, const QTimeSpan &right);
+Q_CORE_EXPORT QTime operator+(const QTime &left, const QTimeSpan &right);
+Q_CORE_EXPORT QTime operator-(const QTime &left, const QTimeSpan &right);
+Q_CORE_EXPORT QDateTime operator+(const QDateTime &left, const QTimeSpan &right);
+Q_CORE_EXPORT QDateTime operator-(const QDateTime &left, const QTimeSpan &right);
+
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTimeSpan &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTimeSpan &);
+#endif // QT_NO_DATASTREAM
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QTimeSpan &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTIMESPAN_H