Commit 39295548 authored by Ulf Hermann's avatar Ulf Hermann

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's avatarChristian Kandeler <christian.kandeler@qt.io>
parent 97a465ae
......@@ -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
......@@ -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)
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
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")
}
}
......@@ -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
/****************************************************************************
**
** 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
/****************************************************************************
**
** 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()
}
}
}
<RCC>
<qresource prefix="/flamegraph">
<file>FlameGraphText.qml</file>
<file>FlameGraphDetails.qml</file>
<file>FlameGraphDelegate.qml</file>
</qresource>
</RCC>
......@@ -16,7 +16,8 @@ SUBDIRS = \
ssh \
timeline \
sqlite \
clangbackendipc
clangbackendipc \
flamegraph
for(l, SUBDIRS) {
QTC_LIB_DEPENDS =
......
......@@ -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",
......
......@@ -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);
......
......@@ -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>
......@@ -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 \
......
......@@ -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",
......
QTC_PLUGIN_NAME = QmlProfiler
QTC_LIB_DEPENDS += \
extensionsystem \
flamegraph \
qmldebug \
qmljs \
timeline \
......
......@@ -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;
......
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 \
......
......@@ -24,4 +24,4 @@ SUBDIRS += \
valgrind
qtHaveModule(qml): SUBDIRS += qml
qtHaveModule(quick): SUBDIRS += timeline
qtHaveModule(quick): SUBDIRS += flamegraph timeline
......@@ -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",
......
QTC_LIB_DEPENDS += flamegraph
include(../qttest.pri)
QT += quick
SOURCES += tst_flamegraph.cpp
import qbs
QtcAutotest {
name: "FlameGraph autotest"
Depends { name: "FlameGraph" }
Depends { name: "Qt.quick" }
Depends { name: "Qt.gui" }
files: "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;