diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2016-07-18 11:19:00 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2016-07-20 08:55:28 +0000 |
commit | 392955488c253c99bc67b3eaba991002ba6bbdf2 (patch) | |
tree | ad0408110425e79f136436fd8a57846024f43bf2 | |
parent | 97a465ae18defedaa7ac1fcb4ab3212ece136170 (diff) |
Move flame graph view from QmlProfiler to separate library
We want to use it for other profilers, too.
Change-Id: Ice4bd7fdfce6e0153d62a7c9a83dc7de6d5cba30
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
26 files changed, 413 insertions, 261 deletions
diff --git a/src/plugins/qmlprofiler/flamegraph.cpp b/src/libs/flamegraph/flamegraph.cpp index ff57db5eb5..79627c2dc5 100644 --- a/src/plugins/qmlprofiler/flamegraph.cpp +++ b/src/libs/flamegraph/flamegraph.cpp @@ -25,8 +25,7 @@ #include "flamegraph.h" -namespace QmlProfiler { -namespace Internal { +namespace FlameGraph { FlameGraph::FlameGraph(QQuickItem *parent) : QQuickItem(parent) @@ -180,10 +179,4 @@ void FlameGraph::rebuild() emit depthChanged(m_depth); } -QVariant FlameGraphAttached::data(int role) const -{ - return m_data.isValid() ? m_data.data(role) : QVariant(); -} - -} // namespace Internal -} // namespace QmlProfiler +} // namespace FlameGraph diff --git a/src/plugins/qmlprofiler/flamegraph.h b/src/libs/flamegraph/flamegraph.h index 18550359ba..5fe7f88ca0 100644 --- a/src/plugins/qmlprofiler/flamegraph.h +++ b/src/libs/flamegraph/flamegraph.h @@ -25,82 +25,15 @@ #pragma once +#include "flamegraph_global.h" +#include "flamegraphattached.h" + #include <QQuickItem> #include <QAbstractItemModel> -namespace QmlProfiler { -namespace Internal { - -class FlameGraphAttached : public QObject -{ - Q_OBJECT - Q_PROPERTY(qreal relativeSize READ relativeSize WRITE setRelativeSize - NOTIFY relativeSizeChanged) - Q_PROPERTY(qreal relativePosition READ relativePosition WRITE setRelativePosition - NOTIFY relativePositionChanged) - Q_PROPERTY(bool dataValid READ isDataValid NOTIFY dataValidChanged) - -public: - FlameGraphAttached(QObject *parent = 0) : - QObject(parent), m_relativeSize(0), m_relativePosition(0) {} - - Q_INVOKABLE QVariant data(int role) const; - - bool isDataValid() const - { - return m_data.isValid(); - } - - qreal relativeSize() const - { - return m_relativeSize; - } - - void setRelativeSize(qreal relativeSize) - { - if (relativeSize != m_relativeSize) { - m_relativeSize = relativeSize; - emit relativeSizeChanged(); - } - } - - qreal relativePosition() const - { - return m_relativePosition; - } - - void setRelativePosition(qreal relativePosition) - { - if (relativePosition != m_relativePosition) { - m_relativePosition = relativePosition; - emit relativePositionChanged(); - } - } - - void setModelIndex(const QModelIndex &data) - { - if (data != m_data) { - bool validChanged = (data.isValid() != m_data.isValid()); - m_data = data; - if (validChanged) - emit dataValidChanged(); - emit dataChanged(); - } - } - -signals: - void dataChanged(); - void dataValidChanged(); - void relativeSizeChanged(); - void relativePositionChanged(); - -private: - QPersistentModelIndex m_data; - qreal m_relativeSize; - qreal m_relativePosition; -}; +namespace FlameGraph { -class FlameGraph : public QQuickItem +class FLAMEGRAPH_EXPORT FlameGraph : public QQuickItem { Q_OBJECT Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) @@ -169,7 +102,6 @@ private: const QModelIndex &childIndex, qreal position, qreal size); }; -} // namespace Internal -} // namespace QmlProfiler +} // namespace FlameGraph -QML_DECLARE_TYPEINFO(QmlProfiler::Internal::FlameGraph, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPEINFO(FlameGraph::FlameGraph, QML_HAS_ATTACHED_PROPERTIES) diff --git a/src/libs/flamegraph/flamegraph.pro b/src/libs/flamegraph/flamegraph.pro new file mode 100644 index 0000000000..f9fb063e80 --- /dev/null +++ b/src/libs/flamegraph/flamegraph.pro @@ -0,0 +1,16 @@ +QT += qml quick +DEFINES += FLAMEGRAPH_LIBRARY + +include(../../qtcreatorlibrary.pri) + +SOURCES += \ + $$PWD/flamegraph.cpp + +HEADERS += \ + $$PWD/flamegraph.h \ + $$PWD/flamegraph_global.h \ + $$PWD/flamegraphattached.h + +RESOURCES += \ + $$PWD/qml/flamegraph.qrc + diff --git a/src/libs/flamegraph/flamegraph.qbs b/src/libs/flamegraph/flamegraph.qbs new file mode 100644 index 0000000000..2a44780532 --- /dev/null +++ b/src/libs/flamegraph/flamegraph.qbs @@ -0,0 +1,30 @@ +import qbs 1.0 + +import QtcLibrary + +Project { + name: "FlameGraph" + + QtcDevHeaders { } + + QtcLibrary { + Depends { name: "Qt"; submodules: ["qml", "quick", "gui"] } + + Group { + name: "General" + files: [ + "flamegraph.cpp", "flamegraph.h", + "flamegraph_global.h", + "flamegraphattached.h", + ] + } + + Group { + name: "QML" + prefix: "qml/" + files: ["flamegraph.qrc"] + } + + cpp.defines: base.concat("FLAMEGRAPH_LIBRARY") + } +} diff --git a/src/libs/flamegraph/flamegraph_dependencies.pri b/src/libs/flamegraph/flamegraph_dependencies.pri new file mode 100644 index 0000000000..6705c38c3d --- /dev/null +++ b/src/libs/flamegraph/flamegraph_dependencies.pri @@ -0,0 +1,2 @@ +QTC_LIB_NAME = FlameGraph + diff --git a/src/plugins/qmlprofiler/tests/flamegraph_test.h b/src/libs/flamegraph/flamegraph_global.h index bcfeb43b39..663c6abe7f 100644 --- a/src/plugins/qmlprofiler/tests/flamegraph_test.h +++ b/src/libs/flamegraph/flamegraph_global.h @@ -25,45 +25,10 @@ #pragma once -#include <qmlprofiler/flamegraph.h> -#include <QObject> -#include <QStandardItemModel> -#include <QQmlComponent> -#include <QQuickItem> +#include <QtGlobal> -namespace QmlProfiler { -namespace Internal { - -class DelegateObject : public QQuickItem -{ - Q_OBJECT -}; - -class DelegateComponent : public QQmlComponent -{ - Q_OBJECT -public: - QObject *create(QQmlContext *context) override; - QObject *beginCreate(QQmlContext *) override; - void completeCreate() override; -}; - -class FlameGraphTest : public QObject -{ - Q_OBJECT -private slots: - void initTestCase(); - void testRebuild(); - void cleanupTestCase(); - -private: - static const int sizeRole = Qt::UserRole + 1; - static const int dataRole = Qt::UserRole + 2; - FlameGraph flameGraph; - QStandardItemModel model; - DelegateComponent delegate; -}; - - -} // namespace Internal -} // namespace QmlProfiler +#if defined(FLAMEGRAPH_LIBRARY) +# define FLAMEGRAPH_EXPORT Q_DECL_EXPORT +#else +# define FLAMEGRAPH_EXPORT Q_DECL_IMPORT +#endif diff --git a/src/libs/flamegraph/flamegraphattached.h b/src/libs/flamegraph/flamegraphattached.h new file mode 100644 index 0000000000..00d5302b0b --- /dev/null +++ b/src/libs/flamegraph/flamegraphattached.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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 "flamegraph_global.h" +#include <QObject> +#include <QModelIndex> +#include <QVariant> + +namespace FlameGraph { + +class FLAMEGRAPH_EXPORT FlameGraphAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal relativeSize READ relativeSize WRITE setRelativeSize + NOTIFY relativeSizeChanged) + Q_PROPERTY(qreal relativePosition READ relativePosition WRITE setRelativePosition + NOTIFY relativePositionChanged) + Q_PROPERTY(bool dataValid READ isDataValid NOTIFY dataValidChanged) + +public: + FlameGraphAttached(QObject *parent = 0) : + QObject(parent), m_relativeSize(0), m_relativePosition(0) {} + + Q_INVOKABLE QVariant data(int role) const + { + return m_data.isValid() ? m_data.data(role) : QVariant(); + } + + bool isDataValid() const + { + return m_data.isValid(); + } + + qreal relativeSize() const + { + return m_relativeSize; + } + + void setRelativeSize(qreal relativeSize) + { + if (relativeSize != m_relativeSize) { + m_relativeSize = relativeSize; + emit relativeSizeChanged(); + } + } + + qreal relativePosition() const + { + return m_relativePosition; + } + + void setRelativePosition(qreal relativePosition) + { + if (relativePosition != m_relativePosition) { + m_relativePosition = relativePosition; + emit relativePositionChanged(); + } + } + + void setModelIndex(const QModelIndex &data) + { + if (data != m_data) { + bool validChanged = (data.isValid() != m_data.isValid()); + m_data = data; + if (validChanged) + emit dataValidChanged(); + emit dataChanged(); + } + } + +signals: + void dataChanged(); + void dataValidChanged(); + void relativeSizeChanged(); + void relativePositionChanged(); + +private: + QPersistentModelIndex m_data; + qreal m_relativeSize; + qreal m_relativePosition; +}; + +} // namespace FlameGraph diff --git a/src/libs/flamegraph/qml/FlameGraphDelegate.qml b/src/libs/flamegraph/qml/FlameGraphDelegate.qml new file mode 100644 index 0000000000..2cf115009d --- /dev/null +++ b/src/libs/flamegraph/qml/FlameGraphDelegate.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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. +** +****************************************************************************/ + +import QtQuick 2.0 +import FlameGraph 1.0 + +Item { + id: flamegraphItem + property color borderColor + property real borderWidth + property real itemHeight + property bool isSelected + property string text; + + signal mouseEntered + signal mouseExited + signal clicked + + property bool textVisible: width > 20 || isSelected + property int level: (parent.level !== undefined ? parent.level + 1 : -1) + + (itemHeight > 0 ? 1 : 0) + + height: parent === null ? 0 : parent.height - (level > 0 ? itemHeight : 0); + width: parent === null ? 0 : parent.width * FlameGraph.relativeSize + x: parent === null ? 0 : parent.width * FlameGraph.relativePosition + + Rectangle { + border.color: borderColor + border.width: borderWidth + color: Qt.hsla((level % 12) / 72, 0.9 + Math.random() / 10, + 0.45 + Math.random() / 10, 0.9 + Math.random() / 10); + height: itemHeight; + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + FlameGraphText { + id: text + visible: textVisible + anchors.fill: parent + anchors.margins: 5 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: flamegraphItem.text + elide: Text.ElideRight + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + font.bold: isSelected + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onEntered: flamegraphItem.mouseEntered() + onExited: flamegraphItem.mouseExited() + onClicked: flamegraphItem.clicked() + + } + } +} diff --git a/src/plugins/qmlprofiler/qml/FlameGraphDetails.qml b/src/libs/flamegraph/qml/FlameGraphDetails.qml index 2875d114af..2875d114af 100644 --- a/src/plugins/qmlprofiler/qml/FlameGraphDetails.qml +++ b/src/libs/flamegraph/qml/FlameGraphDetails.qml diff --git a/src/plugins/qmlprofiler/qml/FlameGraphText.qml b/src/libs/flamegraph/qml/FlameGraphText.qml index a989b39355..a989b39355 100644 --- a/src/plugins/qmlprofiler/qml/FlameGraphText.qml +++ b/src/libs/flamegraph/qml/FlameGraphText.qml diff --git a/src/libs/flamegraph/qml/flamegraph.qrc b/src/libs/flamegraph/qml/flamegraph.qrc new file mode 100644 index 0000000000..cb5c19a9eb --- /dev/null +++ b/src/libs/flamegraph/qml/flamegraph.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/flamegraph"> + <file>FlameGraphText.qml</file> + <file>FlameGraphDetails.qml</file> + <file>FlameGraphDelegate.qml</file> + </qresource> +</RCC> diff --git a/src/libs/libs.pro b/src/libs/libs.pro index ce90722356..7d8ed299cb 100644 --- a/src/libs/libs.pro +++ b/src/libs/libs.pro @@ -16,7 +16,8 @@ SUBDIRS = \ ssh \ timeline \ sqlite \ - clangbackendipc + clangbackendipc \ + flamegraph for(l, SUBDIRS) { QTC_LIB_DEPENDS = diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs index 1a49be9674..29eb744c1a 100644 --- a/src/libs/libs.qbs +++ b/src/libs/libs.qbs @@ -7,6 +7,7 @@ Project { "clangbackendipc/clangbackendipc.qbs", "cplusplus/cplusplus.qbs", "extensionsystem/extensionsystem.qbs", + "flamegraph/flamegraph.qbs", "glsl/glsl.qbs", "languageutils/languageutils.qbs", "modelinglib/modelinglib.qbs", diff --git a/src/plugins/qmlprofiler/flamegraphview.cpp b/src/plugins/qmlprofiler/flamegraphview.cpp index bb4a78a5df..b47031ad12 100644 --- a/src/plugins/qmlprofiler/flamegraphview.cpp +++ b/src/plugins/qmlprofiler/flamegraphview.cpp @@ -24,10 +24,12 @@ ****************************************************************************/ #include "flamegraphview.h" -#include "flamegraph.h" #include "qmlprofilerconstants.h" #include "qmlprofilertool.h" +#include <flamegraph/flamegraph.h> + +#include <QQmlEngine> #include <QQmlContext> #include <QVBoxLayout> #include <QMenu> @@ -44,14 +46,15 @@ FlameGraphView::FlameGraphView(QmlProfilerModelManager *manager, QWidget *parent // We cannot change this without breaking the settings. setObjectName(QStringLiteral("QmlProfilerFlamegraph")); - qmlRegisterType<FlameGraph>("FlameGraph", 1, 0, "FlameGraph"); - qmlRegisterUncreatableType<FlameGraphModel>("FlameGraphModel", 1, 0, "FlameGraphModel", + qmlRegisterType<FlameGraph::FlameGraph>("FlameGraph", 1, 0, "FlameGraph"); + qmlRegisterUncreatableType<FlameGraphModel>("QmlProfilerFlameGraphModel", 1, 0, + "QmlProfilerFlameGraphModel", QLatin1String("use the context property")); qmlRegisterUncreatableType<QAbstractItemModel>("AbstractItemModel", 1, 0, "AbstractItemModel", QLatin1String("only for Qt 5.4")); m_content->rootContext()->setContextProperty(QStringLiteral("flameGraphModel"), m_model); - m_content->setSource(QUrl(QStringLiteral("qrc:/qmlprofiler/FlameGraphView.qml"))); + m_content->setSource(QUrl(QStringLiteral("qrc:/qmlprofiler/QmlProfilerFlameGraphView.qml"))); m_content->setClearColor(QColor(0xdc, 0xdc, 0xdc)); m_content->setResizeMode(QQuickWidget::SizeRootObjectToView); diff --git a/src/plugins/qmlprofiler/qml/FlameGraphView.qml b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml index b1df306eec..e9e351b57c 100644 --- a/src/plugins/qmlprofiler/qml/FlameGraphView.qml +++ b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml @@ -26,7 +26,8 @@ import QtQuick 2.0 import QtQuick.Controls 1.3 import FlameGraph 1.0 -import FlameGraphModel 1.0 +import QmlProfilerFlameGraphModel 1.0 +import "../flamegraph/" ScrollView { id: root @@ -45,7 +46,6 @@ ScrollView { FlameGraph { property int itemHeight: Math.max(30, flickable.height / depth) - property int level: -1 property color blue: "blue" property color blue1: Qt.lighter(blue) property color blue2: Qt.rgba(0.375, 0, 1, 1) @@ -59,21 +59,42 @@ ScrollView { width: parent.width height: depth * itemHeight model: flameGraphModel - sizeRole: FlameGraphModel.DurationRole + sizeRole: QmlProfilerFlameGraphModel.DurationRole sizeThreshold: 0.002 maximumDepth: 25 y: flickable.height > height ? flickable.height - height : 0 - delegate: Item { + delegate: FlameGraphDelegate { id: flamegraphItem - property int typeId: FlameGraph.data(FlameGraphModel.TypeIdRole) || -1 + property int typeId: FlameGraph.data(QmlProfilerFlameGraphModel.TypeIdRole) || -1 property bool isBindingLoop: parent.checkBindingLoop(typeId) - property int level: parent.level + (rangeTypeVisible ? 1 : 0) - property bool isSelected: typeId !== -1 && typeId === root.selectedTypeId - && rangeTypeVisible property bool rangeTypeVisible: - root.visibleRangeTypes & (1 << FlameGraph.data(FlameGraphModel.RangeTypeRole)) + root.visibleRangeTypes & (1 << FlameGraph.data(QmlProfilerFlameGraphModel.RangeTypeRole)) + + itemHeight: rangeTypeVisible ? flamegraph.itemHeight : 0 + isSelected: typeId !== -1 && typeId === root.selectedTypeId && rangeTypeVisible + + borderColor: { + if (isSelected) + return flamegraph.blue2; + else if (tooltip.hoveredNode === flamegraphItem) + return flamegraph.blue1; + else if (note() !== "" || isBindingLoop) + return flamegraph.orange; + 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 || @@ -93,10 +114,45 @@ ScrollView { } } + function buildText() { + if (!FlameGraph.dataValid) + return "<others>"; + + return FlameGraph.data(QmlProfilerFlameGraphModel.DetailsRole) + " (" + + FlameGraph.data(QmlProfilerFlameGraphModel.TypeRole) + ", " + + FlameGraph.data(QmlProfilerFlameGraphModel.TimeInPercentRole) + "%)"; + } + text: textVisible ? buildText() : "" + FlameGraph.onDataChanged: if (textVisible) text = buildText(); + + onMouseEntered: { + tooltip.hoveredNode = flamegraphItem; + } + + onMouseExited: { + if (tooltip.hoveredNode === flamegraphItem) + tooltip.hoveredNode = null; + } + + onClicked: { + if (flamegraphItem.FlameGraph.dataValid) { + tooltip.selectedNode = flamegraphItem; + root.typeSelected(flamegraphItem.FlameGraph.data( + QmlProfilerFlameGraphModel.TypeIdRole)); + root.gotoSourceLocation( + flamegraphItem.FlameGraph.data( + QmlProfilerFlameGraphModel.FilenameRole), + flamegraphItem.FlameGraph.data( + QmlProfilerFlameGraphModel.LineRole), + flamegraphItem.FlameGraph.data( + QmlProfilerFlameGraphModel.ColumnRole)); + } + } + // 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(FlameGraphModel.TypeRole) || ""; } - function note() { return FlameGraph.data(FlameGraphModel.NoteRole) || ""; } + function title() { return FlameGraph.data(QmlProfilerFlameGraphModel.TypeRole) || ""; } + function note() { return FlameGraph.data(QmlProfilerFlameGraphModel.NoteRole) || ""; } function details() { var model = []; function addDetail(name, index, format) { @@ -130,106 +186,17 @@ ScrollView { model.push(qsTr("Details")); model.push(qsTr("Various Events")); } else { - addDetail(qsTr("Details"), FlameGraphModel.DetailsRole, noop); - addDetail(qsTr("Type"), FlameGraphModel.TypeRole, noop); - addDetail(qsTr("Calls"), FlameGraphModel.CallCountRole, noop); - addDetail(qsTr("Total Time"), FlameGraphModel.DurationRole, printTime); - addDetail(qsTr("Mean Time"), FlameGraphModel.TimePerCallRole, printTime); - addDetail(qsTr("In Percent"), FlameGraphModel.TimeInPercentRole, + addDetail(qsTr("Details"), QmlProfilerFlameGraphModel.DetailsRole, noop); + addDetail(qsTr("Type"), QmlProfilerFlameGraphModel.TypeRole, noop); + addDetail(qsTr("Calls"), QmlProfilerFlameGraphModel.CallCountRole, noop); + addDetail(qsTr("Total Time"), QmlProfilerFlameGraphModel.DurationRole, printTime); + addDetail(qsTr("Mean Time"), QmlProfilerFlameGraphModel.TimePerCallRole, printTime); + addDetail(qsTr("In Percent"), QmlProfilerFlameGraphModel.TimeInPercentRole, addPercent); - addDetail(qsTr("Location"), FlameGraphModel.LocationRole, noop); + addDetail(qsTr("Location"), QmlProfilerFlameGraphModel.LocationRole, noop); } return model; } - - Rectangle { - border.color: { - if (flamegraphItem.isSelected) - return flamegraph.blue2; - else if (tooltip.hoveredNode === flamegraphItem) - return flamegraph.blue1; - else if (flamegraphItem.note() !== "" || flamegraphItem.isBindingLoop) - return flamegraph.orange; - else - return flamegraph.grey1; - } - border.width: { - if (tooltip.hoveredNode === flamegraphItem || - tooltip.selectedNode === flamegraphItem) { - return 2; - } else if (flamegraphItem.note() !== "") { - return 3; - } else { - return 1; - } - } - color: Qt.hsla((level % 12) / 72, 0.9 + Math.random() / 10, - 0.45 + Math.random() / 10, 0.9 + Math.random() / 10); - height: flamegraphItem.rangeTypeVisible ? flamegraph.itemHeight : 0; - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - - FlameGraphText { - id: text - visible: width > 20 || flamegraphItem === tooltip.selectedNode - anchors.fill: parent - anchors.margins: 5 - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: visible ? buildText() : "" - elide: Text.ElideRight - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - font.bold: flamegraphItem === tooltip.selectedNode - - function buildText() { - if (!flamegraphItem.FlameGraph.dataValid) - return "<others>"; - - return flamegraphItem.FlameGraph.data(FlameGraphModel.DetailsRole) - + " (" - + flamegraphItem.FlameGraph.data(FlameGraphModel.TypeRole) - + ", " - + flamegraphItem.FlameGraph.data( - FlameGraphModel.TimeInPercentRole) + "%)"; - } - } - - MouseArea { - anchors.fill: parent - hoverEnabled: true - - onEntered: { - tooltip.hoveredNode = flamegraphItem; - } - - onExited: { - if (tooltip.hoveredNode === flamegraphItem) - tooltip.hoveredNode = null; - } - - onClicked: { - if (flamegraphItem.FlameGraph.dataValid) { - tooltip.selectedNode = flamegraphItem; - root.typeSelected(flamegraphItem.FlameGraph.data( - FlameGraphModel.TypeIdRole)); - root.gotoSourceLocation( - flamegraphItem.FlameGraph.data( - FlameGraphModel.FilenameRole), - flamegraphItem.FlameGraph.data( - FlameGraphModel.LineRole), - flamegraphItem.FlameGraph.data( - FlameGraphModel.ColumnRole)); - } - } - } - } - - FlameGraph.onDataChanged: if (text.visible) text.text = text.buildText(); - - height: flamegraph.height - level * flamegraph.itemHeight; - width: parent === null ? flamegraph.width : parent.width * FlameGraph.relativeSize - x: parent === null ? 0 : parent.width * FlameGraph.relativePosition } } diff --git a/src/plugins/qmlprofiler/qml/qmlprofiler.qrc b/src/plugins/qmlprofiler/qml/qmlprofiler.qrc index e9d17c44bf..daf9a34b48 100644 --- a/src/plugins/qmlprofiler/qml/qmlprofiler.qrc +++ b/src/plugins/qmlprofiler/qml/qmlprofiler.qrc @@ -2,8 +2,6 @@ <qresource prefix="/qmlprofiler"> <file>bindingloops.vert</file> <file>bindingloops.frag</file> - <file>FlameGraphView.qml</file> - <file>FlameGraphText.qml</file> - <file>FlameGraphDetails.qml</file> + <file>QmlProfilerFlameGraphView.qml</file> </qresource> </RCC> diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro index 9fffbe27fb..154e348610 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofiler/qmlprofiler.pro @@ -6,7 +6,6 @@ include(../../qtcreatorplugin.pri) SOURCES += \ debugmessagesmodel.cpp \ - flamegraph.cpp \ flamegraphmodel.cpp \ flamegraphview.cpp \ inputeventsmodel.cpp \ @@ -48,7 +47,6 @@ SOURCES += \ HEADERS += \ debugmessagesmodel.h \ - flamegraph.h \ flamegraphmodel.h \ flamegraphview.h \ inputeventsmodel.h \ diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs index d923983c36..c870d3096f 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.qbs +++ b/src/plugins/qmlprofiler/qmlprofiler.qbs @@ -4,6 +4,8 @@ QtcPlugin { name: "QmlProfiler" Depends { name: "Qt"; submodules: ["widgets", "network", "quick", "quickwidgets"] } + + Depends { name: "FlameGraph" } Depends { name: "QmlJS" } Depends { name: "QmlDebug" } Depends { name: "Utils" } @@ -19,7 +21,6 @@ QtcPlugin { name: "General" files: [ "debugmessagesmodel.cpp", "debugmessagesmodel.h", - "flamegraph.cpp", "flamegraph.h", "flamegraphmodel.cpp", "flamegraphmodel.h", "flamegraphview.cpp", "flamegraphview.h", "inputeventsmodel.cpp", "inputeventsmodel.h", @@ -77,7 +78,6 @@ QtcPlugin { prefix: "tests/" files: [ "debugmessagesmodel_test.cpp", "debugmessagesmodel_test.h", - "flamegraph_test.cpp", "flamegraph_test.h", "flamegraphmodel_test.cpp", "flamegraphmodel_test.h", "flamegraphview_test.cpp", "flamegraphview_test.h", "inputeventsmodel_test.cpp", "inputeventsmodel_test.h", diff --git a/src/plugins/qmlprofiler/qmlprofiler_dependencies.pri b/src/plugins/qmlprofiler/qmlprofiler_dependencies.pri index d029cdabf6..850352458a 100644 --- a/src/plugins/qmlprofiler/qmlprofiler_dependencies.pri +++ b/src/plugins/qmlprofiler/qmlprofiler_dependencies.pri @@ -1,6 +1,7 @@ QTC_PLUGIN_NAME = QmlProfiler QTC_LIB_DEPENDS += \ extensionsystem \ + flamegraph \ qmldebug \ qmljs \ timeline \ diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp index ae489ce0b9..4f8450b612 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -32,7 +32,6 @@ #ifdef WITH_TESTS #include "tests/debugmessagesmodel_test.h" -#include "tests/flamegraph_test.h" #include "tests/flamegraphmodel_test.h" #include "tests/flamegraphview_test.h" #include "tests/inputeventsmodel_test.h" @@ -102,7 +101,6 @@ QList<QObject *> QmlProfiler::Internal::QmlProfilerPlugin::createTestObjects() c QList<QObject *> tests; #ifdef WITH_TESTS tests << new DebugMessagesModelTest; - tests << new FlameGraphTest; tests << new FlameGraphModelTest; tests << new FlameGraphViewTest; tests << new InputEventsModelTest; diff --git a/src/plugins/qmlprofiler/tests/tests.pri b/src/plugins/qmlprofiler/tests/tests.pri index db4ed15007..8cbefe4b76 100644 --- a/src/plugins/qmlprofiler/tests/tests.pri +++ b/src/plugins/qmlprofiler/tests/tests.pri @@ -1,6 +1,5 @@ SOURCES += \ $$PWD/debugmessagesmodel_test.cpp \ - $$PWD/flamegraph_test.cpp \ $$PWD/flamegraphmodel_test.cpp \ $$PWD/flamegraphview_test.cpp \ $$PWD/inputeventsmodel_test.cpp \ @@ -18,7 +17,6 @@ SOURCES += \ HEADERS += \ $$PWD/debugmessagesmodel_test.h \ - $$PWD/flamegraph_test.h \ $$PWD/flamegraphmodel_test.h \ $$PWD/flamegraphview_test.h \ $$PWD/inputeventsmodel_test.h \ diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index af26b3319d..585245d354 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -24,4 +24,4 @@ SUBDIRS += \ valgrind qtHaveModule(qml): SUBDIRS += qml -qtHaveModule(quick): SUBDIRS += timeline +qtHaveModule(quick): SUBDIRS += flamegraph timeline diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs index 6b1b308442..03b754cd50 100644 --- a/tests/auto/auto.qbs +++ b/tests/auto/auto.qbs @@ -14,6 +14,7 @@ Project { "extensionsystem/extensionsystem.qbs", "externaltool/externaltool.qbs", "filesearch/filesearch.qbs", + "flamegraph/flamegraph.qbs", "generichighlighter/generichighlighter.qbs", "json/json.qbs", "profilewriter/profilewriter.qbs", diff --git a/tests/auto/flamegraph/flamegraph.pro b/tests/auto/flamegraph/flamegraph.pro new file mode 100644 index 0000000000..6ea151f4c9 --- /dev/null +++ b/tests/auto/flamegraph/flamegraph.pro @@ -0,0 +1,5 @@ +QTC_LIB_DEPENDS += flamegraph +include(../qttest.pri) + +QT += quick +SOURCES += tst_flamegraph.cpp diff --git a/tests/auto/flamegraph/flamegraph.qbs b/tests/auto/flamegraph/flamegraph.qbs new file mode 100644 index 0000000000..de00698243 --- /dev/null +++ b/tests/auto/flamegraph/flamegraph.qbs @@ -0,0 +1,9 @@ +import qbs + +QtcAutotest { + name: "FlameGraph autotest" + Depends { name: "FlameGraph" } + Depends { name: "Qt.quick" } + Depends { name: "Qt.gui" } + files: "tst_flamegraph.cpp" +} diff --git a/src/plugins/qmlprofiler/tests/flamegraph_test.cpp b/tests/auto/flamegraph/tst_flamegraph.cpp index 001aaf60f9..4e249887b2 100644 --- a/src/plugins/qmlprofiler/tests/flamegraph_test.cpp +++ b/tests/auto/flamegraph/tst_flamegraph.cpp @@ -23,14 +23,46 @@ ** ****************************************************************************/ -#include "flamegraph_test.h" +#include <flamegraph/flamegraph.h> +#include <flamegraph/flamegraphattached.h> +#include <QObject> +#include <QStandardItemModel> +#include <QQmlComponent> +#include <QQuickItem> #include <QtTest> #include <QQuickItem> -namespace QmlProfiler { -namespace Internal { +class DelegateObject : public QQuickItem +{ + Q_OBJECT +}; + +class DelegateComponent : public QQmlComponent +{ + Q_OBJECT +public: + QObject *create(QQmlContext *context) override; + QObject *beginCreate(QQmlContext *) override; + void completeCreate() override; +}; + +class tst_FlameGraph : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void testRebuild(); + void cleanupTestCase(); + +private: + static const int sizeRole = Qt::UserRole + 1; + static const int dataRole = Qt::UserRole + 2; + FlameGraph::FlameGraph flameGraph; + QStandardItemModel model; + DelegateComponent delegate; +}; -void FlameGraphTest::initTestCase() +void tst_FlameGraph::initTestCase() { flameGraph.setDelegate(&delegate); flameGraph.setModel(&model); @@ -45,7 +77,7 @@ void FlameGraphTest::initTestCase() QCOMPARE(flameGraph.sizeThreshold(), 0.01); } -void FlameGraphTest::testRebuild() +void tst_FlameGraph::testRebuild() { flameGraph.setModel(nullptr); qreal sum = 0; @@ -75,7 +107,9 @@ void FlameGraphTest::testRebuild() qreal i = 0; qreal position = 0; foreach (QQuickItem *child, flameGraph.childItems()) { - FlameGraphAttached *attached = FlameGraph::qmlAttachedProperties(child); + FlameGraph::FlameGraphAttached *attached = + FlameGraph::FlameGraph::qmlAttachedProperties(child); + QVERIFY(attached); QCOMPARE(attached->relativeSize(), (++i) / sum); QCOMPARE(attached->relativePosition(), position / sum); QCOMPARE(attached->data(dataRole).toInt(), 100 / static_cast<int>(i)); @@ -83,12 +117,15 @@ void FlameGraphTest::testRebuild() qreal j = 0; foreach (QQuickItem *grandchild, child->childItems()) { - FlameGraphAttached *attached2 = FlameGraph::qmlAttachedProperties(grandchild); + FlameGraph::FlameGraphAttached *attached2 = + FlameGraph::FlameGraph::qmlAttachedProperties(grandchild); + QVERIFY(attached2); QCOMPARE(attached2->relativeSize(), 1.0 / i); QCOMPARE(attached2->relativePosition(), (j++) / i); QCOMPARE(grandchild->childItems().count(), 1); - FlameGraphAttached *skipped = - FlameGraph::qmlAttachedProperties(grandchild->childItems()[0]); + FlameGraph::FlameGraphAttached *skipped = + FlameGraph::FlameGraph::qmlAttachedProperties(grandchild->childItems()[0]); + QVERIFY(skipped); QCOMPARE(skipped->relativePosition(), 0.0); QCOMPARE(skipped->relativeSize(), 0.001 * 10); } @@ -98,7 +135,7 @@ void FlameGraphTest::testRebuild() QCOMPARE(i, 9.0); } -void FlameGraphTest::cleanupTestCase() +void tst_FlameGraph::cleanupTestCase() { } @@ -119,5 +156,6 @@ void DelegateComponent::completeCreate() { } -} // namespace Internal -} // namespace QmlProfiler +QTEST_MAIN(tst_FlameGraph) + +#include "tst_flamegraph.moc" |