Commit 18332d15 authored by Ulf Hermann's avatar Ulf Hermann

Timeline: Move printTime() into Timeline and add hours, minutes, nanos

We should use it for all time printing instead of duplicating the code
everywhere.

Change-Id: I530baa31fd7044aefce6201fec0ab27c99a61a1d
Reviewed-by: Christian Kandeler's avatarChristian Kandeler <christian.kandeler@qt.io>
parent c2b89ae3
......@@ -16,8 +16,8 @@ SOURCES += \
$$PWD/timelinenotesmodel.cpp \
$$PWD/timelineabstractrenderer.cpp \
$$PWD/timelineoverviewrenderer.cpp \
$$PWD/timelinetheme.cpp
$$PWD/timelinetheme.cpp \
$$PWD/timelineformattime.cpp
HEADERS += \
$$PWD/timeline_global.h \
......@@ -39,7 +39,8 @@ HEADERS += \
$$PWD/timelineabstractrenderer_p.h \
$$PWD/timelineoverviewrenderer_p.h \
$$PWD/timelineoverviewrenderer.h \
$$PWD/timelinetheme.h
$$PWD/timelinetheme.h \
$$PWD/timelineformattime.h
RESOURCES += \
$$PWD/qml/timeline.qrc
......
......@@ -17,6 +17,7 @@ Project {
"README",
"timelineabstractrenderer.cpp", "timelineabstractrenderer.h",
"timelineabstractrenderer_p.h",
"timelineformattime.cpp", "timelineformattime.h",
"timelineitemsrenderpass.cpp", "timelineitemsrenderpass.h",
"timelinemodel.cpp", "timelinemodel.h", "timelinemodel_p.h",
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
......
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "timelineformattime.h"
namespace Timeline {
QString formatTime(qint64 timestamp, qint64 reference)
{
static const char *decimalUnits[] = {"ns", "\xb5s", "ms", "s"};
static const double second = 1e9;
static const double minute = 60;
static const double hour = 60;
int round = 0;
int barrier = 1;
auto roundTo3 = [](double time, int round) {
// always show at least 3 significant digits
if (time < 10 && round < 2)
return 2;
else if (time < 100 && round < 1)
return 1;
else
return round;
};
for (uint i = 0, end = sizeof(decimalUnits) / sizeof(char *); i < end; ++i) {
const double dividend = barrier;
if (reference < barrier) {
round += 3;
barrier *= 1000;
} else {
barrier *= 10;
if (reference < barrier) {
round += 2;
barrier *= 100;
} else {
barrier *= 10;
if (reference < barrier)
round += 1;
barrier *= 10;
}
}
if (timestamp < barrier) {
double time = timestamp;
if (dividend > 1) {
time /= dividend;
round = roundTo3(time, round);
}
return QString::number(time, 'f', round)
+ QString::fromLatin1(decimalUnits[i]);
}
}
double seconds = timestamp / second;
if (seconds < minute) {
return QString::number(seconds, 'f', roundTo3(seconds, round)) + "s";
} else {
int minutes = seconds / minute;
seconds -= minutes * minute;
if (minutes < hour) {
return QString::fromLatin1("%1m %2s").arg(QString::number(minutes),
QString::number(seconds, 'f', round));
} else {
int hours = minutes / hour;
hours -= hours * hour;
if (reference < barrier * minute) {
return QString::fromLatin1("%1h %2m %3s").arg(QString::number(hours),
QString::number(minutes),
QString::number(seconds, 'f', round));
} else {
return QString::fromLatin1("%1h %2m").arg(QString::number(hours),
QString::number(minutes));
}
}
}
}
}
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "timeline_global.h"
#include <QString>
#include <limits>
namespace Timeline {
QString TIMELINE_EXPORT formatTime(qint64 timestamp,
qint64 reference = std::numeric_limits<qint64>::max());
}
......@@ -25,6 +25,7 @@
#include "debugmessagesmodel.h"
#include "qmlprofilerconstants.h"
#include <timeline/timelineformattime.h>
namespace QmlProfiler {
namespace Internal {
......@@ -78,7 +79,7 @@ QVariantMap DebugMessagesModel::details(int index) const
QVariantMap result;
result.insert(QLatin1String("displayName"), messageType(type.detailType()));
result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index)));
result.insert(tr("Timestamp"), Timeline::formatTime(startTime(index)));
result.insert(tr("Message"), m_data[index].text);
result.insert(tr("Location"), type.displayName());
return result;
......
......@@ -27,6 +27,8 @@
#include "qmlprofilermodelmanager.h"
#include "qmlprofilereventtypes.h"
#include <timeline/timelineformattime.h>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QMetaEnum>
......@@ -75,7 +77,7 @@ QMetaEnum InputEventsModel::metaEnum(const char *name)
QVariantMap InputEventsModel::details(int index) const
{
QVariantMap result;
result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index)));
result.insert(tr("Timestamp"), Timeline::formatTime(startTime(index)));
QString type;
const InputEvent &event = m_data[index];
switch (event.type) {
......
......@@ -27,6 +27,8 @@
#include "qmlprofilermodelmanager.h"
#include "qmlprofilereventtypes.h"
#include <timeline/timelineformattime.h>
namespace QmlProfiler {
namespace Internal {
......@@ -119,7 +121,7 @@ QVariantMap PixmapCacheModel::details(int index) const
result.insert(QLatin1String("displayName"), tr("Image Loaded"));
if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished)
result.insert(tr("Result"), tr("Load Error"));
result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index)));
result.insert(tr("Duration"), Timeline::formatTime(duration(index)));
}
result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize));
......
......@@ -28,6 +28,7 @@
#include "qmlprofilerdatamodel.h"
#include <utils/qtcassert.h>
#include <timeline/timelineformattime.h>
#include <QCoreApplication>
#include <QVector>
......@@ -182,7 +183,7 @@ QVariantMap QmlProfilerAnimationsModel::details(int index) const
QVariantMap result;
result.insert(QStringLiteral("displayName"), displayName());
result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index)));
result.insert(tr("Duration"), Timeline::formatTime(duration(index)));
result.insert(tr("Framerate"), QString::fromLatin1("%1 FPS").arg(m_data[index].framerate));
result.insert(tr("Animations"), QString::number(m_data[index].animationcount));
result.insert(tr("Context"), selectionId(index) == GuiThread ? tr("GUI Thread") :
......
......@@ -92,16 +92,6 @@ QString getInitialDetails(const QmlEventType &event)
return details;
}
QString QmlProfilerDataModel::formatTime(qint64 timestamp)
{
if (timestamp < 1e6)
return QString::number(timestamp/1e3f,'f',3) + trUtf8(" \xc2\xb5s");
if (timestamp < 1e9)
return QString::number(timestamp/1e6f,'f',3) + tr(" ms");
return QString::number(timestamp/1e9f,'f',3) + tr(" s");
}
QmlProfilerDataModel::QmlProfilerDataModel(Utils::FileInProjectFinder *fileFinder,
QmlProfilerModelManager *parent) :
QObject(parent), d_ptr(new QmlProfilerDataModelPrivate)
......
......@@ -39,8 +39,6 @@ class QMLPROFILER_EXPORT QmlProfilerDataModel : public QObject
{
Q_OBJECT
public:
static QString formatTime(qint64 timestamp);
explicit QmlProfilerDataModel(Utils::FileInProjectFinder *fileFinder,
QmlProfilerModelManager *parent);
~QmlProfilerDataModel();
......
......@@ -31,6 +31,7 @@
#include "timeline/timelinenotesrenderpass.h"
#include "timeline/timelineitemsrenderpass.h"
#include "timeline/timelineselectionrenderpass.h"
#include "timeline/timelineformattime.h"
#include <QCoreApplication>
#include <QVector>
......@@ -223,7 +224,7 @@ QVariantMap QmlProfilerRangeModel::details(int index) const
result.insert(QStringLiteral("displayName"),
tr(QmlProfilerModelManager::featureName(mainFeature())));
result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index)));
result.insert(tr("Duration"), Timeline::formatTime(duration(index)));
result.insert(tr("Details"), types[id].data());
result.insert(tr("Location"), types[id].displayName());
......
......@@ -29,6 +29,7 @@
#include <coreplugin/minisplitter.h>
#include <utils/qtcassert.h>
#include <timeline/timelineformattime.h>
#include <QUrl>
#include <QHash>
......@@ -573,7 +574,7 @@ void QmlProfilerStatisticsMainView::parseModel()
}
if (d->m_fieldShown[TotalTime]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.duration),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.duration),
stats.duration);
}
......@@ -583,7 +584,7 @@ void QmlProfilerStatisticsMainView::parseModel()
}
if (d->m_fieldShown[SelfTime]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.durationSelf),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.durationSelf),
stats.durationSelf);
}
......@@ -591,22 +592,22 @@ void QmlProfilerStatisticsMainView::parseModel()
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
if (d->m_fieldShown[TimePerCall]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.timePerCall),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.timePerCall),
stats.timePerCall);
}
if (d->m_fieldShown[MedianTime]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.medianTime),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.medianTime),
stats.medianTime);
}
if (d->m_fieldShown[MaxTime]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.maxTime),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.maxTime),
stats.maxTime);
}
if (d->m_fieldShown[MinTime]) {
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.minTime),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.minTime),
stats.minTime);
}
......@@ -848,7 +849,7 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
type.displayName());
const QString typeName = QmlProfilerStatisticsMainView::nameForType(type.rangeType());
newRow << new StatisticsViewItem(typeName, typeName);
newRow << new StatisticsViewItem(QmlProfilerDataModel::formatTime(stats.duration),
newRow << new StatisticsViewItem(Timeline::formatTime(stats.duration),
stats.duration);
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available") :
......
......@@ -27,6 +27,8 @@
#include "qmlprofilermodelmanager.h"
#include "qmlprofilereventtypes.h"
#include <timeline/timelineformattime.h>
#include <QCoreApplication>
#include <QDebug>
......@@ -122,7 +124,7 @@ QVariantMap SceneGraphTimelineModel::details(int index) const
result.insert(QLatin1String("displayName"), tr(threadLabel(stage)));
result.insert(tr("Stage"), tr(StageLabels[stage]));
result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index)));
result.insert(tr("Duration"), Timeline::formatTime(duration(index)));
const int glyphCount = m_data[index].glyphCount;
if (glyphCount >= 0)
......
......@@ -24,6 +24,9 @@
****************************************************************************/
#include "debugmessagesmodel_test.h"
#include <timeline/timelineformattime.h>
#include <QtTest>
namespace QmlProfiler {
......@@ -93,7 +96,7 @@ void DebugMessagesModelTest::testDetails()
QCOMPARE(details.value(QLatin1String("displayName")).toString(),
model.tr(messageTypes[i % (QtMsgType::QtInfoMsg + 1)]));
QCOMPARE(details.value(model.tr("Timestamp")).toString(),
QmlProfilerDataModel::formatTime(i));
Timeline::formatTime(i));
QCOMPARE(details.value(model.tr("Message")).toString(),
QString::fromLatin1("message %1").arg(i));
QCOMPARE(details.value(model.tr("Location")).toString(),
......
......@@ -25,6 +25,8 @@
#include "inputeventsmodel_test.h"
#include "timeline/timelinemodel_p.h"
#include "timeline/timelineformattime.h"
#include <QtTest>
namespace QmlProfiler {
......@@ -105,7 +107,7 @@ void InputEventsModelTest::testDetails()
{
for (int i = 0; i < 10; ++i) {
const QVariantMap details = model.details(i);
QCOMPARE(details[model.tr("Timestamp")].toString(), QmlProfilerDataModel::formatTime(i));
QCOMPARE(details[model.tr("Timestamp")].toString(), Timeline::formatTime(i));
QString displayName = details[QString("displayName")].toString();
QVERIFY(!displayName.isEmpty());
switch (static_cast<InputEventType>(i % MaximumInputEventType)) {
......
......@@ -24,6 +24,7 @@
****************************************************************************/
#include "pixmapcachemodel_test.h"
#include <timeline/timelineformattime.h>
#include <QtTest>
namespace QmlProfiler {
......@@ -248,7 +249,7 @@ void PixmapCacheModelTest::testConsistency()
QVERIFY(expandedRow < model.expandedRowCount());
QVERIFY(details[QLatin1String("displayName")].toString() == model.tr("Image Loaded"));
QCOMPARE(details[model.tr("Duration")].toString(),
QmlProfilerDataModel::formatTime(model.duration(i)));
Timeline::formatTime(model.duration(i)));
// In expanded view pixmaps of the same URL but different sizes are allowed to overlap.
// It looks bad, but that should be a rare thing.
break;
......
......@@ -24,6 +24,7 @@
****************************************************************************/
#include "qmlprofileranimationsmodel_test.h"
#include <timeline/timelineformattime.h>
#include <QtTest>
namespace QmlProfiler {
......@@ -127,7 +128,7 @@ void QmlProfilerAnimationsModelTest::testDetails()
QVariantMap details = model.details(i);
QCOMPARE(details["displayName"].toString(), model.displayName());
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Duration")].toString(),
QmlProfilerDataModel::formatTime(1));
Timeline::formatTime(1));
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Framerate")].toString(),
QString::fromLatin1("%1 FPS").arg(frameRate(i)));
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Animations")].toString(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment