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")); }