From 0d695617f1968b8bbaa46c15f892d82807b1ac49 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 23 Jun 2014 12:34:37 +0200 Subject: [PATCH] QmlProfiler: Add scales to rows in timeline If you resize the rows to at least double their default size and if the model specifies a scale it will be drawn as additional horizontal lines and numbers in the background. Change-Id: I02844b4102e043031ee04daa45666dc3f8da1d2e Task-number: QTCREATORBUG-12337 Reviewed-by: Kai Koehne --- .../qmlprofiler/abstracttimelinemodel.cpp | 12 ++++ .../qmlprofiler/abstracttimelinemodel.h | 2 + src/plugins/qmlprofiler/qml/TimeMarks.qml | 58 ++++++++++++++++++- .../qmlprofiler/timelinemodelaggregator.cpp | 10 ++++ .../qmlprofiler/timelinemodelaggregator.h | 2 + 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp index ae5646dfca2..581b1708bb8 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -237,6 +237,18 @@ float AbstractTimelineModel::getHeight(int index) const return 1.0f; } +int AbstractTimelineModel::rowMinValue(int rowNumber) const +{ + Q_UNUSED(rowNumber); + return 0; +} + +int AbstractTimelineModel::rowMaxValue(int rowNumber) const +{ + Q_UNUSED(rowNumber); + return 0; +} + void AbstractTimelineModel::dataChanged() { Q_D(AbstractTimelineModel); diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.h b/src/plugins/qmlprofiler/abstracttimelinemodel.h index ef407afafb9..ea0486970a6 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.h @@ -93,6 +93,8 @@ public: Q_INVOKABLE virtual int getEventIdForLocation(const QString &filename, int line, int column) const; Q_INVOKABLE virtual int getBindingLoopDest(int index) const; Q_INVOKABLE virtual float getHeight(int index) const; + virtual int rowMinValue(int rowNumber) const; + virtual int rowMaxValue(int rowNumber) const; signals: void expandedChanged(); diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index a2e2d49bc2b..d3e9c6f66cc 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -35,6 +35,10 @@ Canvas { objectName: "TimeMarks" contextType: "2d" + readonly property int scaleMinHeight: 60 + readonly property int scaleStepping: 30 + readonly property string units: " kMGT" + property real startTime property real endTime property real timePerPixel @@ -70,8 +74,6 @@ Canvas { var lineStart = y < 0 ? -y : 0; var lineEnd = Math.min(height, labels.height - y); - context.fillStyle = "#000000"; - context.font = "8px sans-serif"; for (var ii = 0; ii < blockCount+1; ii++) { var x = Math.floor(ii*pixelsPerBlock - realStartPos); context.strokeStyle = "#B0B0B0"; @@ -99,9 +101,27 @@ Canvas { } } + function prettyPrintScale(amount) { + var unitOffset = 0; + for (unitOffset = 0; amount > (1 << ((unitOffset + 1) * 10)); ++unitOffset) {} + var result = (amount >> (unitOffset * 10)); + if (result < 100) { + var comma = Math.round(((amount >> ((unitOffset - 1) * 10)) & 1023) * + (result < 10 ? 100 : 10) / 1024); + if (comma < 10 && result < 10) + return result + ".0" + comma + units[unitOffset]; + else + return result + "." + comma + units[unitOffset]; + } else { + return result + units[unitOffset]; + } + } + function drawBackgroundBars( context, region ) { var colorIndex = true; + context.font = "8px sans-serif"; + // separators var cumulatedHeight = y < 0 ? -y : 0; for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); ++modelIndex) { @@ -123,6 +143,40 @@ Canvas { context.strokeStyle = context.fillStyle = colorIndex ? "#f0f0f0" : "white"; context.fillRect(0, cumulatedHeight - rowHeight - y, width, rowHeight); + if (rowHeight >= scaleMinHeight) { + var minVal = qmlProfilerModelProxy.rowMinValue(modelIndex, row); + var maxVal = qmlProfilerModelProxy.rowMaxValue(modelIndex, row); + if (minVal !== maxVal) { + context.strokeStyle = context.fillStyle = "#B0B0B0"; + + var stepValUgly = Math.ceil((maxVal - minVal) / + Math.floor(rowHeight / scaleStepping)); + + // align to clean 2**x + var stepVal = 1; + while (stepValUgly >>= 1) + stepVal <<= 1; + + var stepHeight = rowHeight / (maxVal - minVal); + + for (var step = minVal; step <= maxVal - stepVal; step += stepVal) { + var offset = cumulatedHeight - step * stepHeight - y; + context.beginPath(); + context.moveTo(0, offset); + context.lineTo(width, offset); + context.stroke(); + context.fillText(prettyPrintScale(step), 5, offset - 2); + } + context.beginPath(); + context.moveTo(0, cumulatedHeight - rowHeight - y); + context.lineTo(width, cumulatedHeight - rowHeight - y); + context.stroke(); + context.fillText(prettyPrintScale(maxVal), 5, + cumulatedHeight - rowHeight - y + 8); + + } + } + if (cumulatedHeight > y + height) return; } diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp index cfa33b2af72..b696f7f4959 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -182,6 +182,16 @@ const QString TimelineModelAggregator::title(int modelIndex) const return d->modelList[modelIndex]->title(); } +int TimelineModelAggregator::rowMinValue(int modelIndex, int row) const +{ + return d->modelList[modelIndex]->rowMinValue(row); +} + +int TimelineModelAggregator::rowMaxValue(int modelIndex, int row) const +{ + return d->modelList[modelIndex]->rowMaxValue(row); +} + int TimelineModelAggregator::findFirstIndex(int modelIndex, qint64 startTime) const { return d->modelList[modelIndex]->findFirstIndex(startTime); diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.h b/src/plugins/qmlprofiler/timelinemodelaggregator.h index b2690b53626..60a401b96a6 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.h @@ -70,6 +70,8 @@ public: Q_INVOKABLE void setExpanded(int modelIndex, bool expanded); Q_INVOKABLE int rowCount(int modelIndex) const; Q_INVOKABLE const QString title(int modelIndex) const; + Q_INVOKABLE int rowMinValue(int modelIndex, int row) const; + Q_INVOKABLE int rowMaxValue(int modelIndex, int row) const; int findFirstIndex(int modelIndex, qint64 startTime) const; int findFirstIndexNoParents(int modelIndex, qint64 startTime) const;