diff --git a/src/libs/tracing/flamegraph.h b/src/libs/tracing/flamegraph.h
index a01c44ea39e..666e1e7143a 100644
--- a/src/libs/tracing/flamegraph.h
+++ b/src/libs/tracing/flamegraph.h
@@ -94,6 +94,11 @@ public:
setRoot(QModelIndex());
}
+ Q_INVOKABLE QVariant total(int role) const
+ {
+ return m_model ? m_model->data(m_root, role) : QVariant();
+ }
+
static FlameGraphAttached *qmlAttachedProperties(QObject *object);
signals:
diff --git a/src/libs/tracing/qml/FlameGraphView.qml b/src/libs/tracing/qml/FlameGraphView.qml
new file mode 100644
index 00000000000..53c2edf9da7
--- /dev/null
+++ b/src/libs/tracing/qml/FlameGraphView.qml
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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.
+**
+****************************************************************************/
+
+import FlameGraph 1.0
+import TimelineTheme 1.0
+
+import QtQml 2.2
+import QtQuick 2.9
+import QtQuick.Controls 1.3
+
+ScrollView {
+ id: root
+ property int selectedTypeId: -1
+ property int sizeRole: -1
+ property var model: null
+
+ property int typeIdRole: -1
+ property int sourceFileRole: -1
+ property int sourceLineRole: -1
+ property int sourceColumnRole: -1
+ property int detailsTitleRole: -1
+ property int summaryRole: -1
+ property int noteRole: -1
+
+ property var trRoleNames: []
+
+ property var modes: []
+
+ property var details: function(flameGraph) { return []; }
+ property var summary: function(attached) {
+ if (!attached.dataValid)
+ return qsTr("others");
+
+ return attached.data(summaryRole) + " (" + percent(sizeRole, attached) + "%)";
+ }
+
+ property var isHighlighted: function(node) {
+ return false;
+ }
+
+ function percent(role, attached) {
+ return Math.round(attached.data(role) / flamegraph.total(role) * 1000) / 10;
+ }
+
+ function toMap(previousValue, currentValue, currentIndex, array) {
+ if (currentIndex % 2 === 1)
+ previousValue[array[currentIndex - 1]] = array[currentIndex];
+ return previousValue;
+ }
+
+ function addDetail(role, format, model, attached) {
+ model.push(trRoleNames[role]);
+ model.push(format(role, attached)
+ + (modes.indexOf(role) >= 0 ? " (" + percent(role, attached) + "%)" : ""));
+ }
+
+ property var detailFormats: {
+ "noop": function(role, flameGraph) {
+ return flameGraph.data(role);
+ },
+ "addLine": function(role, flameGraph) {
+ var result = flameGraph.data(role);
+ var line = flameGraph.data(root.sourceLineRole);
+ return line > 0 ? result + ":" + line : result;
+ },
+ "printTime": function(role, flameGraph) {
+ var time = flameGraph.data(role);
+ if (time <= 0)
+ return "0";
+ if (time < 1000)
+ return time + " ns";
+ time = Math.floor(time / 1000);
+ if (time < 1000)
+ return time + " μs";
+ if (time < 1e6)
+ return (time / 1000) + " ms";
+ return (time / 1e6) + " s";
+ },
+ "printMemory": function(role, flameGraph) {
+ var bytes = flameGraph.data(role);
+ if (bytes === 0)
+ return "0b";
+
+ var units = ["b", "kb", "Mb", "Gb"];
+ var div = 1;
+ for (var i = 0; i < units.length; ++i, div *= 1024) {
+ if (bytes > div * 1024)
+ continue;
+
+ bytes /= div;
+ var digitsAfterDot = Math.round(3 - Math.log(bytes) / Math.LN10);
+ var multiplier = Math.pow(10, digitsAfterDot);
+ return Math.round(bytes * multiplier) / multiplier + units[i];
+ }
+ }
+ }
+
+ onSelectedTypeIdChanged: tooltip.hoveredNode = null
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ tooltip.selectedNode = null;
+ if (model !== null)
+ model.typeSelected(-1);
+ }
+ onDoubleClicked: {
+ tooltip.selectedNode = null;
+ if (model !== null)
+ model.typeSelected(-1);
+ flamegraph.resetRoot();
+ }
+ }
+
+ Flickable {
+ id: flickable
+ contentHeight: flamegraph.height
+ boundsBehavior: Flickable.StopAtBounds
+
+ FlameGraph {
+ property int delegateHeight: Math.min(60, Math.max(30, flickable.height / depth))
+ property color blue: "blue"
+ property color blue1: Qt.lighter(blue)
+ property color blue2: Qt.rgba(0.375, 0, 1, 1)
+ property color grey1: "#B0B0B0"
+ property color highlight: Theme.color(Theme.Timeline_HighlightColor)
+
+ id: flamegraph
+ width: parent.width
+ height: Math.max(depth * delegateHeight, flickable.height)
+ model: root.model
+ sizeRole: root.sizeRole
+ sizeThreshold: 0.002
+ maximumDepth: 128
+ y: flickable.height > height ? flickable.height - height : 0
+
+ delegate: FlameGraphDelegate {
+ id: flamegraphItem
+
+ property var typeId: FlameGraph.data(root.typeIdRole) || -1
+ property bool isHighlighted: root.isHighlighted(flamegraphItem)
+
+ itemHeight: flamegraph.delegateHeight
+ isSelected: typeId !== -1 && typeId === root.selectedTypeId
+
+ borderColor: {
+ if (isSelected)
+ return flamegraph.blue2;
+ else if (tooltip.hoveredNode === flamegraphItem)
+ return flamegraph.blue1;
+ else if (note() !== "" || isHighlighted)
+ return flamegraph.highlight;
+ else
+ return flamegraph.grey1;
+ }
+ borderWidth: {
+ if (tooltip.hoveredNode === flamegraphItem ||
+ tooltip.selectedNode === flamegraphItem) {
+ return 2;
+ } else if (note() !== "" || isHighlighted) {
+ return 3;
+ } else {
+ return 1;
+ }
+ }
+
+ onIsSelectedChanged: {
+ if (isSelected && (tooltip.selectedNode === null ||
+ tooltip.selectedNode.typeId !== root.selectedTypeId)) {
+ tooltip.selectedNode = flamegraphItem;
+ } else if (!isSelected && tooltip.selectedNode === flamegraphItem) {
+ tooltip.selectedNode = null;
+ }
+ }
+
+ text: textVisible ? root.summary(FlameGraph) : ""
+ FlameGraph.onModelIndexChanged: {
+ if (textVisible)
+ text = root.summary(FlameGraph);
+
+ // refresh to trigger reevaluation
+ if (tooltip.selectedNode == flamegraphItem) {
+ var selectedNode = tooltip.selectedNode;
+ tooltip.selectedNode = null;
+ tooltip.selectedNode = selectedNode;
+ }
+ if (tooltip.hoveredNode == flamegraphItem) {
+ var hoveredNode = tooltip.hoveredNode;
+ tooltip.hoveredNode = null;
+ tooltip.hoveredNode = hoveredNode;
+ }
+ }
+
+ onMouseEntered: {
+ tooltip.hoveredNode = flamegraphItem;
+ }
+
+ onMouseExited: {
+ if (tooltip.hoveredNode === flamegraphItem) {
+ // Keep the window around until something else is hovered or selected.
+ if (tooltip.selectedNode === null
+ || tooltip.selectedNode.typeId !== root.selectedTypeId) {
+ tooltip.selectedNode = flamegraphItem;
+ }
+ tooltip.hoveredNode = null;
+ }
+ }
+
+ function selectClicked() {
+ if (FlameGraph.dataValid) {
+ tooltip.selectedNode = flamegraphItem;
+ selectedTypeId = FlameGraph.data(root.typeIdRole);
+ model.typeSelected(selectedTypeId);
+ model.gotoSourceLocation(
+ FlameGraph.data(root.sourceFileRole),
+ FlameGraph.data(root.sourceLineRole),
+ FlameGraph.data(root.sourceColumnRole));
+ }
+ }
+
+ onClicked: selectClicked()
+ onDoubleClicked: {
+ flamegraph.root = FlameGraph.modelIndex;
+ selectClicked();
+ }
+
+ // Functions, not properties to limit the initial overhead when creating the nodes,
+ // and because FlameGraph.data(...) cannot be notified anyway.
+ function title() {
+ return FlameGraph.data(root.detailsTitleRole) || qsTr("unknown");
+ }
+
+ function note() {
+ return FlameGraph.data(root.noteRole) || "";
+ }
+
+ function details() {
+ return root.details(FlameGraph);
+ }
+ }
+ }
+
+ FlameGraphDetails {
+ id: tooltip
+
+ minimumX: 0
+ maximumX: flickable.width
+ minimumY: flickable.contentY
+ maximumY: flickable.contentY + flickable.height
+
+ titleBarColor: Theme.color(Theme.Timeline_PanelHeaderColor)
+ titleBarTextColor: Theme.color(Theme.PanelTextColorLight)
+ contentColor: Theme.color(Theme.Timeline_PanelBackgroundColor)
+ contentTextColor: Theme.color(Theme.Timeline_TextColor)
+ noteTextColor: Theme.color(Theme.Timeline_HighlightColor)
+ buttonHoveredColor: Theme.color(Theme.FancyToolButtonHoverColor)
+ buttonSelectedColor: Theme.color(Theme.FancyToolButtonSelectedColor)
+ borderWidth: 0
+
+ property var hoveredNode: null;
+ property var selectedNode: null;
+
+ property var currentNode: {
+ if (hoveredNode !== null)
+ return hoveredNode;
+ else if (selectedNode !== null)
+ return selectedNode;
+ else
+ return null;
+ }
+
+ onClearSelection: {
+ selectedTypeId = -1;
+ selectedNode = null;
+ root.model.typeSelected(-1);
+ }
+
+ dialogTitle: {
+ if (currentNode)
+ return currentNode.title();
+ else if (root.model === null || root.model.rowCount() === 0)
+ return qsTr("No data available");
+ else
+ return "";
+ }
+
+ model: currentNode ? currentNode.details() : []
+ note: currentNode ? currentNode.note() : ""
+
+ Connections {
+ target: root.model
+ onModelReset: {
+ tooltip.hoveredNode = null;
+ tooltip.selectedNode = null;
+ }
+ }
+ }
+
+ Button {
+ x: flickable.width - width
+ y: flickable.contentY
+
+ // It won't listen to anchors.margins and by default it doesn't add any margin. Great.
+ width: implicitWidth + 20
+
+ text: qsTr("Visualize %1").arg(trRoleNames[root.sizeRole])
+
+ menu: Menu {
+ id: modesMenu
+ Instantiator {
+ model: root.modes
+ MenuItem {
+ text: root.trRoleNames[modelData]
+ onTriggered: root.sizeRole = modelData
+ }
+ onObjectAdded: modesMenu.insertItem(index, object)
+ onObjectRemoved: modesMenu.removeItem(object)
+ }
+ }
+ }
+ }
+}
diff --git a/src/libs/tracing/qml/tracing.qrc b/src/libs/tracing/qml/tracing.qrc
index c59a7ab93ae..a76ad2609ab 100644
--- a/src/libs/tracing/qml/tracing.qrc
+++ b/src/libs/tracing/qml/tracing.qrc
@@ -6,6 +6,7 @@
FlameGraphDelegate.qml
FlameGraphDetails.qml
FlameGraphText.qml
+ FlameGraphView.qml
ico_edit.png
ico_edit@2x.png
ico_rangeselected.png
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp
index 4c62be82e68..9621cf9bf24 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.cpp
+++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp
@@ -208,7 +208,6 @@ QVariant FlameGraphModel::lookup(const FlameGraphData &stats, int role) const
case DurationRole: return stats.duration;
case CallCountRole: return stats.calls;
case TimePerCallRole: return stats.duration / stats.calls;
- case TimeInPercentRole: return stats.duration * 100 / m_stackBottom.duration;
case AllocationsRole: return stats.allocations;
case MemoryRole: return stats.memory;
default: break;
@@ -321,7 +320,6 @@ QHash FlameGraphModel::roleNames() const
{ColumnRole, "column"},
{NoteRole, "note"},
{TimePerCallRole, "timePerCall"},
- {TimeInPercentRole, "timeInPercent"},
{RangeTypeRole, "rangeType"},
{LocationRole, "location" },
{AllocationsRole, "allocations" },
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.h b/src/plugins/qmlprofiler/flamegraphmodel.h
index a3aa58b1881..c1984ffc437 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.h
+++ b/src/plugins/qmlprofiler/flamegraphmodel.h
@@ -68,7 +68,6 @@ public:
ColumnRole,
NoteRole,
TimePerCallRole,
- TimeInPercentRole,
RangeTypeRole,
LocationRole,
AllocationsRole,
diff --git a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
index eb6a43ab3f8..a734b011a20 100644
--- a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
+++ b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
@@ -23,20 +23,30 @@
**
****************************************************************************/
-import QtQuick 2.0
-import QtQuick.Controls 1.3
-import FlameGraph 1.0
import QmlProfilerFlameGraphModel 1.0
-import TimelineTheme 1.0
import "../tracing/"
-ScrollView {
+FlameGraphView {
id: root
- property int selectedTypeId: -1
- property int sizeRole: QmlProfilerFlameGraphModel.DurationRole
+ model: flameGraphModel
+ sizeRole: QmlProfilerFlameGraphModel.DurationRole
- readonly property var trRoleNames: [
+ typeIdRole: QmlProfilerFlameGraphModel.TypeIdRole
+ sourceFileRole: QmlProfilerFlameGraphModel.FilenameRole
+ sourceLineRole: QmlProfilerFlameGraphModel.LineRole
+ sourceColumnRole: QmlProfilerFlameGraphModel.ColumnRole
+ detailsTitleRole: QmlProfilerFlameGraphModel.TypeRole
+ summaryRole: QmlProfilerFlameGraphModel.DetailsRole
+ noteRole: QmlProfilerFlameGraphModel.NoteRole
+
+ modes: [
+ QmlProfilerFlameGraphModel.DurationRole,
+ QmlProfilerFlameGraphModel.MemoryRole,
+ QmlProfilerFlameGraphModel.AllocationsRole
+ ]
+
+ trRoleNames: [
QmlProfilerFlameGraphModel.DurationRole, qsTr("Total Time"),
QmlProfilerFlameGraphModel.CallCountRole, qsTr("Calls"),
QmlProfilerFlameGraphModel.DetailsRole, qsTr("Details"),
@@ -45,311 +55,47 @@ ScrollView {
QmlProfilerFlameGraphModel.LocationRole, qsTr("Location"),
QmlProfilerFlameGraphModel.AllocationsRole, qsTr("Allocations"),
QmlProfilerFlameGraphModel.MemoryRole, qsTr("Memory")
- ].reduce(function(previousValue, currentValue, currentIndex, array) {
- if (currentIndex % 2 === 1)
- previousValue[array[currentIndex - 1]] = array[currentIndex];
- return previousValue;
- }, {})
+ ].reduce(toMap, {})
- onSelectedTypeIdChanged: tooltip.hoveredNode = null
+ details: function(flameGraph) {
+ var model = [];
+ if (!flameGraph.dataValid) {
+ model.push(trRoleNames[QmlProfilerFlameGraphModel.DetailsRole]);
+ model.push(qsTr("Various Events"));
+ } else {
+ function addDetail(role, format) { root.addDetail(role, format, model, flameGraph); }
- Flickable {
- id: flickable
- contentHeight: flamegraph.height
- boundsBehavior: Flickable.StopAtBounds
+ addDetail(QmlProfilerFlameGraphModel.DetailsRole, detailFormats.noop);
+ addDetail(QmlProfilerFlameGraphModel.CallCountRole, detailFormats.noop);
+ addDetail(QmlProfilerFlameGraphModel.DurationRole, detailFormats.printTime);
+ addDetail(QmlProfilerFlameGraphModel.TimePerCallRole, detailFormats.printTime);
+ addDetail(QmlProfilerFlameGraphModel.LocationRole, detailFormats.noop);
+ addDetail(QmlProfilerFlameGraphModel.MemoryRole, detailFormats.printMemory);
+ addDetail(QmlProfilerFlameGraphModel.AllocationsRole, detailFormats.noop);
+ }
+ return model;
+ }
- MouseArea {
- anchors.fill: parent
- onClicked: {
- tooltip.selectedNode = null;
- flameGraphModel.typeSelected(-1);
- }
- onDoubleClicked: {
- tooltip.selectedNode = null;
- flameGraphModel.typeSelected(-1);
- flamegraph.resetRoot();
+ summary: function(attached) {
+ if (!attached.dataValid)
+ return qsTr("others");
+
+ return attached.data(QmlProfilerFlameGraphModel.DetailsRole) + " ("
+ + attached.data(QmlProfilerFlameGraphModel.TypeRole) + ", "
+ + root.percent(root.sizeRole, attached) + "%)";
+ }
+
+ isHighlighted: function(node) {
+ function recurse(parentNode, typeId) {
+ if (!parentNode)
+ return false;
+ if (parentNode.typeId === typeId) {
+ parentNode.isHighlighted = true;
+ return true;
}
+ return recurse(parentNode.parent, typeId);
}
- FlameGraph {
- property int delegateHeight: Math.min(60, Math.max(30, flickable.height / depth))
- property color blue: "blue"
- property color blue1: Qt.lighter(blue)
- property color blue2: Qt.rgba(0.375, 0, 1, 1)
- property color grey1: "#B0B0B0"
- property color grey2: "#A0A0A0"
- property color highlight: Theme.color(Theme.Timeline_HighlightColor)
-
- function checkBindingLoop(otherTypeId) {return false;}
-
- id: flamegraph
- width: parent.width
- height: Math.max(depth * delegateHeight, flickable.height)
- model: flameGraphModel
- sizeRole: root.sizeRole
- sizeThreshold: 0.002
- maximumDepth: 25
- y: flickable.height > height ? flickable.height - height : 0
-
- delegate: FlameGraphDelegate {
- id: flamegraphItem
-
- property int typeId: FlameGraph.data(QmlProfilerFlameGraphModel.TypeIdRole) || -1
- property bool isBindingLoop: parent.checkBindingLoop(typeId)
-
- itemHeight: flamegraph.delegateHeight
- isSelected: typeId !== -1 && typeId === root.selectedTypeId
-
- borderColor: {
- if (isSelected)
- return flamegraph.blue2;
- else if (tooltip.hoveredNode === flamegraphItem)
- return flamegraph.blue1;
- else if (note() !== "" || isBindingLoop)
- return flamegraph.highlight;
- else
- return flamegraph.grey1;
- }
- borderWidth: {
- if (tooltip.hoveredNode === flamegraphItem ||
- tooltip.selectedNode === flamegraphItem) {
- return 2;
- } else if (note() !== "") {
- return 3;
- } else {
- return 1;
- }
- }
-
- onIsSelectedChanged: {
- if (isSelected && (tooltip.selectedNode === null ||
- tooltip.selectedNode.typeId !== root.selectedTypeId)) {
- tooltip.selectedNode = flamegraphItem;
- } else if (!isSelected && tooltip.selectedNode === flamegraphItem) {
- tooltip.selectedNode = null;
- }
- }
-
- function checkBindingLoop(otherTypeId) {
- if (typeId === otherTypeId) {
- isBindingLoop = true;
- return true;
- } else {
- return parent.checkBindingLoop(otherTypeId);
- }
- }
-
- function buildText() {
- if (!FlameGraph.dataValid)
- return "";
-
- return FlameGraph.data(QmlProfilerFlameGraphModel.DetailsRole) + " ("
- + FlameGraph.data(QmlProfilerFlameGraphModel.TypeRole) + ", "
- + Math.floor(width / flamegraph.width * 1000) / 10 + "%)";
- }
- text: textVisible ? buildText() : ""
- FlameGraph.onModelIndexChanged: {
- if (textVisible)
- text = buildText();
-
- // refresh to trigger reevaluation
- if (tooltip.selectedNode == flamegraphItem) {
- var selectedNode = tooltip.selectedNode;
- tooltip.selectedNode = null;
- tooltip.selectedNode = selectedNode;
- }
- if (tooltip.hoveredNode == flamegraphItem) {
- var hoveredNode = tooltip.hoveredNode;
- tooltip.hoveredNode = null;
- tooltip.hoveredNode = hoveredNode;
- }
- }
-
- onMouseEntered: {
- tooltip.hoveredNode = flamegraphItem;
- }
-
- onMouseExited: {
- if (tooltip.hoveredNode === flamegraphItem) {
- // Keep the window around until something else is hovered or selected.
- if (tooltip.selectedNode === null
- || tooltip.selectedNode.typeId !== root.selectedTypeId) {
- tooltip.selectedNode = flamegraphItem;
- }
- tooltip.hoveredNode = null;
- }
- }
-
- function selectClicked() {
- if (flamegraphItem.FlameGraph.dataValid) {
- tooltip.selectedNode = flamegraphItem;
- flameGraphModel.typeSelected(flamegraphItem.FlameGraph.data(
- QmlProfilerFlameGraphModel.TypeIdRole));
- flameGraphModel.gotoSourceLocation(
- flamegraphItem.FlameGraph.data(
- QmlProfilerFlameGraphModel.FilenameRole),
- flamegraphItem.FlameGraph.data(
- QmlProfilerFlameGraphModel.LineRole),
- flamegraphItem.FlameGraph.data(
- QmlProfilerFlameGraphModel.ColumnRole));
- }
- }
-
- onClicked: selectClicked()
- onDoubleClicked: {
- selectClicked();
- flamegraph.root = FlameGraph.modelIndex;
- }
-
- // Functions, not properties to limit the initial overhead when creating the nodes,
- // and because FlameGraph.data(...) cannot be notified anyway.
- function title() { return FlameGraph.data(QmlProfilerFlameGraphModel.TypeRole) || ""; }
- function note() { return FlameGraph.data(QmlProfilerFlameGraphModel.NoteRole) || ""; }
- function details() {
- var model = [];
- function addDetail(index, format) {
- model.push(trRoleNames[index]);
- model.push(format(FlameGraph.data(index)));
- }
-
- function printTime(t)
- {
- if (t <= 0)
- return "0";
- if (t < 1000)
- return t + " ns";
- t = Math.floor(t / 1000);
- if (t < 1000)
- return t + " μs";
- if (t < 1e6)
- return (t / 1000) + " ms";
- return (t / 1e6) + " s";
- }
-
- function noop(a) {
- return a;
- }
-
- function addPercent(a) {
- return a + "%";
- }
-
- function printMemory(a) {
- if (a === 0)
- return "0b";
-
- var units = ["b", "kb", "Mb", "Gb"];
- var div = 1;
- for (var i = 0; i < units.length; ++i, div *= 1024) {
- if (a > div * 1024)
- continue;
-
- a /= div;
- var digitsAfterDot = Math.round(3 - Math.log(a) / Math.LN10);
- var multiplier = Math.pow(10, digitsAfterDot);
- return Math.round(a * multiplier) / multiplier + units[i];
- }
- }
-
- if (!FlameGraph.dataValid) {
- model.push(qsTr("Details"));
- model.push(qsTr("Various Events"));
- } else {
- addDetail(QmlProfilerFlameGraphModel.DetailsRole, noop);
- addDetail(QmlProfilerFlameGraphModel.CallCountRole, noop);
- addDetail(QmlProfilerFlameGraphModel.DurationRole, printTime);
- addDetail(QmlProfilerFlameGraphModel.TimePerCallRole, printTime);
- addDetail(QmlProfilerFlameGraphModel.TimeInPercentRole, addPercent);
- addDetail(QmlProfilerFlameGraphModel.LocationRole, noop);
- addDetail(QmlProfilerFlameGraphModel.MemoryRole, printMemory);
- addDetail(QmlProfilerFlameGraphModel.AllocationsRole, noop);
- }
- return model;
- }
- }
- }
-
- FlameGraphDetails {
- id: tooltip
-
- minimumX: 0
- maximumX: flickable.width
- minimumY: flickable.contentY
- maximumY: flickable.contentY + flickable.height
-
- titleBarColor: Theme.color(Theme.Timeline_PanelHeaderColor)
- titleBarTextColor: Theme.color(Theme.PanelTextColorLight)
- contentColor: Theme.color(Theme.Timeline_PanelBackgroundColor)
- contentTextColor: Theme.color(Theme.Timeline_TextColor)
- noteTextColor: Theme.color(Theme.Timeline_HighlightColor)
- buttonHoveredColor: Theme.color(Theme.FancyToolButtonHoverColor)
- buttonSelectedColor: Theme.color(Theme.FancyToolButtonSelectedColor)
- borderWidth: 0
-
- property var hoveredNode: null;
- property var selectedNode: null;
-
- property var currentNode: {
- if (hoveredNode !== null)
- return hoveredNode;
- else if (selectedNode !== null)
- return selectedNode;
- else
- return null;
- }
-
- onClearSelection: {
- selectedTypeId = -1;
- selectedNode = null;
- flameGraphModel.typeSelected(-1);
- }
-
- dialogTitle: {
- if (currentNode)
- return currentNode.title();
- else if (flameGraphModel.rowCount() === 0)
- return qsTr("No data available");
- else
- return "";
- }
-
- model: currentNode ? currentNode.details() : []
- note: currentNode ? currentNode.note() : ""
-
- Connections {
- target: flameGraphModel
- onModelReset: {
- tooltip.hoveredNode = null;
- tooltip.selectedNode = null;
- }
- }
- }
-
- Button {
- x: flickable.width - width
- y: flickable.contentY
-
- // It won't listen to anchors.margins and by default it doesn't add any margin. Great.
- width: implicitWidth + 20
-
- text: qsTr("Visualize %1").arg(trRoleNames[root.sizeRole])
-
- menu: Menu {
- MenuItem {
- text: trRoleNames[QmlProfilerFlameGraphModel.DurationRole]
- onTriggered: root.sizeRole = QmlProfilerFlameGraphModel.DurationRole
- }
-
- MenuItem {
- text: trRoleNames[QmlProfilerFlameGraphModel.MemoryRole]
- onTriggered: root.sizeRole = QmlProfilerFlameGraphModel.MemoryRole
- }
-
- MenuItem {
- text: trRoleNames[QmlProfilerFlameGraphModel.AllocationsRole]
- onTriggered: root.sizeRole = QmlProfilerFlameGraphModel.AllocationsRole
- }
- }
- }
+ return recurse(node.parent, node.typeId);
}
}
diff --git a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
index f4ba5209661..f393e3ea0a5 100644
--- a/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/flamegraphmodel_test.cpp
@@ -158,8 +158,6 @@ void FlameGraphModelTest::testData()
QCOMPARE(model.data(index2, FlameGraphModel::NoteRole).toString(), QString());
QCOMPARE(model.data(index, FlameGraphModel::TimePerCallRole).toLongLong(), 20);
QCOMPARE(model.data(index2, FlameGraphModel::TimePerCallRole).toLongLong(), 12);
- QCOMPARE(model.data(index, FlameGraphModel::TimeInPercentRole).toInt(), 62);
- QCOMPARE(model.data(index2, FlameGraphModel::TimeInPercentRole).toInt(), 37);
QCOMPARE(model.data(index, FlameGraphModel::RangeTypeRole).toInt(),
static_cast(Javascript));
QCOMPARE(model.data(index2, FlameGraphModel::RangeTypeRole).toInt(),
@@ -201,7 +199,6 @@ void FlameGraphModelTest::testRoleNames()
QCOMPARE(names[FlameGraphModel::ColumnRole], QByteArray("column"));
QCOMPARE(names[FlameGraphModel::NoteRole], QByteArray("note"));
QCOMPARE(names[FlameGraphModel::TimePerCallRole], QByteArray("timePerCall"));
- QCOMPARE(names[FlameGraphModel::TimeInPercentRole], QByteArray("timeInPercent"));
QCOMPARE(names[FlameGraphModel::RangeTypeRole], QByteArray("rangeType"));
}