From 18332d15b5e2aaa15c8edc36be138429cfdce350 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 16 Sep 2016 16:10:19 +0200 Subject: [PATCH] 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 --- src/libs/timeline/timeline.pro | 7 +- src/libs/timeline/timeline.qbs | 1 + src/libs/timeline/timelineformattime.cpp | 103 ++++++++++++++++++ src/libs/timeline/timelineformattime.h | 34 ++++++ .../qmlprofiler/debugmessagesmodel.cpp | 3 +- src/plugins/qmlprofiler/inputeventsmodel.cpp | 4 +- src/plugins/qmlprofiler/pixmapcachemodel.cpp | 4 +- .../qmlprofileranimationsmodel.cpp | 3 +- .../qmlprofiler/qmlprofilerdatamodel.cpp | 10 -- .../qmlprofiler/qmlprofilerdatamodel.h | 2 - .../qmlprofiler/qmlprofilerrangemodel.cpp | 3 +- .../qmlprofiler/qmlprofilerstatisticsview.cpp | 15 +-- .../qmlprofiler/scenegraphtimelinemodel.cpp | 4 +- .../tests/debugmessagesmodel_test.cpp | 5 +- .../tests/inputeventsmodel_test.cpp | 4 +- .../tests/pixmapcachemodel_test.cpp | 3 +- .../tests/qmlprofileranimationsmodel_test.cpp | 3 +- 17 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 src/libs/timeline/timelineformattime.cpp create mode 100644 src/libs/timeline/timelineformattime.h diff --git a/src/libs/timeline/timeline.pro b/src/libs/timeline/timeline.pro index 4e254534d6..c40b9dc36e 100644 --- a/src/libs/timeline/timeline.pro +++ b/src/libs/timeline/timeline.pro @@ -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 diff --git a/src/libs/timeline/timeline.qbs b/src/libs/timeline/timeline.qbs index 21f9c12770..1fc250a8a9 100644 --- a/src/libs/timeline/timeline.qbs +++ b/src/libs/timeline/timeline.qbs @@ -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", diff --git a/src/libs/timeline/timelineformattime.cpp b/src/libs/timeline/timelineformattime.cpp new file mode 100644 index 0000000000..f365319319 --- /dev/null +++ b/src/libs/timeline/timelineformattime.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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)); + } + + } + } +} + +} diff --git a/src/libs/timeline/timelineformattime.h b/src/libs/timeline/timelineformattime.h new file mode 100644 index 0000000000..9e9f2367dd --- /dev/null +++ b/src/libs/timeline/timelineformattime.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** 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 +#include + +namespace Timeline { +QString TIMELINE_EXPORT formatTime(qint64 timestamp, + qint64 reference = std::numeric_limits::max()); +} diff --git a/src/plugins/qmlprofiler/debugmessagesmodel.cpp b/src/plugins/qmlprofiler/debugmessagesmodel.cpp index 87e55ef51f..c9395d7377 100644 --- a/src/plugins/qmlprofiler/debugmessagesmodel.cpp +++ b/src/plugins/qmlprofiler/debugmessagesmodel.cpp @@ -25,6 +25,7 @@ #include "debugmessagesmodel.h" #include "qmlprofilerconstants.h" +#include 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; diff --git a/src/plugins/qmlprofiler/inputeventsmodel.cpp b/src/plugins/qmlprofiler/inputeventsmodel.cpp index f31d19d0ce..9b50aa0cec 100644 --- a/src/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/src/plugins/qmlprofiler/inputeventsmodel.cpp @@ -27,6 +27,8 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilereventtypes.h" +#include + #include #include #include @@ -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) { diff --git a/src/plugins/qmlprofiler/pixmapcachemodel.cpp b/src/plugins/qmlprofiler/pixmapcachemodel.cpp index 01770c579b..703f4bf192 100644 --- a/src/plugins/qmlprofiler/pixmapcachemodel.cpp +++ b/src/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -27,6 +27,8 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilereventtypes.h" +#include + 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)); diff --git a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp index 97cee62797..c607d63b3c 100644 --- a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp @@ -28,6 +28,7 @@ #include "qmlprofilerdatamodel.h" #include +#include #include #include @@ -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") : diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp index 52a17f7416..a036a20738 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp @@ -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) diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h index 4698dac409..b2802ee7fa 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h @@ -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(); diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp index bb060d1bc0..89517632a0 100644 --- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp @@ -31,6 +31,7 @@ #include "timeline/timelinenotesrenderpass.h" #include "timeline/timelineitemsrenderpass.h" #include "timeline/timelineselectionrenderpass.h" +#include "timeline/timelineformattime.h" #include #include @@ -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()); diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp index 1ea16445e3..bf9865558b 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -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") : diff --git a/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp index 8ffb3f8290..18342e7b6b 100644 --- a/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp +++ b/src/plugins/qmlprofiler/scenegraphtimelinemodel.cpp @@ -27,6 +27,8 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilereventtypes.h" +#include + #include #include @@ -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) diff --git a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp index 7be5f04ff1..83ad6cf478 100644 --- a/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/debugmessagesmodel_test.cpp @@ -24,6 +24,9 @@ ****************************************************************************/ #include "debugmessagesmodel_test.h" + +#include + #include 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(), diff --git a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp index c67856bc03..2ae3d6957d 100644 --- a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp @@ -25,6 +25,8 @@ #include "inputeventsmodel_test.h" #include "timeline/timelinemodel_p.h" +#include "timeline/timelineformattime.h" + #include 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(i % MaximumInputEventType)) { diff --git a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp index 069de0cca1..cc7beb7ec6 100644 --- a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "pixmapcachemodel_test.h" +#include #include 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; diff --git a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp index ee90b4fc26..67ecda8c84 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "qmlprofileranimationsmodel_test.h" +#include #include 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(), -- GitLab